Skip to main content

Crate spritebox

Crate spritebox 

Source
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  #b86f50

Each 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 bayer4

Seeded 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  6

One 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.
AtlasAnimation
An animation, with the atlas rectangle of each frame.
AtlasFrame
AtlasOptions
How sprites are packed into an atlas.
Background
Backgrounds: finite scenes, surfaces and parallax
BackgroundBuilder
BackgroundExport
BackgroundExportOptions
BackgroundFlatExport
BackgroundLayer
BackgroundLayerExport
BackgroundPlacement
BackgroundRenderOptions
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.
ExportOptions
How a document is exported.
Font
A pixel font: glyphs of one height, with a baseline and a line height.
FontExport
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
GradientStop
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.
KernPair
An adjustment in pixels between two glyphs.
LayerOptions
Limits
Bounds on input and output, checked while text is parsed, before images are allocated and while PNG files are decoded.
Lint
What Document::lint found: the first warnings, and how many of each code there are in all.
LintOptions
What Document::lint checks.
Noise
Seeded value noise that wraps around a width × height area, so a texture tiles with itself.
Palette
A named set of colors, each under a one-character key.
PlacementOptions
Position
A place in text: a 1-based line, and a 1-based column counted in characters.
PreviewOptions
How a preview sheet is drawn.
Profile
ProfileOptions
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.
ScatterOptions
Screen
A screen with a finite pixel canvas and ordered sprite placements.
ScreenItem
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.
StateSet
A control’s states, each referring to an ordinary named sprite.
Surface
An immutable finite key grid, separate from sprites and atlas regions.
SurfaceBuilder
Validated mutable authoring path; finish returns immutable keys.
Terrain
A terrain of a tileset: the variants that autotiling chooses from.
TextOptions
Layout of a static text sprite.
Theme
A named set of color replacements for one base palette.
ThemeExport
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.
TilesetExport
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.
WeightedVariant

Enums§

Align
Horizontal alignment within the text sprite’s width.
Anchor
Axis
BackgroundMode
Dither
How noise values between two ramp keys are drawn.
ErrorCode
Stable error categories. Match on the code rather than the message.
Fill
How a panel’s edges and centre fill their destination.
GradientMode
LintCode
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
ScatterAmount
Scheme
An autotiling scheme: which neighbours choose a terrain’s variant.
Shadow
The silhouette used by Sprite::shadow.
SourceRef

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 side size, a power of two: 0 to size * size - 1, built as M(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 that Document::parse_with succeeds.
check_with_loader
check, loading imported files with loader as Document::parse_with_loader does. Errors in an imported file name it in Error::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.

Type Aliases§

Result