AutoSprite

Phaser Integration

Load AutoSprite spritesheets into Phaser 3 with load.spritesheet, animations, and Arcade Physics bodies.

This guide covers loading AutoSprite PNG spritesheets into Phaser 3 and driving them with the Animation Manager and Arcade Physics.

ℹ️

Need to generate the asset first? Start with the Phaser sprite sheet generator workflow, then use this guide for loader config and animation code.

Quick Start

Drop the PNG into your project

Copy the exported PNG into your game's public/assets/ (or wherever your loader is pointed).

Load in preload()

Phaser's load.spritesheet slices a uniform grid. Use the frameWidth / frameHeight values from AutoSprite's JSON atlas.

preload() {
    this.load.spritesheet('player_run', 'assets/player_run.png', {
        frameWidth: 256,
        frameHeight: 256,
    });
}

Create the animation

In create(), register an animation from a frame range:

create() {
    this.anims.create({
        key: 'run',
        frames: this.anims.generateFrameNumbers('player_run', {
            start: 0,
            end: 11,
        }),
        frameRate: 12,
        repeat: -1, // -1 = loop forever
    });
}

Play it on a Sprite

const player = this.physics.add.sprite(100, 300, 'player_run');
player.anims.play('run');

Loading One Animation Per Sheet

AutoSprite exports one PNG per animation by default. Register each one with its own key:

preload() {
    const size = { frameWidth: 256, frameHeight: 256 };
    this.load.spritesheet('idle', 'assets/idle.png', size);
    this.load.spritesheet('run',  'assets/run.png',  size);
    this.load.spritesheet('jump', 'assets/jump.png', size);
}

create() {
    const anims = [
        { key: 'idle', end: 5,  fps: 8,  loop: true },
        { key: 'run',  end: 11, fps: 14, loop: true },
        { key: 'jump', end: 7,  fps: 12, loop: false },
    ];
    anims.forEach(({ key, end, fps, loop }) => {
        this.anims.create({
            key,
            frames: this.anims.generateFrameNumbers(key, { start: 0, end }),
            frameRate: fps,
            repeat: loop ? -1 : 0,
        });
    });
}
✨
Pro Tip:

Grab frames, frameWidth, and frameHeight directly from AutoSprite's JSON atlas — no need to count frames by eye.

Using a Combined Atlas

If you merge AutoSprite's outputs into a single packed atlas (with TexturePacker, Free Texture Packer, etc.), switch to load.atlas:

preload() {
    this.load.atlas('player', 'assets/player.png', 'assets/player.json');
}

create() {
    this.anims.create({
        key: 'run',
        frames: this.anims.generateFrameNames('player', {
            prefix: 'run_',
            start: 0,
            end: 11,
            zeroPad: 2, // run_00, run_01, ...
        }),
        frameRate: 12,
        repeat: -1,
    });
}

Atlas loading is worth it once you have many animations — one texture, one HTTP request, and Phaser's texture cache stays small.

Arcade Physics Example

Full Arcade Physics player with facing-direction flip:

create() {
    this.player = this.physics.add.sprite(100, 300, 'idle');
    this.player.setCollideWorldBounds(true);
    this.cursors = this.input.keyboard.createCursorKeys();
}

update() {
    const { left, right, up } = this.cursors;
    const onGround = this.player.body.blocked.down;

    if (left.isDown) {
        this.player.setVelocityX(-160);
        this.player.setFlipX(true);
        if (onGround) this.player.anims.play('run', true);
    } else if (right.isDown) {
        this.player.setVelocityX(160);
        this.player.setFlipX(false);
        if (onGround) this.player.anims.play('run', true);
    } else {
        this.player.setVelocityX(0);
        if (onGround) this.player.anims.play('idle', true);
    }

    if (up.isDown && onGround) {
        this.player.setVelocityY(-400);
        this.player.anims.play('jump', true);
    }
}

Handling Animation Events

React to an animation finishing (e.g. chain attack → idle):

this.player.on('animationcomplete-attack', () => {
    this.player.anims.play('idle');
});

Generic listener (fires for any animation):

this.player.on(Phaser.Animations.Events.ANIMATION_COMPLETE, (anim) => {
    console.log('finished', anim.key);
});

Pixel Art Tips

✨
Pro Tip:

In your Phaser game config, set pixelArt: true (or antialias: false) to keep pixel edges crisp. This switches the texture filter to NEAREST.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    pixelArt: true,
    physics: { default: 'arcade' },
    scene: { preload, create, update },
};

Common Issues

Only the first frame plays: You called play('run') but never created the animation with that key. anims.create must run in create() before play.

Sprite looks blurry: Enable pixelArt: true in the game config.

Frames are off by one: AutoSprite's JSON frames counts the total; Phaser's end is inclusive and zero-indexed, so end = frames - 1.

Wrong frame dimensions: The frameWidth / frameHeight must exactly match the AutoSprite JSON. If your sheet is 4096×256 with 16 frames, frame size is 256×256 — not 4096/16 without checking the PNG height.

Learn More

Need Help?

Join Discord

We have a #phaser channel for framework-specific questions.