SPRITE SHEETS
One character image in, a labelled sprite sheet out
Give PX-Art a base character image, an action, a facing, a frame count and whether the action loops. You get back a trimmed sprite strip with every frame aligned to a shared scale and baseline, editable frame by frame, and exportable as a sprite sheet PNG with a manifest that names each animation row plus an Aseprite-compatible JSON, GIF and APNG.
What you provide
| Input | Notes |
|---|---|
| Base character image | The identity anchor. Generate it in the characters module or bring your own. |
| Reference images | Optional. Used for look, not for copying composition. |
| Action | Ten common actions are offered directly; anything else you describe in free text is matched to an internal choreography profile. |
| Facing | One of eight. south, north, east, south-east and north-east are generated; west, south-west and north-west are mirrored from their counterparts. |
| Frame count | 1 to 15 frames per action. |
| Loop flag | Changes how frames are sampled — see below. |
What happens between the request and the strip
The action pipeline is not one image call. It is a sequence built to keep a moving character recognisable as the same character:
- Anchor the poseFor non-front facings, a locked turn image is produced first: the front base rotated to the target viewpoint as a single standing pose.
- Composite a chroma canvasThe subject is placed on a keyed background with a fixed camera so the background can be removed cleanly later.
- Image-to-videoA two-second clip is generated from that canvas — motion comes from a video model, not from independently sampled stills.
- Decode every frameffmpeg extracts the full frame set, then frames are sampled according to the delivery semantics you asked for.
- Key out and trim as a setThe chroma background is removed, then the whole sequence is cropped to the union of all frames, so translation across the animation survives instead of every frame being centred independently.
- Assemble the stripFrames are laid into a strip with one scale and one baseline for the whole sequence.
- Palette post-processingColours are conformed according to the game's style profile.
- Quality gate, then storeFacing drift, inter-frame coherence and ground contact are checked before the result is saved into the actions module.
Keeping it the same character
Consistency here is three concrete mechanisms, not a prompt instruction:
Palette lock
A shared palette is extracted from the character's base image, and every action for that character reuses it. Switching from idle to attack does not shift the character's colours.
Body-size profile plus scale reference
Characters are classed as small, normal, tall or giant, and normalised deterministically against a proportion reference with a horizon line and a head line, so characters in one game stay in scale with each other.
Cached turn anchor
Every non-front facing is anchored to its locked turn image, which fixes which hand holds the weapon and which limbs are near and far. It is cached per character and facing, so all later frames in that direction inherit the same decision.
The same machinery drives portraits, avatars and battle sprites — see characters and animation for the view types.
Frames, timing and loop semantics
- Looping actions are sampled over the half-open range from the first frame up to but excluding the last, so a walk cycle does not stutter on a duplicated pose at the seam.
- One-shot actions keep their true first and last frames, because the wind-up and the settle are the point.
- Playback rate is 6 to 15 fps; duration is simply frames divided by fps, so a 6-frame walk at 12 fps is half a second.
- A dense frame set is retained alongside the delivered strip, capped at 30 frames. Delete a frame you dislike and a real frame can be pulled in to replace it — one that already shares the delivered strip's scale and baseline, rather than a freshly generated stranger.
Editing what came back
The results desk is where a sheet becomes usable. You can step through frame by frame, delete frames, redo the whole run, or patch a single frame locally when one hand or one shadow is wrong. Local edits cost 2 credits per patch, which makes fixing one frame far cheaper than regenerating a 10-credit action.
Deleting frames is usually better than regenerating. The surviving frames keep their alignment; a regenerated sequence is a new sample and may drift from the version you already approved.
Exporting
Export packs a ZIP per character containing every state you selected:
slime/
slime-sprite-sheet.png atlas, one row per animation
slime-manifest.json rows, pivots, per-frame rects
slime-sprite-sheet.json Aseprite-compatible frames + frameTags
frames/walk/slime-frame-00.png ...
gif/slime-walk.gif
apng/slime-walk.png full alpha, unlike GIF
The manifest is the part an engine or an agent reads:
{
"app": "px-art",
"schema": "perfectpixel.sprite/2",
"version": 2,
"character": "slime",
"sheet": {
"image": "slime-sprite-sheet.png",
"width": 1536, "height": 384,
"cellWidth": 256, "cellHeight": 256,
"trimmed": true
},
"animations": {
"walk": {
"row": 0, "frames": 6, "fps": 12, "loop": true,
"durationMs": 83,
"pivot": { "x": 128, "y": 240 },
"rects": [ { "x": 0, "y": 0, "w": 256, "h": 256 } ],
"trims": [ { "x": 62, "y": 40, "w": 130, "h": 200 } ]
}
}
}
pivot is the foot anchor at the bottom centre of a cell — the value you feed to your engine so a character stands on the ground instead of floating. rects are absolute coordinates on the sheet; trims are the content bounding box inside each cell, which is what you want for tight hit boxes. The Aseprite-compatible file carries frames, frameTags and per-frame duration in milliseconds, so importers built for that format pick up the animation names without extra work.
Reading a sheet from a coding agent
Every stored strip carries its frame count and size, so an agent calling search_assets sees "kind": "action", "frames": 6 and the pixel dimensions before it downloads anything. preview_assets confirms it visually, get_asset_downloads issues a short-lived URL. Details on the MCP page.
Getting it into your game
Slice by cellWidth and cellHeight, take the animation names and fps from the manifest, and set your texture filter to nearest for pixel styles. Importers that already speak the Aseprite JSON layout can consume the second JSON file directly. There is a thin Godot-side adapter for scene bundles; Unity support is not claimed.
Limits and things to check
- Generation is probabilistic. A run can miss the description. Check before production; that is what the results desk and frame-level edits are for.
- The video stage can refuse. The pipeline depends on the model obeying the chroma-key background and fixed camera. When it does not, the run reports an error and asks for a regenerate rather than shipping broken frames.
- Mirrored facings are mirrors. Asymmetric details — a scar, a shoulder pad, a weapon in one hand — flip with the image on
west,south-westandnorth-west. - One frame is a still. A 1-frame action is a pose, not an animation; the loop-sampling rules only mean something from 2 frames up.
- Rights are yours to verify. Commercial use is allowed for legally generated assets, subject to third-party rights, applicable law and AI-provider terms; results are not guaranteed exclusive or registrable.
- Composition needs a desktop. Sheets can be reviewed anywhere, but the Arrange workspace expects a large canvas and precise pointer control.
An action costs 10 credits when frame-based and 18 when video-based; local frame repair is 2 credits per patch. Failed or partially failed runs refund the unfinished portion automatically. See pricing; formal checkout is still under review and not open yet.
FAQ
What do I need before generating a sprite sheet?
One base character image, an action, a facing, a frame count between 1 and 15, and whether the action loops. Reference images are optional and are used for look rather than composition.
How does the character stay the same across idle, walk and attack?
Three mechanisms: a palette extracted from the base image and locked across every action of that character; a body-size profile (small, normal, tall, giant) normalised against a proportion reference with horizon and head lines; and a cached locked turn image per character and facing that fixes which hand holds what and which limbs are near or far.
Why does a looping animation drop the last frame?
Because it would duplicate the first pose. Looping actions are sampled from the first frame up to but excluding the last, which removes the stutter at the seam. One-shot actions keep their true first and last frames.
Can I fix a single bad frame without regenerating everything?
Yes. You can delete frames, patch one frame locally for 2 credits, or redo the whole run. A dense frame set of up to 30 frames is kept, so a deleted frame can be replaced by a real frame that already shares the strip's scale and baseline.
What file formats does export produce?
A ZIP containing the sprite sheet PNG, a manifest JSON with per-animation rows, pivots and frame rectangles, an Aseprite-compatible JSON with frameTags and per-frame durations, individual frame PNGs, a GIF per state and an APNG per state for full alpha.
Where is the character's ground contact point?
In the manifest, as the animation's pivot — the foot anchor at the bottom centre of the cell. Use it as your sprite origin so characters stand on the floor rather than floating.
How many directions can one action have?
Eight facings. Five are generated (south, north, east, south-east, north-east) and three are produced by mirroring (west, south-west, north-west), which means asymmetric details flip on the mirrored side.
Related
Generate your first sprite sheet
Start a game project, make a character, and take a walk cycle from base image to exported sheet with a manifest your engine can read.
Create a free accountSee pricingNew accounts start with 20 credits. Formal checkout is still under review and not open yet.