SpriteAnimationTicker en Flame para controlar una animación en Flutter

Un AnimationTicker es una técnica utilizada en varias bibliotecas de animación y permiten controlar una animación; en el caso de Flame, también permiten escuchar los estados de la animación; por ejemplo, cuando se completa la animación:

animationTicker.onComplete = () {
    ***
  }
};
Cuando se ejecuta un frame de la animación:
animationTicker.onFrame = (index) {
  ***
  }
};

Todo esto se hace mediante la clase de SpriteAnimationTicker de Flame; para el juego que estamos implementando, es necesario conocer cuando acaba la animación de "muriendo" para reiniciar la partida; para esto, podemos emplear cualquiera de los listeners mostrados anteriormente.

Primero, necesitamos inicializar el ticker:

lib/components/player_component.dart

class PlayerComponent extends Character {
  ***
  late SpriteAnimationTicker deadAnimationTicker;

  @override
  void onLoad() async {
    ***
    deadAnimationTicker = deadAnimation.createTicker();
  }

  @override
  void update(double dt) {
    ***
    deadAnimationTicker.update(dt);
    super.update(dt);
  }
}

Con la función de createTicker() creamos un ticker (SpriteAnimationTicker) sobre la animación que vamos a controlador; en el caso del juego que estamos implementando, nos interesa es detectar cuando termina la animación de muriendo, que se va a ejecutar únicamente cuando el player se queda sin vidas y al terminar la animación, se reinicia el nivel. La razón de que es inicializado la propiedad de deadAnimationTicker en el onLoad() y no cuando se emplee la animación de deadAnimation (al quedarse el player sin vidas) es que es necesario actualizar el ticker en la función de upload() según el ciclo de vida del ticker:

deadAnimationTicker.update(dt)

Con el ticket, se crea un listener para detectar cuando termina la animación de ejecutarse; para ello, podemos ejecutar el listener de onComplete():

deadAnimationTicker.onComplete = () {
  // TODO
};

O el de onFrame(), que se ejecuta por cada Frame, pero, preguntando si el frame actual es el último:

deadAnimationTicker.onFrame = (index) {
  if (deadAnimationTicker.isLastFrame) {
    // TODO
  }
};

Finalmente, el código completo queda como:

lib/components/player_component.dart

class PlayerComponent extends Character {
  void reset({bool dead = false}) async {
    game.overlays.remove('Statistics');
    game.overlays.add('Statistics');
    velocity = Vector2.all(0);
    game.paused = false;
    blockPlayer = true;
    inviciblePlayer = true;
    movementType = MovementType.idle;
    if (dead) {
      animation = deadAnimation;

      deadAnimationTicker = deadAnimation.createTicker();
      deadAnimationTicker.onFrame = (index) {
        // print("-----" + index.toString());
        if (deadAnimationTicker.isLastFrame) {
          animation = idleAnimation;
          position =
              Vector2(spriteSheetWidth / 4, mapSize.y - spriteSheetHeight);
        }
      };

      deadAnimationTicker.onComplete = () {
        if (animation == deadAnimation) {
          animation = idleAnimation;
          position =
              Vector2(spriteSheetWidth / 4, mapSize.y - spriteSheetHeight);
        }
      };
    } else {
      animation = idleAnimation;
      position = Vector2(spriteSheetWidth / 4, mapSize.y - spriteSheetHeight);
      size = Vector2(spriteSheetWidth / 4, spriteSheetHeight / 4);
    }
    game.colisionMeteors = 0;
    game.addConsumibles();

    //position = Vector2(spriteSheetWidth / 4, 0);
  }
}

Este material forma parte de mi curso y libro completo sobre el desarrollo de juegos en 2D con Flutter y Flame.

- Andrés Cruz

In english
Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.