Start here
Export the PNG and JSON together with tag data, then use Phaser’s Aseprite loader and createFromAseprite. Keep the named ranges, direction and per-frame durations from the same export.
Three real Phaser animations play the original six frames in forward, reverse and ping-pong order. Missing or out-of-range requested tags fail the example’s explicit validation before animation creation.
What you need
The original editable ASE contains six 16×12 frames with different visible bounds and unequal durations. The project includes that input, native-verified PNG/JSON references, source, a package lockfile and notices. You can run its local consumer without installing Aseprite.
Download the original editable ASE · Original 32×16 atlas PNG · Inspect its native-verified JSON
Tested with: Aseprite 1.1.7-dev GPLv2 source build, Linux ARM64 / Ubuntu 22.04 / Xvfb; Phaser 3.90.0 Canvas, eventemitter3 5.0.1; Chrome UA 154.0.0.0 on MacIntel; Node 24.22.0 and independent Pillow 12.3.0 inspection. CLI export, not native GUI editing.
2. Export the tag data with the image
If you have an authorized native runtime, run the included wrapper from the extracted project directory in the environment where that runtime works:
ASEPRITE_BIN=/path/to/aseprite bash export-native.sh assets/original.ase runs/nativeChoose a new output directory. The wrapper exports both example sizes and checks an editable save/reopen. Its 1× export uses this shell excerpt:
common=(--batch --list-tags "$input" --trim --sheet-type packed \
--filename-format '{frame}' --format json-array)
"$native_bin" "${common[@]}" --sheet atlas-1x.png --data atlas-1x.jsonInside the wrapper, $input is the resolved original path, $native_bin is your supplied executable, and the working directory is the new runs/native destination. Numbered keys "0"–"5" are deliberate: this Phaser helper looks up numeric frame keys.
To inspect your new export in the demo, copy both runs/native/atlas-1x.png and atlas-1x.json to their corresponding assets/atlas-1x.* paths. The server serves its explicit asset allowlist, rather than arbitrary files in runs/.
3. Load the pair and create the named animations
The included scene uses this call in preload():
this.load.aseprite("tagged", "assets/atlas-1x.png", "assets/atlas-1x.json");After loading, create() validates the request and creates the real animations:
const names = ["walk", "reverse", "bounce"];
validateTags(this.cache.json.get("tagged"), names);
this.anims.createFromAseprite("tagged", names);
this.add.sprite(40, 130, "tagged", "0")
.setOrigin(0).setScale(10).play({ key: "walk", repeat: -1 });validateTags, imported from the included consumer.mjs, checks numbered frame keys, positive durations, requested names and in-range tag endpoints. Phaser’s helper reverses reverse and enables yoyo for pingpong. Keep the exported per-frame durations instead of replacing them with one assumed FPS.
4. Run and inspect the result
With Node 24+ in the extracted directory, run:
npm ci --ignore-scripts
npm test
npm startOpen http://127.0.0.1:8178. Phaser is served from the exact local package and lockfile, with no CDN. If the port is occupied, set ASEPRITE_PHASER_PORT before starting. Opening the HTML directly as a file does not run this loader project.
The top row plays all three tags. Pause/Resume controls their actual Phaser animation states. The scene uses pixelArt: false, antialias: false, roundPixels: false, integer positions and 10× sprite scale.
The recorded run observed the three orders above and all ten distinct tag/frame states. Their actual rendered crops matched the original frames composited over the demo background.


5. Check wrong tags and keep timing claims bounded
Requesting missing produced the example guard’s missing-tag error; a tag ending at frame 99 produced its range error. Neither created an invalid animation. These are application checks before the helper call; Phaser itself is not claimed to throw those messages.
A separate hidden Phaser sprite stayed on frame 0 after 89 ms, advanced to 1 after 1 ms more, advanced to 2 after 149+1 ms, and completed after 59+1 ms. These were explicit update deltas, separate from the live game-loop trace. They verify native duration handling, not elapsed-time delivery or an FPS guarantee.
This proof covers the original document, historical CLI and pinned Canvas consumer. It does not establish current Aseprite menus, every ASE feature, WebGL/mobile behavior or production performance.
Original source and artwork are MIT-licensed; no native binary is bundled. The separately source-built Aseprite runtime used GPLv2. Phaser and its pinned eventemitter3 dependency use MIT; keep the included notices. Native Linux/Xvfb export is distinct from a current desktop GUI workflow.