Search code examples
flutterflame

State Machine into Flame from Flutter?


just got a Question about the Flame Engine from Flutter.

Does someone know, how i can implement a Game State Machine into Flame? I tried something similar like you see in the code bellow, but when the GameState changes after a certain amount of time, the screen gets black.

Maybe someone of you had the same problem.

Greetz

import 'dart:async';

import 'package:fit_fighter/constants/globals.dart';

import 'package:fit_fighter/scene/dumbell_scene.dart';
import 'package:fit_fighter/scene/enemy_scene.dart';

import 'package:flame/components.dart';
import 'package:flame/game.dart';

import 'package:flame_audio/flame_audio.dart';
import 'package:flutter/widgets.dart';

enum GameState { dumbell, enemy }

class FitFighterGame extends FlameGame
    with HasDraggables, HasCollisionDetection {
  int score = 0;
  late Timer timer;
  int remainingTime = 5;
  late PositionComponent _gameInstance;
  late bool sceneLoaded = false;

  late GameState currentGameState;

  @override
  Future<void> onLoad() async {
    super.onLoad();

    FlameAudio.audioCache.loadAll([
      Globals.dumbbellSound,
      Globals.virusSound,
      Globals.vaccineSound,
      Globals.proteinSound,
    ]);

    currentGameState = GameState.dumbell;

    switch (currentGameState) {
      case GameState.dumbell:
        {
          _gameInstance = DumbbellScene();
          add(_gameInstance);
          break;
        }
      case GameState.enemy:
        {
          break;
        }
    }
  }

  @override
  void update(double dt) async {
    super.update(dt);

    switch (currentGameState) {
      case GameState.dumbell:
        {
          (_gameInstance as DumbbellScene).myUpdate(dt);
          break;
        }
      case GameState.enemy:
        {
          if (!sceneLoaded) {
            _gameInstance.removeFromParent();
            _gameInstance = EnemyScene();
            add(_gameInstance);
            sceneLoaded = true;
            print("Scene Load");
          }
          break;
        }
    }
  }

  @override
  void render(Canvas canvas) {
    // TODO: implement render

    switch (currentGameState) {
      case GameState.dumbell:
        {
          break;
        }
      case GameState.enemy:
        {
          (_gameInstance as EnemyScene).myRender(canvas);
          break;
        }
    }
    super.render(canvas);
  }
}

Expected, that the change of the GameState would call a new Scene in Flame. For some reason the Screen beccomes black and doesn't show the new scene.


Solution

  • You shouldn't manually call render or update methods like you're doing, override the render and update method in your components and put your logic and rendering code in there.

    When you add a component that means that the game engine will call update and render automatically for that component.

    Most of the time you never have to override render directly in your game class.

    So when your state changes, just remove the old _gameInstance and add the new scene. You can also handle this with the RouterComponent.