How to create sprite sheets & animations for Flame Engine

Andreas Löw
Last updated:
GitHub
How to create sprite sheets & animations for Flame Engine

Who is this tutorial for?

This tutorial is for anyone who wants to use the Flame Engine with sprite sheets. It'll cover the basics of adding sprites and animations to a scene, as well as some tricks like packing sprite sheets, and speeding up the loading times.

This is the scene you are going to create in this tutorial:

Flame Engine Sprite Sheet Demo

Creating a simple Flame game scene

Downloading the assets

Download the sprites and background image from here: assets.zip. You can use these assets for learning purposes. Please don't publish them on your own blog or tutorial, or use them in your own game or app without my written consent.

Extract the contents into a folder called assets inside your Flutter project. The archive contains the graphics you see in the demo above:

  • background.png
  • capguy
    • turn_01.png ... turn_06.png
    • walk_01.png ... walk_08.png

We also offer you the full source code for this tutorial on GitHub.

Installing Flame

If you haven't already, start by setting up a new Flutter project:

flutter create my_game
cd my_game

Now, add flame and flame_texturepacker to your project:

flutter pub add flame flame_texturepacker

This adds the dependencies to pubspec.yaml and runs flutter pub get.

Next, you need to configure the assets. Open your pubspec.yaml file and add the following assets section to the flutter configuration. Make sure to keep the indentation correct and don't forget the trailing slash:

pubspec.yaml
flutter:
  assets:
    - assets/images/sprites/
    - assets/images/spritesheets/

Getting started with a simple scene

Start by creating a lib/main.dart file with this content:

lib/main.dart
import 'package:flame/game.dart';
import 'package:flame/components.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(GameWidget(game: MyGame()));
}

class MyGame extends FlameGame {
  @override
  Future<void> onLoad() async {
    // load the background image
    // Note: Flame's base directory when loading images is assets/images
    final background = await loadSprite('sprites/background.png');

    // add background as a component
    add(SpriteComponent(sprite: background));
  }
}

This sets up a basic Flame game and loads the background image.

Testing the scene

Run the application on your preferred device or simulator:

flutter run

You should see the background of the game scene:

Background scene of the Flame sprite sheet demo

Creating a sprite sheet

To create the sprite sheets, you'll use TexturePacker, a powerful desktop application for creating sprite sheets and optimizing images for game development.

Please download TexturePacker from here:

After the installation click on Try TexturePacker Pro.

In the main screen:

  1. Drop the sprites folder onto the left panel
  2. Choose data format Flame Engine on the top of the right panel
Select Flame as framework and drop the sprites folder onto TexturePacker

When you add a folder to TexturePacker, it collects all sprites in that folder recursively. The subfolder names are prepended to the sprite names. In our example, the sprites will be available with names like capguy/walk_01, capguy/walk_02 and so on.

The main folder name "sprites" is omitted by default. If you want to include it as part of the sprite name, use Prepend folder name from the Advanced settings.

Create a new folder called spritesheets in your project's assets/images directory. In TexturePacker, click on the folder icon next to Data file and navigate to the spritesheets folder. Name the data file cityscene.atlas.

Finally, press Publish sprite sheet to write the sprite sheet to your project folder.

Create a sprite sheet for Flame

This automatically creates 2 files:

  • spritesheets/cityscene.png - the sprite sheet image
  • spritesheets/cityscene.atlas - the sprite sheet data file

Optimizing your sprite sheets for faster loading

The resulting cityscene.png is about 450 KB in size. But we can do better! TexturePacker can dramatically reduce the file size of your sprite sheets, making your game load faster.

Simply change the Texture format from PNG-32 to PNG-8 (indexed) and press Publish sprite sheet again. The result is a sprite sheet which is almost identical but now is only 110 KB — a 75% reduction in file size!

Loading the sprite sheet in your game

You just need to load the sprite sheet using the flame_texturepacker package.

Import the package in your lib/main.dart:

import 'package:flame_texturepacker/flame_texturepacker.dart';

Then, inside onLoad, load the sprite sheet:

lib/main.dart
    // load the sprite sheet
    final atlas = await atlasFromAssets('spritesheets/cityscene.atlas');

Adding a sprite from a sprite sheet

Adding a sprite from the sprite sheet is easy. Let's fetch the background sprite from the sprite sheet instead of loading it directly:

lib/main.dart
    // fetch the background sprite from the sprite sheet
    final background = atlas.findSpriteByName('background');

    // add background as a component
    add(SpriteComponent(sprite: background));

Adding and playing animations

TexturePacker can automatically detect animations in your sprites and give you a list of all frames. This works with files named 01.png, 02.png, etc., but also with files ending with a _ or - and a number. E.g. capguy/walk_01.png, capguy/walk_02.png, etc. will be detected as animation. The animation name is the same as the sprite name but without the numbers. In our case: capguy/walk.

To enable this animation detection feature, simply go back to TexturePacker:

  • Use the button on the bottom right to switch to the Advanced settings.
  • Enable the Auto-detect animations checkbox
  • Update the sprite sheet by pressing Publish sprite sheet.

Let's see how we can create an animated sprite in Flame. Add the following Player class to your code:

lib/main.dart
class Player extends SpriteAnimationComponent {
  final TexturePackerAtlas atlas;
  final double sceneWidth;

  Player(this.atlas, this.sceneWidth) : super(position: Vector2(100, 400));

  @override
  Future<void> onLoad() async {
    // create the walking animation
    final walkSprites = atlas.findSpritesByName('capguy/walk');
    animation = SpriteAnimation.spriteList(
      walkSprites,
      stepTime: 0.1,
      loop: true,
    );
  }
}

This class uses the findSpritesByName method to retrieve all sprites of the animation and create a SpriteAnimation from them.

In MyGame.onLoad(), add an instance of the Player to your game:

lib/main.dart
    // create and add the player
    add(Player(atlas, background!.srcSize.x));

Now go back into your simulator and reload the scene. You should now see your character walking in place.

To make the character move across the screen, update the Player class by adding an update method:

lib/main.dart
  double speed = 100.0; // pixels per second

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

    // move the player horizontally
    position.x += speed * dt;

    if (position.x >= sceneWidth) {
      position.x = -size.x;
    }
  }

Reloading the application should now show the character walking across the screen and wrapping around when he reaches the edge.

Flame Engine Sprite Sheet Demo