How to create sprite sheets & animations for libGDX

Joachim Grill
Last updated:
GitHub
How to create sprite sheets & animations for libGDX

In this tutorial you will learn how to use sprite sheets with libGDX.

Why using sprite sheets?

  • By loading all graphics at once instead of numerous single images, the loading time of your app can be significantly reduced.
  • Using a sprite atlas also enhances the game's performance, because textures only need to be set on the graphics device once, resulting in improved frame rates.

Creating a sprite sheet

The easiest way to create a sprite sheet is using TexturePacker — available for Windows, macOS and Linux:

Creating a sprite sheet with TexturePacker is quite simple:

  1. Drag and drop all the files you want to add to the left pane of TexturePacker
  2. Select the LibGDX framework and set the file path for the generated Data file. The Texture file can be left empty; TexturePacker will automatically save the PNG containing the sprite sheet next to the data file.
  3. Click on Publish sprite sheet
Creating a sprite sheet with TexturePacker

We recommend storing the individual sprites in a root folder named raw-assets, while only placing the sprite sheet data and texture file in the assets folder. This makes it easier to determine which assets must be deployed later.

Using a sprite sheet

Let's start with a new, empty project as you can generate it with the libGDX Project Setup Tool. The default implementation of the main class in the core module loads a sprite called badlogic.jpg and displays it on a red background.

In the previous section, we've already added the badlogic.jpg sprite to the sprite sheet. Now, we can load the sprite sheet and extract the sprite from it:

core/src/com/mygdx/game/MyGdxGame.java
package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.ScreenUtils;

public class MyGdxGame extends ApplicationAdapter {
	SpriteBatch batch;
	TextureAtlas textureAtlas;
	Sprite sprite;
	// highlight-end

	@Override
	public void create () {
		batch = new SpriteBatch();
		textureAtlas = new TextureAtlas("spritesheet.txt");
		sprite = textureAtlas.createSprite("badlogic");
	}

	@Override
	public void render () {
		ScreenUtils.clear(0.57f, 0.77f, 0.85f, 1);
		batch.begin();
		sprite.setPosition(10, 10);
		sprite.draw(batch);
		batch.end();
	}

	@Override
	public void dispose () {
		batch.dispose();
		textureAtlas.dispose();
	}
}

We've also changed the background to a less annoying color:

Screenshot of the demo app

Creating an animation

Now, we want to replace the static sprite with an animation. TexturePacker can automatically detect animation sprites: If the sprite filenames only differ by a sequence number suffix, TexturePacker will remove this suffix and export all the sprites as animation frames in the data file.

This makes it very easy to create an animation from a sprite sheet:

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.ScreenUtils;

public class MyGdxGame extends ApplicationAdapter {
	SpriteBatch batch;
	TextureAtlas textureAtlas;
	Animation<Sprite> animation;
	float stateTime = 0;

	@Override
	public void create () {
		batch = new SpriteBatch();
		textureAtlas = new TextureAtlas("spritesheet.txt");
		animation = new Animation<>(0.066f, textureAtlas.createSprites("capguy"), Animation.PlayMode.LOOP);
	}

	@Override
	public void render () {
		ScreenUtils.clear(0.57f, 0.77f, 0.85f, 1);

		stateTime += Gdx.graphics.getDeltaTime();
		Sprite sprite = animation.getKeyFrame(stateTime, true);
		sprite.setX(stateTime * 250 % (Gdx.graphics.getWidth() + 400) - 200);

		batch.begin();
		sprite.draw(batch);
		batch.end();
	}

	@Override
	public void dispose () {
		batch.dispose();
		textureAtlas.dispose();
	}
}

The Animation object acts as a container for animation frames. You can retrieve the frame to display at a specific point in time using the getKeyFrame method. Note that you need to track the elapsed time externally.

The complete example project is available on GitHub