Sprite Sheet Generator
Pack multiple images into one PNG atlas. Choose JSON or XML metadata when exporting.
Layout
Drop images here or click to browse
PNG, JPEG, WebP, GIF · up to 64 files
Sprite Sheet PNG + JSON: the TexturePacker format for Phaser and PixiJS
A sprite sheet JSON export is one packed PNG plus a .json file that lists every frame's name, x/y position, and width/height — the same structure TexturePacker produces. Phaser 3 loads it with this.load.atlas(); PixiJS loads it with the Spritesheet class. Upload your images, choose Grid for equal-size animation frames or Pack for mixed-size icons, then export as JSON Hash or JSON Array below.
JSON Hash vs. JSON Array — which do you need?
TexturePacker has shipped two JSON layouts for years, and engines only parse one of them correctly:
- JSON Hash (default) — frames sit in a
framesobject keyed by filename, e.g.frames["hero_walk_01"]. This is whatthis.load.atlas(key, png, json)andnew PIXI.Spritesheet(texture, atlasData)expect without extra parsing. - JSON Array — frames sit in an array under
textures[0].framesinstead of an object. Use it for Phaser'sthis.load.multiatlas()loader or any pipeline built around TexturePacker's array export.
Grid vs. Pack layout
- Grid — equal-size cells in rows and columns. Best for walk cycles, idle loops, and other frames that must line up for animation. Drag slots to reorder frames before exporting.
- Pack — max-rects bin packing that fits mixed-size UI icons and props into the smallest possible sheet, with no wasted padding between rows.
Loading the atlas in your game
Both formats decode with a couple of lines of code:
// Phaser 3
this.load.atlas('hero', 'spritesheet.png', 'spritesheet.json');
// later: this.add.sprite(x, y, 'hero', 'hero_walk_01');
// PixiJS v8
const texture = await PIXI.Assets.load('spritesheet.png');
const sheet = new PIXI.Spritesheet(texture, atlasJson);
await sheet.parse();
const sprite = new PIXI.Sprite(sheet.textures['hero_walk_01']);
Every frame keeps its original size - pixel coordinates map 1:1 to your source images. All packing and export runs locally in your browser; no file is uploaded to a server. Building for Friday Night Funkin' or a Flash-style pipeline instead? Use the Sprite Sheet & XML Generator.
FAQ
What's the actual difference between JSON Hash and JSON Array?
Both store the same frame data — name, x, y, width, height. Hash nests frames in an object keyed by filename so you look them up by name; Array nests the same frames inside a list under textures[0]. Pick whichever your loader documents; Phaser's single-atlas load.atlas() and PixiJS both default to Hash.
Do my images get uploaded to a server?
No. Packing, previewing, and exporting all happen in your browser. Nothing leaves your device until you download the ZIP.
How many images can I pack into one sheet?
Up to 64 PNG, JPEG, WebP, or GIF files per batch. If you need more frames than that, split them into two sheets and load both atlases in your engine.
Is this a free alternative to TexturePacker?
Yes. There's no install, no account, and no watermark — you get a TexturePacker-compatible PNG + JSON pair for Grid or Pack layouts at no cost.
Sprite Sheet PNG + XML: the TextureAtlas format for FNF and Flash
A sprite sheet XML export is one packed PNG plus a TextureAtlas .xml file that lists a <SubTexture> element — name, x, y, width, height — for each frame. Friday Night Funkin' mod tools, Starling, and most Flash-derived engines read this directly, with no JSON parsing involved. Upload your images, choose Grid for evenly-sized animation frames or Pack for mixed-size props, then export Sprite Sheet PNG + XML from the export menu.
Reading a TextureAtlas XML file
The XML mirrors the classic Sparrow/Starling shape — one root element wrapping one <SubTexture> per frame:
<TextureAtlas imagePath="spritesheet.png">
<SubTexture name="idle0000" x="0" y="0" width="64" height="64"/>
<SubTexture name="idle0001" x="64" y="0" width="64" height="64"/>
</TextureAtlas>
Frame names come straight from your uploaded filenames (minus the extension), so name your source images the way you want frames named in-engine — e.g. idle0000.png, idle0001.png for a Flixel/HaxeFlixel animation.
Grid vs. Pack layout
- Grid — equal-size cells in rows and columns, ideal for uniform animation frames like walk cycles and FNF character idle/sing loops. Drag slots to reorder before exporting.
- Pack — max-rects bin packing for mixed-size assets, useful for UI icons and props where frame dimensions vary.
Where TextureAtlas XML is used
- Friday Night Funkin' mods — character sprites typically ship as a
.png+.xmlpair loaded through HaxeFlixel'sFlxAtlasFrames.fromSparrow(). - Starling / Adobe AIR — the native
TextureAtlasclass parses this exact tag structure. - Custom or legacy engines — any XML parser can read frame rectangles without pulling in a JSON library.
All packing and export runs locally in your browser; no file is uploaded to a server. Building for Phaser or PixiJS instead? Use the Sprite Sheet Generator for JSON Hash or JSON Array output.
FAQ
Does the XML match the format Friday Night Funkin' mods expect?
Yes — each frame is a <SubTexture name x y width height> element inside one <TextureAtlas imagePath> root, the Sparrow/Starling shape that FlxAtlasFrames.fromSparrow() and most FNF mod-loading code expect.
Do my images get uploaded anywhere?
No. Packing, previewing, and exporting all happen in your browser. Nothing leaves your device until you download the ZIP.
How many sprites can one atlas include?
Up to 64 PNG, JPEG, WebP, or GIF files per batch. For larger character sets, export multiple sheets and load each XML file separately.
Can I get JSON instead of XML from the same upload?
Yes — switch the export mode to Sprite Sheet PNG + JSON and pick Hash or Array. Your uploaded images stay exactly as you left them.