How to use a Sprite Sheet Flutter Component with Flame 15 - Animated 2D Games

To generate an animated Sprite Sheet, we have to perform various operations that range from loading a sprite image to referencing it in the project; each state of the sprite has to have a defined size; to do this, we use a couple of properties:

late double spriteSheetWidth = 680.0, spriteSheetHeight = 472.0;

It is important to note that you must specify the size according to the sprite you are using.

We load the sprite sheet:

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

And we define the spriteSheet so that it can be manipulated through a property; It is in this step that we use the individual dimensions of each state:

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

Finally, it is now possible to consult each position of one of the steps of the sprite sheet individually:

sprite = spriteSheet.getSprite(1, 1);

An animation is nothing more than a sprite list, therefore, if you create a sprite list, you can use it in the corresponding Flame component to manage the animated sprites; for example:

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)];
  }
}

Sprite animation with Sprite Animation Component

In Flame, we have a component to generate the animations based on a Sprite Sheet like:

In Flame's course and book to create 2D games, we created a function, with which, we can easily generate an animated list ready to use in a SpriteAnimation; we simply see the sprite sheet as an array and define the start and end position, as well as the size of the sprite sheet; among other options:

 

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: Tests

For this function, we will need the following parameters:

  1. Initial step at X (for example (3,0)).
  2. Initial step at Y (for example (3,0)).
  3. Number of steps (for example, the value of 6 corresponds to what we want 6 sprites).
  4. The width of the array (in the dino.png image the sprite matrix would be 3x3 so the width would be 3).
  5. Animation speed.
  6. If it is to be executed in a loop.

With this in mind, we'll create the following extension function that extends the SpriteSheet class:

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);
  }
}

The most important thing is to note the for block in which we traverse the sprite array just as in the examples explained above; with this sprite list, we generate the animation using SpriteAnimation.spriteList().

With the previous code defined in the PlayeSpriteSheetComponent class, we define the animation property, using the function called createAnimationByLimit() that we created previously, the rest of the properties are the same used in any other SpriteComponent or PositionComponent type component that we presented in previous examples; properties like size, position are needed to indicate the size and position of the sprite.

Remember that this material is part of my complete course on Flame Flutter and book on developing 2D games with Flame.

- Andrés Cruz

En español
Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.