Expand description
2D pixel art as plain text, in safe Rust with zero dependencies.
A spritebox file defines palettes, sprites, procedural textures, animations, tilesets, tilemaps and pixel fonts as text that a person or an AI assistant can write, read and diff. The crate validates it with exact diagnostics, renders it to RGBA8 images and PNG files, and draws preview sheets to review a whole file at a glance. The same text gives the same pixels on every platform.
use spritebox::{Color, Document, PreviewOptions};
let document: Document = "
palette dawn
. transparent
k #1a1c2c
o #f4b41b
y #ffe478
w #ffffff
sprite coin 8x8 palette=dawn
..kkkk..
.kooyyk.
kooyywok
kooyyook
kooooook
koooooyk
.koooyk.
..kkkk..
".parse()?;
let coin = document.sprite("coin").unwrap().render();
assert_eq!(coin.pixel(5, 2), Some(Color::WHITE));
let png = coin.to_png();
let sheet = document.preview(&PreviewOptions::default())?;§The text format
A definition starts at the first column with a directive and a name; the lines
under it are indented with spaces (any number, the same for every line of a
block). ; starts a comment that runs to the end of the line. Blank lines are
ignored. Names use ASCII letters, digits, _ and -.
import NAME brings in the definitions of another file, loaded by a function the
caller gives Document::parse_with_loader; the crate itself reads no files.
§Palettes
palette dawn
. transparent
k #1a1c2c
o #f4b41b80
palette dusk from=dawn ; dawn's keys, then these replace or add
o #b86f50Each line is a key, one character, and a color: #rrggbb, #rrggbbaa or
transparent, in sRGB with alpha that is not premultiplied. Keys may be any
character but spaces, control characters and ; ( ) , =. A palette may hold at
most Limits::max_palette_colors keys.
§Sprites
sprite coin 8x8 palette=dawn
..kkkk..
...WxH is the size in pixels, and each of the H rows is one word of W keys of
the palette. palette= may be left out when the file defines one palette.
slice=N or slice=LEFT,TOP,RIGHT,BOTTOM marks a nine-slice panel, whose
Insets the metadata states.
Instead of rows, a sprite may have layers, drawn bottom first, each with rows or made from another sprite of the same size and palette:
sprite hero 16x16 palette=dawn
layer body
...
layer shadow = blob:offset(1,1)§Procedural textures
texture grass 16x16 palette=dawn seed=7
noise cell=8 octaves=3 roughness=60
ramp h g g G
dither bayer4Seeded value Noise that wraps, mapped onto a ramp of keys with Dither; a
texture is a sprite, usable as a layer, a tile or anything else a sprite is.
§Derived sprites
sprite NAME = CHAIN builds a sprite from another with a modifier chain: a name
and :modifiers applied left to right, without spaces, such as
coin:flip_x:swap(dusk):outline(k). The modifiers are flip_x, flip_y, rot90,
rot180, rot270 (clockwise), offset(dx,dy), pad(n), scale(n),
swap(palette), outline(key), size(WxH) and shadow(key,dx,dy); Sprite
has a method for each. A chain may start from a sprite or from a tileset’s tile,
written TILESET.TILE.
§Animations
animation coin_spin loop
coin 6
coin_edge 6
coin_edge:flip_x 6One frame per line: a sprite or a modifier chain, and the ticks it shows (Diamon
steps at 60 a second). loop, the default, or once. A chain’s trailing flips are
flags of the Frame, since engines flip sprites when they draw them.
§Tilesets and tilemaps
tileset ground 8x8 palette=dawn
tile brick
...rows...
terrain dirt 47
island
...rows...
h_strip
v_strip
inner
fill
tilemap level tileset=ground
legend
. empty
# dirt solid
b brick solid
map
..bb..
######A terrain’s pieces are whole tiles; spritebox assembles its 16 or 47 variants
from their quarters (see Piece::for_quarter and Scheme::variant). A map
cell of a terrain takes the variant for its neighbours. Tileset and
Tilemap hold the result: tile indices from 1, 0 for an empty cell, and the
solid indices. The README documents the rules in full.
§Pixel fonts
font hud height=7 baseline=7 line_height=9
glyph A
.###.
#...#
...Rows of # and .; characters as themselves or U+003B. Font::render draws
text, and Font::to_ttf writes TrueType whose outlines are the pixels as
squares, with the em at the glyph height, so it is crisp at integer multiples of
its pixel size.
§Lint
Document::lint reports art that is valid but strays from pixel-art practice,
such as noise pixels or unused palette keys, as Warnings with a stable
LintCode and the position of the pixel’s character in its row.
lint=allow(CODE,...) on a definition, and lint allow CODE... in a file, allow
codes on purpose.
§Errors
Errors are Error values with a stable ErrorCode and, for text, the
Position of the error: its line and its column in characters.
Document::parse returns the first; check returns all of them. Parsing is
bounded by Limits, and malformed input gives an error, never a panic.
§Output
Sprite::render gives an Image: RGBA8 pixels, sRGB-encoded and not
premultiplied, tightly packed, top row first. Document::atlas packs every
sprite into one texture, with each one’s Rect and the animations’ frames, as
structs and as JSON, and Document::export adds a texture for each tileset, the
tilemaps and a TrueType file for each font. png encodes and decodes PNG files, and
Document::preview draws a preview sheet.
Modules§
- neighbours
- Neighbour bits of an autotile mask, clockwise from north.
- png
- PNG encoding and decoding, with the crate’s own DEFLATE, zlib, CRC-32 and Adler-32.
Structs§
- Animation
- An animation: frames shown in order, each for a number of ticks.
- Atlas
- Every sprite of a document in one texture, and where each one is.
- Atlas
Animation - An animation, with the atlas rectangle of each frame.
- Atlas
Frame - Atlas
Options - How sprites are packed into an atlas.
- Background
- Backgrounds: finite scenes, surfaces and parallax
- Background
Builder - Background
Export - Background
Export Options - Background
Flat Export - Background
Layer - Background
Layer Export - Background
Placement - Background
Render Options - Color
- A color: sRGB-encoded red, green and blue, and an alpha that is not premultiplied.
- Document
- A parsed and validated spritebox file.
- Error
- An error with a stable category, human-readable context and, for errors in text, the position where it was found.
- Export
- The files of a document: see
Export::files. - Export
Options - How a document is exported.
- Font
- A pixel font: glyphs of one height, with a baseline and a line height.
- Font
Export - A font as a TrueType file.
- Frame
- One frame of an
Animation. - Glyph
- One glyph: a grid of pixels as tall as its font, and an advance.
- Gradient
- Gradient
Stop - Group
- A group: sprites that belong together, such as the icons of an inventory.
- IconSet
- Icons with a shared size, in authored order.
- Image
- An RGBA8 image: sRGB-encoded, not premultiplied, tightly packed rows, top row first.
- Insets
- The borders of a nine-slice panel, in pixels from each edge: the corners keep their size while the edges and the middle stretch.
- Kern
Pair - An adjustment in pixels between two glyphs.
- Layer
Options - Limits
- Bounds on input and output, checked while text is parsed, before images are allocated and while PNG files are decoded.
- Lint
- What
Document::lintfound: the first warnings, and how many of each code there are in all. - Lint
Options - What
Document::lintchecks. - Noise
- Seeded value noise that wraps around a
width×heightarea, so a texture tiles with itself. - Palette
- A named set of colors, each under a one-character key.
- Placement
Options - Position
- A place in text: a 1-based line, and a 1-based column counted in characters.
- Preview
Options - How a preview sheet is drawn.
- Profile
- Profile
Options - A profile uses unnormalized wrapped value noise. Heights are y boundaries.
- Ramp
- A ramp: the keys of a palette that shade one material, dark to light.
- Ratio
- Rect
- A rectangle of a texture in texels, from its top-left corner.
- Region
- A sprite’s place in an atlas.
- Scatter
Options - Screen
- A screen with a finite pixel canvas and ordered sprite placements.
- Screen
Item - A sprite chain placed on a screen.
- Sprite
- A sprite: a grid of palette keys in one or more layers, and the palette that colors them.
- State
Set - A control’s states, each referring to an ordinary named sprite.
- Surface
- An immutable finite key grid, separate from sprites and atlas regions.
- Surface
Builder - Validated mutable authoring path;
finishreturns immutable keys. - Terrain
- A terrain of a tileset: the variants that autotiling chooses from.
- Text
Options - Layout of a static text sprite.
- Theme
- A named set of color replacements for one base palette.
- Theme
Export - Additional images for a theme. All use the base export’s region metadata.
- Tilemap
- A grid of tile indices of one tileset, with the indices that are solid.
- Tileset
- Tiles of one size and palette, in one texture.
- Tileset
Export - A tileset’s texture and what the metadata says of it.
- TtfOptions
- How a font is written as TrueType.
- Warning
- A lint warning: a stable code, a message and, when it is about a place in the text, its position.
- Weighted
Variant
Enums§
- Align
- Horizontal alignment within the text sprite’s width.
- Anchor
- Axis
- Background
Mode - Dither
- How noise values between two ramp keys are drawn.
- Error
Code - Stable error categories. Match on the code rather than the message.
- Fill
- How a panel’s edges and centre fill their destination.
- Gradient
Mode - Lint
Code - Stable lint categories. Match on the code rather than the message.
- Piece
- The hand-drawn pieces of a terrain, each a whole tile.
- Primitive
- A filled primitive, with signed pixel coordinates and half-open box bounds.
- Repeat
- Scatter
Amount - Scheme
- An autotiling scheme: which neighbours choose a terrain’s variant.
- Shadow
- The silhouette used by
Sprite::shadow. - Source
Ref
Constants§
- ATLAS_
FILE - The name of the atlas texture in exported files.
- BLOB_
MASKS - The 47 masks of the blob scheme in variant order: every 8-bit neighbour mask whose corner bits are set only where both neighbouring edge bits are, ascending.
- METADATA_
FILE - The name of the metadata file.
Functions§
- bayer
- The threshold of cell
(x, y)of the Bayer matrix of sidesize, a power of two: 0 tosize * size - 1, built asM(2n) = [[4M, 4M+2], [4M+3, 4M+1]]. - check
- Parses and validates
text, and returns every error found, ordered by position. An empty list means thatDocument::parse_withsucceeds. - check_
with_ loader check, loading imported files withloaderasDocument::parse_with_loaderdoes. Errors in an imported file name it inError::file.- reduce
- Clears each corner bit whose two neighbouring edge bits are not both set: a corner only matters when both edges beside it connect.
- scene_
seed - Stable FNV-1a-64 over length-prefixed UTF-8 components (u64 LE lengths), then u64 LE seeds, followed by the SplitMix64 finalizer. No path or order enters it.