RiggyTry it

From a layered PSD to an animated Spine character in Phaser 4

A step-by-step walk from layered art to a character that plays in a Phaser 4 game: the rig is made from a PSD, exported as Spine 4.2 JSON and loaded with the official Spine plugin for Phaser. The demo below is the finished result — click it to switch animations.

The result

A cat at a laptop with four animations: idle (a loop, nodding to the music), hack, glitch and bigwin (one-shots that return to idle). The whole demo is one HTML page and a short main.js; open it on its own and view the source. Using PixiJS instead? The same rig in PixiJS 8; Unity? The Unity version.

From layered art to a rig

The art is a layered PSD with 15 parts: body, head, two eyes and pupils, headphones, the arm in two pieces, laptop screen and keyboard, laces and tail. Each part on its own layer is all a skeleton needs — bones move layers, they do not redraw them.

The rig was made in Riggy by describing the motion in chat:

  • “idle — the cat nods its head to music at 90 BPM, as if listening.”
  • “hack — new animation: the cat lifts its paw and hits the keys sharply.”
  • “bigwin — the cat sways its head left and right to the music, raises a paw a little and waves it.”

The result is 18 bones and four animations. You can get the same files by rigging in the Spine editor by hand — the Phaser part below does not care where the skeleton came from.

Export Spine 4.2 JSON

The export is plain Spine 4.2 data:

skeleton.json    bones, slots, skins and the four animations
skeleton.atlas   where each part sits on the texture page
page.png         the texture page itself
images/          every part as its own PNG, to repack the atlas if you want

Phaser needs the first three. Two things to check in any export, not only Riggy's. First, the runtime version must match the export: these files say 4.2, so the plugin must be a 4.2 build. Second, the .atlas file must start with the page image name. The Phaser plugin takes the first line of the file as the page name, so an atlas that starts with an empty line (the old 3.x style) makes it load a folder instead of page.png and fail with Failed to process file: image.

Add Phaser and the Spine plugin

Esoteric Software publishes the plugin as @esotericsoftware/spine-phaser-v4 for Phaser 4 and spine-phaser-v3 for Phaser 3. Their latest tag already points to Spine 4.3, so pin a 4.2 version for 4.2 exports. From a CDN:

<script src="https://cdn.jsdelivr.net/npm/phaser@4.2.1/dist/phaser.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@esotericsoftware/spine-phaser-v4@4.2.120/dist/iife/spine-phaser-v4.min.js"></script>

or from npm:

npm install phaser@4.2.1 @esotericsoftware/spine-phaser-v4@4.2.120

Register the plugin as a scene plugin in the game config:

new Phaser.Game({
  type: Phaser.WEBGL,
  parent: "game",
  width: 800,
  height: 600,
  ...
  plugins: {
    scene: [{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }],
  },
});

Load the skeleton and play it

The plugin adds two loader types — spineJson for the skeleton and spineAtlas for the atlas, which also loads its page images from the same folder:

  preload() {
    this.load.spineJson("cat-data", "assets/skeleton.json");
    this.load.spineAtlas("cat-atlas", "assets/skeleton.atlas");
  }

In create, this.add.spine places the skeleton. The x, y point is where the root bone stands — for this rig, the bottom center — and the skeleton is scaled down to fit an 800×600 canvas:

    const cat = this.add.spine(400, 580, "cat-data", "cat-atlas");
    cat.setScale(0.45);

    // blend 0.2 s between any two animations instead of snapping
    cat.animationState.data.defaultMix = 0.2;
    cat.animationState.setAnimation(0, "idle", true);

defaultMix crossfades every switch between animations, so the cat never snaps from one pose to another.

One-shots that return to the loop

A one-shot such as hack should play once and hand control back to idle. Queue the loop right behind it on the same track:

        // play the one-shot once, then go back to the idle loop
        cat.animationState.setAnimation(0, name, false);
        cat.animationState.addAnimation(0, "idle", true, 0);

The last argument of addAnimation is a delay; 0 starts idle as soon as the one-shot ends, blended by the same default mix.

When it does not load

Licensing

The Phaser plugin is part of the Spine Runtimes. Shipping a game with them requires a Spine license from Esoteric Software, whoever made the skeleton. What that means for exported rigs is on the licensing page. Riggy is an independent tool, not affiliated with Esoteric Software or Phaser.

Your layered art, moving in Phaser

Drop a PSD, say what should move, export Spine 4.2 and load it with the code above.

Animate your own PSD