Como utilizar un Sprite Sheet Componente Flutter con Flame 15 - Juegos 2D animados

Para generar un Sprite Sheet animado, tenemos que realizar varias operaciones que van, desde cargar una imagen sprite, hasta referenciarla en el proyecto; cada estado del sprite, tiene que tener un tamano definido; para ello, usamos un par de propiedades:

late double spriteSheetWidth = 680.0, spriteSheetHeight = 472.0;

Es importante notar que, debes de especificar el tamaño acorde al sprite que estés utilizando.

Cargamos el sprite sheet:

var spriteImages = await Flame.images.load('dino.png');

Y definimos el spriteSheet para que pueda ser manipulado mediante una propiedad; es en este paso que, utilizamos las dimensiones individuales de cada estado:

final spriteSheet = SpriteSheet(image: spriteImages, srcSize: Vector2(spriteSheetWidth, spriteSheetHeight));

Finalmente, ya es posible consultar de manera individual cada posición de uno de los pasos del sprite sheet:

sprite = spriteSheet.getSprite(1, 1);

Una animacion, no es mas que una lista de Sprite, por lo tanto, si formas un sprite list, puedes utilizarlas en el componente correspondiente de Flame para manejar los sprite animados; por ejemplo:

class PlayeSpriteSheetComponent extends SpriteAnimationComponent {
  late double screenWidth, screenHeight, centerX, centerY;
  final double spriteWidth = 512.0, spriteHeight = 512.0;

  late double spriteSheetWidth = 680.0, spriteSheetHeight = 472.0;

  late SpriteAnimation dinoAnimation;

  @override
  Future<void> onLoad() async {
    super.onLoad();
    screenWidth = MediaQueryData.fromWindow(window).size.width;
    screenHeight = MediaQueryData.fromWindow(window).size.height;

    centerX = (screenWidth / 2) - (spriteSheetWidth / 2);
    centerY = (screenHeight / 2) - (spriteSheetHeight / 2);

    var spriteImages = await Flame.images.load('dino.png');

    final spriteSheet = SpriteSheet(
        image: spriteImages,
        srcSize: Vector2(spriteSheetWidth, spriteSheetHeight));

    //sprite = spriteSheet.getSprite(1, 1);
    position = Vector2(centerX, centerY);
    size = Vector2(spriteSheetWidth, spriteSheetHeight);
    //sprite = await Sprite.load('Sprite.png');

    animation = [spriteSheet.getSprite(1, 1),spriteSheet.getSprite(1, 2)];
  }
}

Animacione de sprite con SpriteAnimationComponent

En Flame, tenemos un componente para generar las animaciones en base a un Sprite Sheet como:

En el curso y libro de Flame para crear juegos en 2D, creamos una función, con la cual, podemos generar facilmente un listado animado listo para usar en un SpriteAnimation; simplemente vemos el sprite sheet como una matriz y definimos la posición inicial y final, ademas del tamaño del sprite sheet; entre otras opciones:

 

extension CreateAnimationByLimit on SpriteSheet {
  SpriteAnimation createAnimationByLimit({
    required int xInit,
    required int yInit,
    required int step,
    required int sizeX,
    required double stepTime,
    bool loop = true,
  }) {
    final List<Sprite> spriteList = [];


    int x = xInit;
    int y = yInit - 1;


    for (var i = 0; i < step; i++) {
      if (y >= sizeX) {
        y = 0;
        x++;
      } else {
        y++;
      }


      spriteList.add(getSprite(x, y));
      // print(x.toString() + ' ' + y.toString());
    }


    return SpriteAnimation.spriteList(spriteList,
        stepTime: stepTime, loop: loop);
  }
}

SpriteAnimationComponent: Pruebas

Para esta función, necesitaremos los siguientes parámetros:

  1. Paso inicial en X (por ejemplo (3,0)).
  2. Paso inicial en Y (por ejemplo (3,0)).
  3. Cantidad de pasos (por ejemplo el valor de 6 corresponde a qué queremos 6 sprites).
  4. El ancho de la matriz (en la imagen de dino.png la matriz de sprite sería de 3x3 por lo tanto, el ancho sería de 3).
  5. Velocidad de la animación.
  6. Si se va a ejecutar en bucle.

Teniendo esto en cuenta, crearemos la siguiente función de extensión que extienda a la clase SpriteSheet:

lib/components/player_sprite_sheet_component.dart

 

extension CreateAnimationByLimit on SpriteSheet {
  SpriteAnimation createAnimationByLimit({
    required int xInit,
    required int yInit,
    required int step,
    required int sizeX,
    required double stepTime,
    bool loop = true,
  }) {
    final List<Sprite> spriteList = [];

    int x = xInit;
    int y = yInit - 1;

    for (var i = 0; i < step; i++) {
      if (y >= sizeX) {
        y = 0;
        x++;
      } else {
        y++;
      }

      spriteList.add(getSprite(x, y));
     // print(x.toString() + ' ' + y.toString());
    }

    return SpriteAnimation.spriteList(spriteList,
        stepTime: stepTime, loop: loop);
  }
}

Lo más importante es notar el bloque del for en la cual, recorremos la matriz de los sprite justamente como en los ejemplos explicados anteriormente; con esta lista de sprite, generamos la animación utilizando SpriteAnimation.spriteList().

 

Con el codigo anterior definido en la clase PlayeSpriteSheetComponent  definimos la propiedad de animation, usando la función llamada createAnimationByLimit() que creamos anteriormente, el resto de propiedades, son las mismas empleadas en cualquier otro componente de tipo SpriteComponent o PositionComponent que presentamos en anteriores entregas; propiedades como size, position son necesarias para indicar el tamaño y posicion del sprite.

 

Recuerda que este material forma parte de mi curso completo sobre Flame Flutter y libro sobre el desarrollo de juegos en 2D con 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.