Each asset is stored as a single transparent PNG that may pack several
individual sprites. This document explains how a sheet is laid out and how to
slice it using the geometry from metadata.json.
- Format: 32-bit RGBA PNG with an alpha channel.
- Location:
sprites/<category>/<id>.png. - Tile unit: sprites are authored on a tile grid. An object that is
w × htiles wide and tall occupies aw × hblock of the base sprite cell.
A single sheet may hold many frames. The total is nSprites, distributed across
these dimensions (all found in the asset's geometry block g):
- Size —
w×htiles per frame. - Layers —
layersstacked draw layers per frame (e.g. base + overlay). - Patterns —
px×py×pzvariants (e.g. facing direction, color variant, or state). - Phases —
phasesanimation frames in a cycle.
In the general case:
nSprites = w * h * layers * px * py * pz * phases
- Read the asset's geometry from
metadata.json.things["<id>"].g. - Determine the base sprite cell size used by the sheet (commonly a fixed tile
size such as 32×32 or 64×64 pixels, scaled by
w/h). - Walk the sheet in row-major order, extracting
nSpritescells. - Index the extracted cells by
(layer, px, py, pz, phase)to address a specific variant/frame.
Because every count needed to reconstruct the layout lives in the metadata, you can slice sheets generically without hardcoding per-asset rules.
- Animations: iterate
phasefrom0tophases - 1to play a cycle. - Directions: many creatures encode facing as a pattern axis (
px/py). - Static objects: items with
phases = 1and all pattern counts= 1are a single image — no slicing required. - Layers: when
layers > 1, composite the layers in order for the final frame.
See usage.md for concrete loading examples.