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 interested in using Flame Engine with sprite sheets. It covers the basics of adding sprites and animations to a scene, as well as techniques like packing sprite sheets, and optimizing 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 in your own blog or tutorial, or use them in a 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 created a project yet, 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 command automatically 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 code initializes 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, we use TexturePacker, a powerful desktop application for creating sprite sheets and optimizing images for game development.

Please download TexturePacker from here:

After installation, activate the trial by clicking 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 a folder is added 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 accessible using 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 that looks almost identical but is now only 110 KB — a 75% reduction in file size!

Loading the sprite sheet in your game

To use the sprite sheet in Flame, we need to load it 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 simple. 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 create lists of all frames. This works with files named 01.png, 02.png, etc., but also for files ending with a _ or - followed by a number. For example, capguy/walk_01.png, capguy/walk_02.png, etc., will be detected as an animation. The animation names are the same as the sprite names, but without the trailing numbers. In our case: capguy/walk.

To enable this animation detection feature, 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 creates 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));

Go back to your simulator and reload the scene. You should see the 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;
    }
  }

Reload your application, and you should see the character walking across the screen and wrapping around when reaching the edge.

Flame Engine Sprite Sheet Demo