How to create sprite sheets & animations for PixiJS 7

Andreas Löw
How to create sprite sheets & animations for PixiJS 7
Last update: Last week

Who is this tutorial for?

This tutorial is for all readers who want to use PixiJS. The tutorial covers the basics of adding sprites and animations to a scene. It also covers advances techniques like setting pivot points, packing sprite sheets, optimizing loading times.

This tutorial uses of PixiJS 7. Read this if you are still using older versions of PixiJS: How to create sprite sheets and animations for PixiJS 6.x

Here are the steps we cover in this tutorial:

How to create and use sprite sheets with PixiJS

This tutorial guides you through the following steps

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

Create a simple PixiJS game scene

Download the assets

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

Extract the contents into a folder that you now use for development of this demo.

The archive contains the graphics you see in the demo above:

  • scene
    • background.png
    • middleground.png
  • sprites
    • character
      • 01.png ... 08.png

Download PixiJS

Download the current version of PixiJS. You only need the pixi.js file for this tutorial. Save the files in the same folder as the assets.

Getting started with a simple scene

Start by creating an index.html file that:

<!doctype html>
<html lang="en">
        <title>PixiJS Sprite Sheet Demo</title>
        <script src="pixi.js"></script>
        <script src="demo.js"></script>

Create your game file: demo.js in the same folder:

// Create a PixiJS application
const app = new PIXI.Application({width: 960, height: 540});

// add the view that Pixi created for you to the DOM

// load the assets and start the scene
]).then(() => {
    // initialize background image
    const background = PIXI.Sprite.from("scene/background.png");

    // add the middle ground
    const middleground = PIXI.Sprite.from("scene/middleground.png");

    // scale stage container to match the background size
    app.stage.scale.x = app.view.width / background.width;
    app.stage.scale.y = app.view.height / background.height;

Let's take a look at this code:

The first lines initialize the PixiJS application with a width of 960 and a height of 540. It then adds the application's view to the DOM.

The next lines load the background.png and middleground.png images. Both images are added to the state once they are loaded.

Finally, the stage is resized to match the background images size. We have to do this because I included high-resolution versions of all images. I'll show you how you can resize them to match different device resolutions later.

Testing the scene in your browser

You can't open the application in the browser directly by opening the HTML file. This is because of security restrictions. PixiJS loads the resources dynamically which is not permitted in HTML files loaded from the file system.

The easiest way to display the application is using a local web browser... but you don't have to install Apache on your computer to do so. A simple server like the npm module http-server is sufficient.

If you already have node installed, it's simply opening a command prompt in the folder where your index.html is located. Type

npx http-server -c-1 .

The -c-1 option disables caching - which is important during development. Otherwise, you might not see changes after editing files in the browser.

And open http://localhost:8080 in your browser. You should now see the background of the game scene:

Background scene for the PixiJS sprite sheet demo

Create a sprite sheet from animation frames

To create the sprite sheets, we use TexturePacker, a robust desktop application, for creating sprite sheets and optimizing images for game development. Since its initial release in 2010, TexturePacker has been continually updated with new features and bug fixes, making it a reliable and efficient tool for game developers.

Please download TexturePacker from here:

After installation, activate the trial by clicking on Try TexturePacker Pro. You can now use all features of TexturePacker for the next 7 days. After that, you can still use TexturePacker for free, but only with a reduced set of features.

In the main screen:

  1. Choose PixiJS from the center screen
  2. Drop the sprites folder onto the left panel
Select PixiJS as Framework and drop the sprites folder onto TexturePacker
Select PixiJS and drop the sprites folder onto TexturePacker

In case you dropped the sprites first, or you already used TexturePacker for a project, click on Framework and select PixiJS from the dialog that opens here.

TexturePacker collects all sprites in that folder. A sub-folder in that main folder is pre-ended to the sprite name. So your sprites will be accessible using the names character/walk_01.png, character/walk_02.png and so on.

The main folder name (sprites) is by default omitted - if you want to include it as part of the sprite name use Prepend folder name from the Advanced settings. You can also remove the .png extension from the filenames by enabling Trim sprite names, also in the Advanced Settings.

Create a new folder called spritesheets in the demo directory.

In TexturePacker, click on the folder icon next to Data file and navigate to your spritesheets folder. Name the file character.json.

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

Create a sprite sheet for PixiJS
Set the file name and press publish sprite sheet

This automatically creates 2 files:

  • character.png - the sprite sheet image
  • character.json - the sprite sheet data file that contains the positions and names if your sprites

Play the animation in PixiJS

Back to your demo.js. Add the spritesheets/character.json to the list of assets to load:

]).then(() => {

TexturePacker detects animations in your sprites and creates lists of all frames. This makes creating animations in PixiJS very simple.

This works with files named 01.png, 02.png, ... but also for files ending with a _ or - and a number. E.g. character/walk-01.png, character/walk-02.png will also be detected.

The animation are named in the same way as the sprites - but without the numbers and the .png. In our case here character/walk.

First, you have to get the animations from the texture. You can do this by accessing the Asset cache. Append these code blocks before the closing }); at the end of the file:

    // get the sheet json data, required for resolving animations
    const animations = PIXI.Assets.cache.get('spritesheets/character.json').data.animations;

