---
title: "How to create sprite sheets for Phaser with TexturePacker"
description: "Learn how to create sprite sheets for Phaser with TexturePacker. This tutorial also explains how to create an animation and how optimize your spritesheet."
canonical: "https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser"
date: "2026-08-25T00:00:00.000Z"
modified: "2026-08-25T00:00:00.000Z"
source: "html"
---

# How to create sprite sheets for Phaser with TexturePacker

Joachim Grill, Andreas Löw

Last updated: August 25, 2026

[texturepacker](https://www.codeandweb.com/texturepacker/tutorials.md),  [phaser](https://www.codeandweb.com/tutorials/phaser.md),  [tutorial](https://www.codeandweb.com/tags/tutorial),  [sprite-sheets](https://www.codeandweb.com/tags/sprite-sheets),  [animation](https://www.codeandweb.com/tags/animation)

[GitHub](https://github.com/CodeAndWeb/phaser-sprite-sheet-example)

![How to create sprite sheets for Phaser with TexturePacker](https://www.codeandweb.com/static/966b49e618100fbb4789ae6d41cc2fcc/a6312/_opengraph-image.png)

## What you are going to learn

*   **Creating sprite sheets** with TexturePacker
*   **Loading sprite sheets** in Phaser 4
*   Setting **Pivot Points** with TexturePacker
*   Playing **Animations** from the sprite sheet
*   **Optimizing** start up time and reducing download size

Read this tutorial if you are still using Phaser 3: [Creating sprite sheets for Phaser 3](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3)

Here's a preview of the game scene you are going to create during this tutorial - all assets included. The complete tutorial code is available on [GitHub](https://github.com/CodeAndWeb/phaser-sprite-sheet-example).

Loading Phaser Demo

## Why should I use a sprite sheet?

The first step is to create a sprite sheet. Using sprite sheets with Phaser serves two primary purposes:

### Speed up loading of the game:

By loading all graphics at once instead of numerous single images from a web server, the loading time of your game is significantly reduced.

### Improve frame rate:

Using a sprite atlas enhances the game's performance. With WebGL, textures only need to be set once for rendering, resulting in improved frame rates.

> “TexturePacker is an essential part of our daily workflow. Every bit of GPU memory helps when dealing with mobile html5 games, so intelligent packing of assets is a must. And Texture Packer has all the features we need to effortlessly create atlases for our games.”
> 
> ![Richard Davey](https://www.codeandweb.com/static/354acc3e83c76a47e768b761377a4d0f/f9edd/richard-davey.jpg)
> 
> Richard Davey (@photonstorm)
> 
> Creator of Phaser

## Set up a new Phaser project

Phaser provides a set of project templates which makes creating a new phaser project quite simple:

```bash
npm create @phaserjs/game@latest MyProject
```

For our example we select:

*   Web Bundler: vite
*   Minimal
*   Javascript

Now we can install the required npm packages and start a local server + browser:

```bash
cd MyProject
npm install
npm run dev
```

The complete demo project we're going to create in this tutorial is also available on [GitHub](https://github.com/CodeAndWeb/phaser-sprite-sheet-example).

## Creating sprite sheets - the easy way

The easiest way to create your sprite sheets is using TexturePacker. Please download TexturePacker from here:

[Download TexturePacker 8.3.0](https://www.codeandweb.com/texturepacker/download/8.3.0/win)

for Windows

[Also available for macOS and Linux](https://www.codeandweb.com/texturepacker/download.md)

When starting the application choose **Try TexturePacker Pro**. In the main window use the **Choose Data Format** button and select **Phaser** from the list. You can use the filter to find it faster.

  ![Selecting Phaser exporter for TexturePacker](https://www.codeandweb.com/static/61b88c873f18346a7996d32e49f968fa/283d3/texturepacker-select-phaser-exporter%402x.png)

Be careful to select the **Phaser** format, only this one supports pivot point editing, multi-pack with one single json file and normal map packing. The other two Phaser data file formats can be used with older Phaser versions. In this case please have a look on the [previous version of this tutorial](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser2)

The [demo project](https://github.com/CodeAndWeb/phaser-sprite-sheet-example) of this tutorial already contains some artwork in the **/sprites**\-folder. Simply drag and drop the **cityscene** folder into TexturePacker.

Adding folders has two main advantages over adding single sprites

*   Adding or removing sprites in the folder also adds or removes them from the sprite sheet.
*   Sub folder names become part of the sprite names — e.g. `capguy/walk/0001.png` and not just `0001.png`

After that, use the file selection button to enter a name for the JSON data file. Name it **cityscene.json** and place it in the **public/assets/spritesheets** folder of your project. By default, TexturePacker will save the texture image as **cityscene.png** in the same folder.

Finally, press **Publish sprite sheet** to create and save the sprite sheet. We are now finished with TexturePacker. That's all it takes to create a sprite sheet.

  ![Creating sprite sheets for Phaser](https://www.codeandweb.com/static/e39e45cced3b724ec523ddedb75c11db/283d3/creating-sprite-sheets-for-phaser%402x.png)

## Loading the sprite sheet in Phaser

In **src/game/main.js** the project template configures the screen size: We change it to 800x600 to match the size of our background image, and disable the automatic scaling:

src/game/main.js

```js
const config = {
    type: AUTO,
    width: 800,
    height: 600,
    parent: 'game-container',
    backgroundColor: '#028af8',
    // scale: {
    //     mode: Scale.FIT,
    //     autoCenter: Scale.CENTER_BOTH
    // },
    scene: [
        MainGame
    ]
};
```

The project template file **src/game/scenes/Game.js** displays some text on a blue background. For our demo app we remove the content of the `preload()` and `create()` functions and add our own code:

src/game/scenes/Game.js

```js
import { Scene } from 'phaser';

export class Game extends Scene
{
    constructor ()
    {
        super('Game');
    }

    preload ()
    {
        this.load.multiatlas('cityscene',
                             'assets/spritesheets/cityscene.json',
                             'assets/spritesheets');
    }

    create ()
    {
        this.add.sprite(0, 0, 'cityscene', 'background.png');
    }
}
```

The `preload()` function is used to load assets. There we can use _this.load.multiatlas()_ to load our sprite sheet: The first parameter _'cityscene'_ specifies the key that can be used to access the atlas after it has been loaded. The second parameter _'assets/spritesheets/cityscene.json'_ is the atlas definition to load, the last parameter _'assets/spritesheets'_ is the name of the folder in which the image files are stored.

The `create()` function is used to set up our game scene, here we add the background sprite to the scene. Within the sheet the sprite is referenced by its filename (enable "Trim sprite names" in TexturePacker if you prefer sprite names without _.png_ extension):

After saving the **Game.js** file the **npm run dev** script will automatically rebuild the game and refresh the browser window. You will see only a quarter of our background image in the top-left corner:

  ![Bad pivot point in Phaser](https://www.codeandweb.com/static/6df8fe995fda5b663d38788fc744d77a/24144/background-misaligned.png)

By default, the pivot point of a sprite is in the center of the image, so the call `this.add.sprite(0, 0, ...)` places the center of our background sprite at position (0,0). In the next section we will learn how to fix this.

## Setting pivot points with TexturePacker

Pivot points can easily be set for each sprite in TexturePacker. Select **background.png** on the left side of the TexturePacker window, and then click on the **Sprite Settings** button in the toolbar. On the left side you can now enable and configure the pivot point of the selected sprite:

  ![Editing Phaser anchor points](https://www.codeandweb.com/static/ce96f34267520a9def0861ff8144060c/283d3/texturepacker-edit-pivotpoint%402x.png)

Select **Top left** in the **Predefined** input field, and re-publish the sprite sheet. Now reload the browser window displaying your phaser game (changed asset files are not detected automatically). The background image should be perfectly placed now:

  ![Aligning sprites with Phaser](https://www.codeandweb.com/static/b5f1427ac16e39d06f6a169d245ccbf5/24144/background-aligned.png)

If the sprite isn't displayed as expected it's always a good idea to check the Javascript console in your browser. Maybe the sprite sheet wasn't found, or you're using a wrong sprite name? There shouldn't be any warning or error in the console!

## Adding an animation

To add a walking character to the scene we have to create an animated sprite and move it across the screen. First we'll have to create the sprite and store it in a member variable of our scene:

```js
create()
{
    this.add.sprite(0, 0, 'cityscene', 'background.png');

    this.capguy = this.add.sprite(0, 400, 'cityscene', 'capguy/walk/0001.png');
    this.capguy.setScale(0.5, 0.5);
```

This creates a sprite with the first frame of the animation: `capguy/walk/0001.png` and places it at position (0,400). The next line scales the sprite down by 50% because it would otherwise be a bit too big for the scene.

The function `generateFrameNames()` creates a bunch of frame names by creating zero-padded numbers between _start_ and _end_, surrounded by _prefix_ and _suffix_. 1 is the start index, 8 the end index, and the 4 is the number of digits to use:

```js
    const frameNames = this.anims.generateFrameNames('cityscene', {
                           start: 1, end: 8, zeroPad: 4,
                           prefix: 'capguy/walk/', suffix: '.png'
                       });
```

The resulting names are:

*   `{ key:'cityscene', frame:'capguy/walk/0001.png' }`
*   `{ key:'cityscene', frame:'capguy/walk/0002.png' }`
*   ...
*   `{ key:'cityscene', frame:'capguy/walk/0008.png' }`

Now we can create an animation called _walk_ and add it to the _capguy_ sprite:

```js
    this.anims.create({ key: 'walk', frames: frameNames, frameRate: 10, repeat: -1 });
    this.capguy.anims.play('walk');
}
```

The result is Capguy walking on a spot at the left border:

  ![Animating sprites with Phaser](https://www.codeandweb.com/static/e498e86e77a9bf4818e60f54d18a0c84/29d74/animation-at-border.png)

## Moving the sprite

There are several ways to move a sprite in Phaser. You are going to do a simple animation - just pushing the sprite along and resetting it after Capguy left the scene.

Add the following update method to the _Game_ class, Phaser will call it periodically:

```js
  update(time, delta)
  {
      this.capguy.x += delta/10;
      if (this.capguy.x > 850)
      {
          this.capguy.x = -50;
      }
  }
```

Not much to say about that: The time (in milliseconds) since the previous update call is passed as second parameter. To increase Capguy's position 100 pixels per second we divide delta by 10. After reaching the right border the sprite position is reset to the left border.

## Using 9-slice game objects

9-Slice scaling is an efficient 2D graphic resizing technique that is particularly useful for scaling rectangular images and user interface elements without distorting their original aesthetics.

![9-slice scaling](https://www.codeandweb.com/static/81cac94fa303227ef758eeb6b002da16/0f9a8/nine-slice-scaling%402x.png)

As you see, the image is split in 9 sectors. The corners stay identical and are not scaled at all. The borders at the top are scaled horizontally, the borders left and right are scaled vertically. The center is stretched in all directions.

  ![Editing 9 slice sprites with TexturePacker](https://www.codeandweb.com/static/a0929ed135e96bfba55bc3f2d35d7971/283d3/9-slice-scaling-with-phaser%402x.png)

Editing 9-slice sprites in TexturePacker

1.  Open the sprite settings editor and select the sprite you want to edit on the left
2.  Check **Enable 9-patch scaling**
3.  Edit the sprite borders by dragging them with the mouse

To use such a game object in Phaser simply add

```js
        // 9-slice objects
        this.add.nineslice(75, 50, 'cityscene', 'button.png', 100, 50);
        this.add.nineslice(250, 50, 'cityscene', 'button.png', 200, 50);
```

The result looks like this:

![9-slice sprites in phaser](https://www.codeandweb.com/static/c06e01446982bc9021985b2961b1e8de/2b213/nine-slice-button-in-action%402x.png)

The arguments to this function are:

```
nineslice(x, y, texture, frame, width, height)
```

*   `x`, `y`: Position of the NineSlice Object
*   `texture`: Name of the sprite sheet
*   `frame`: Name of the sprite
*   `width` and `height` of the object

There are some more parameters that you can use to specify the borders manually but these are not required if you use TexturePacker to define the NineSlice Object.

> **Warning:** Phaser supports 9-slice game objects in the WebGL renderer only.

## Optimizing your game

The resulting **cityscene.png** has a size of around 400kb — Not much for a fast internet connection but for a mobile device it might be a good idea to optimize the loading time.

TexturePacker allows you to dramatically reduce the amount of memory used by your sprite sheets — while keeping the sprite quality almost like the original.

To enable this optimization select Texture format **PNG-8 (indexed)**:   ![Optimizing sprite sheets for Phaser](https://www.codeandweb.com/static/0f453ddb201df071fd749dc4e45bef29/283d3/optimizing-sprite-sheets-for-phaser%402x.png)

Here's the original sheet: **390kb**   ![High quality sprite sheet in Phaser](https://www.codeandweb.com/static/cecb778ad88c7aff3377eae925eba738/283d3/cityscene-png32.png)

Here's the optimized sheet: **115kb - that is 70% less!**   ![Using png-8 (pngquant) sprite sheets with Phaser to save memory](https://www.codeandweb.com/static/cfef04570e87373c13a560722edc8e1a/283d3/cityscene-pngquant8.png)

## Using texture compression

Texture compression reduces the amount of GPU memory a texture occupies and can speed up rendering. Unlike PNG or JPEG, which are decompressed into raw pixels before they reach the GPU, compressed textures stay compressed in video memory. This means lower memory usage and faster texture uploads.

Phaser supports **KTX** files with **ASTC**, **ETC** and **DXT (S3TC)** compression, which can be generated with TexturePacker. For a full overview of all formats supported by TexturePacker, see [Texture compression](https://www.codeandweb.com/texturepacker/documentation/texture-compression.md). Note that compressed textures require the WebGL renderer — the Canvas renderer does not support them.

### Creating compressed sprite sheets

The easiest way to publish the same sprite sheet in multiple compressed formats is TexturePacker's command line interface:

```bash
TexturePacker cityscene.tps --texture-format ktx --pixel-format ASTC_4x4 \
    --flip-y --premultiply-alpha --json-file cityscene-astc.json

TexturePacker cityscene.tps --texture-format ktx --pixel-format DXT5 \
    --flip-y --premultiply-alpha --json-file cityscene-dxt5.json

TexturePacker cityscene.tps --texture-format ktx --pixel-format ETC2_RGBA \
    --flip-y --premultiply-alpha --json-file cityscene-etc2.json
```

Two settings are essential here — without them the sprites appear distorted, or semi-transparent pixels render with wrong colors:

*   **\--flip-y** stores the texture bottom-up, which is the orientation Phaser 4's WebGL renderer expects for compressed textures. (TexturePacker 8.2.1 and older call this flag `--flip-pvr`.)
*   **\--premultiply-alpha** multiplies the color values with the alpha value before compressing. WebGL cannot apply premultiplication while uploading compressed textures, but Phaser's default blending expects premultiplied alpha — so it must already be baked into the texture data.

### Loading compressed textures

To load compressed textures, replace the `this.load.multiatlas()` call from above with `this.load.texture()` and specify one or more formats:

```js
const path = 'assets/spritesheets';

this.load.texture('cityscene', {
    'ASTC': {
        type: 'KTX',
        multiAtlasURL: `${path}/cityscene-astc.json`,
        multiPath: path,
    },
    'S3TC': {
        type: 'KTX',
        multiAtlasURL: `${path}/cityscene-dxt5.json`,
        multiPath: path,
    },
    'ETC': {
        type: 'KTX',
        multiAtlasURL: `${path}/cityscene-etc2.json`,
        multiPath: path,
    },
});
```

You can specify all three formats for maximum device compatibility, or only the ones you need. Phaser checks which compressed texture formats the GPU supports and loads the appropriate variant.

To verify which format was actually loaded, add this to your `create()` function:

```js
const src = this.textures.get('cityscene').source[0];
console.log('Loaded texture format:', src.compressionAlgorithm ?? 'uncompressed');
```

## Multipack: The easy way to handle many sprites

So, what do you do if your game has more sprites than TexturePacker can fit on a single sprite sheet? Instead of generating multiple sprite sheets using separate TexturePacker projects, there's a much simpler solution:

Enable **Auto Multipack** in TexturePacker: This feature automatically generates as many sprite sheets as needed to hold all sprites. The great part is that all the necessary information is stored in the generated .json file, and you won't have to modify a single line of code!

For even better performance, consider grouping sprites that appear in the same scene of your game on the same sheet. With the **Manual Multipack** mode, you have the flexibility to manually add or remove sprite sheets, and you can easily move sprites between these sheets using drag-and-drop.

For more details see [Multipack documentation](https://www.codeandweb.com/texturepacker/documentation/user-interface-overview.md#multipack).

  ![Handling many sprites with Phaser](https://www.codeandweb.com/static/360ead196533c2224013655f3daa2c17/283d3/multipack%402x.png)

## Finally

That's all for this tutorial. You should now have learned how to easily add animations to Phaser using TexturePacker and discovered how simple it is to optimize your game for improved startup time.

## Structured data

```json
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "How to create sprite sheets for Phaser with TexturePacker",
  "author": [
    {
      "@type": "Person",
      "name": "Joachim Grill"
    },
    {
      "@type": "Person",
      "name": "Andreas Löw"
    }
  ],
  "dateModified": "2026-08-25T00:00:00.000Z",
  "image": "/static/966b49e618100fbb4789ae6d41cc2fcc/a6312/_opengraph-image.png"
}
```
