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:
- Drag and drop all the files you want to add to the left pane of TexturePacker
- 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.
- Click on Publish sprite sheet
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 libgdx.png and displays it on a dark background.
In the previous section, we've already added the libgdx.png sprite to the sprite sheet. Now, we can load the sprite sheet and extract the sprite from it:
package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
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;
/** {@link com.badlogic.gdx.ApplicationListener} implementation shared by all platforms. */
public class MyGdxGame extends ApplicationAdapter {
private SpriteBatch batch;
private TextureAtlas textureAtlas;
private Sprite sprite;
@Override
public void create() {
batch = new SpriteBatch();
textureAtlas = new TextureAtlas("spritesheet.atlas");
sprite = textureAtlas.createSprite("libgdx");
}
@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 bright blue color:
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.GL20;
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;
/** {@link com.badlogic.gdx.ApplicationListener} implementation shared by all platforms. */
public class MyGdxGame extends ApplicationAdapter {
private SpriteBatch batch;
private TextureAtlas textureAtlas;
private Animation<Sprite> animation;
private float stateTime = 0;
@Override
public void create() {
batch = new SpriteBatch();
textureAtlas = new TextureAtlas("spritesheet.atlas");
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