Now create a new AnimatedSprite from the animation data. Configure the main parameters for it: The position and the speed. Finally start playing the animation by calling play() and add it to the stage:

    // create an animated sprite
    const character = PIXI.AnimatedSprite.fromFrames(animations["character/walk"]);

    // configure + start animation:
    character.animationSpeed = 1 / 6;                     // 6 fps
    character.position.set(150, background.height - 780); // almost bottom-left corner of the canvas;

    // add it to the stage and render!

Go back to your browser and refresh the scene. You should see the character doing a moon-walk...

Add these lines to make him walk from left to right:

    // move the character to the right, restart on the left
    app.ticker.add(delta => {
        const speed = 6;
        character.x = (character.x + speed * delta) % (background.width + 200);

This code is a function that is called in regular intervals. We use it to update the x position of the sprite. The function get a value called delta which is the time passed since the last call of the function. We use this to calculate the distance to move the character by multiplying the value with the speed.

This makes the character move at the same speed on all devices - no matter what the frame rate on that device is. If you do not use the delta for that calculation, there might be computers or mobile phones on which the character walks faster or slower.

The final trick is the % which is a modulo division that makes the character appear on the left side after it disappears on the right (x greater or equal to background.width + 200).

Setting anchor points for your PixiJS sprites

The anchor point is the point around which the sprite rotates and scales, and it also determines the position of the sprite when it is placed on the x and y coordinates. Essentially, the anchor point acts as the center of the sprite and is used to control its orientation and movement in the game.

To show you what I mean, please update the ticker function to the following and refresh your browser:

    app.ticker.add(delta => {
        const speed = 6;
        character.x = 500;
        character.rotation += delta/100;

At first glance, the sprite may appear to rotate around a point that seems disconnected from the sprite itself. This is due to the default anchor point being set to the coordinate (0,0), and the presence of large areas of transparency within the sprite's frame.

The default anchor point in PixiJS is at 0/0
The default anchor pont is at 0/0

To overcome this issue, it is important to adjust the anchor point to a suitable location within the sprite. This can be done in TexturePacker and will ensure that the sprite rotates and scales correctly in PixiJS.

To do so, click on Sprite settings in TexturePacker's toolbar and select all sprites in the left panel. Click Fit to see all sprites at once in the center view.

Select all sprites in the center view by pressing the mouse button at the top left of the first sprite and dragging to the bottom right of the last sprite.

The circle in the sprite frames is the anchor point - which are called pivot points in TexturePacker. Move these to the bottom center of the sprite:

Pivot point editor in TexturePacker
The pivot point / anchor point editor in TexturePacker

Back in the game scene, you should now see the character rotating around this point.

Change the code to this to make him walk again:

    // configure + start animation:
    character.animationSpeed = 1 / 6;                     // 6 fps
    character.position.set(150, background.height - 180); // almost bottom-left corner of the canvas;

    // Enable this to update the anchor points with each animation frame
    // character.updateAnchor = true;

    // add it to the stage and render!

    app.ticker.add(delta => {
        const speed = 6;
        character.x = (character.x + speed * delta) % (background.width + 200);

TexturePacker allows you to set individual anchor points for each frame of the animation. This is by default not enabled in an AnimatedSprite. To update the anchor pont for each sprite frame set the updateAnchor property in the sprite to true.

Use MultiPack with PixiJS

Enable MultiPack in TexturePacker

MultiPack is a feature of TexturePacker that allows you to pack many sprites at once. It automatically adds new sprites sheets if the space is not sufficient. This makes handling many sprites much easier for you.

To enable the feature, you have to use TexturePacker 7.0.2 or newer because older versions are not fully compatible.

To enable MultiPack, you have 2 choices:

  • Auto - if you use this variant, TexturePacker does the whole work for you.
  • Manual - you can have to add sprite-sheets manually and can than assign folders or sprites to a sheet. This is great - e.g. if you have multiple levels that don't share sprites. To assigning the sprites, use the tree view on the left. The limitation is that you can't move sprites inside a smart folder. You can only move the smart folder itself.

TexturePacker requires a name extension for the base name of the sprites sheet. {n} now has to be part of the file name and is either repaced with the sheet number (auto multipack) or the sheet name (manual multipack). E.g. you can now name your sprites sheet-{n}.png and sheet-{n}.json which creates sheet-0.png, sheet-1.png or sheet-level1.png, sheet-level2.png,...

Make sure that all your sprite names are unique - using the same name is not possible.

Using MultiPack in PixiJS

In PixiJS it's now sufficient to only load the first sprite sheet:

]).then(() => {

Make sure to only load the first sprite sheet of your multipack set. If you load more than one sheet from the same set, PixjJS deadlocks and does not complete the loading process.

TexturePacker stores all animation frames in the first sprites sheet of the multipack set - no matter on which sprite sheet they are located.

To receive the animation array, use

// get all animations from of the multipack set (stored in the first sprite sheet)
const animations = PIXI.Assets.cache.get('spritesheets/sheet-0.json').data.animations;

To create the animation, use

// create an animated sprite
const character = PIXI.AnimatedSprite.fromFrames(animations["character/walk"]);