pixel-sprite-maker: spritec - .sprite text format -> png/jpg/svg + sprite sheets

- .sprite format: single-char palette keys (hex/rgb()/CSS names/none), grid
  rows, '.' transparent by default, max 256x256 per sprite
- render/sheet/info/preview subcommands; sheets name themselves
  <base>_<cellW>x<cellH>_<cols>x<rows>.<ext> (row-major)
- SVG output RLE-merges pixel runs; JPG composites over --bg
- go tests for parser, colors, scaling, svg, sheet layout

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmdG9GqfSWCzts7AkDwRDh
This commit is contained in:
2026-07-14 02:21:57 +02:00
parent 581e37acd8
commit 23135a96d1
21 changed files with 1444 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
# pixel-sprite-maker (`spritec`)
Turns human/agent-readable `.sprite` text files into pixel art (**PNG, JPG, SVG**)
and combines several sprites into **sprite sheets / animation strips**.
Written in Go, zero dependencies, single static binary.
## Build
```bash
# Arch/Garuda: sudo pacman -S go
cd pixel-sprite-maker
go build -o build/spritec . # or run the VS Code task "build pixel-sprite-maker"
go test ./...
```
## The `.sprite` format
One file = one sprite. Designed so an agent can *see* the result in the text:
```
# comment lines start with '#'
sprite: coin # optional name
palette:
k = #1A1205 dark outline
y = #FFD700 gold
Y = gold CSS names work too — text after the color is a comment
grid:
..kkkk..
.kyyyYk.
kyyyYYyk
..kkkk..
```
Rules:
- **One character = one pixel.** Every grid row must be the same width.
- Palette keys are exactly one character (any unicode). `#`, `=`, `:` and
whitespace are not allowed as keys — so the number of colors is
practically unlimited (a-z, A-Z, 0-9, `!@%&*`, unicode…).
- `.` is **transparent by default**; override it in the palette if you want.
- Colors: `#RGB`, `#RGBA`, `#RRGGBB`, `#RRGGBBAA`, `rgb(r,g,b)`,
`rgba(r,g,b,a)` (alpha 0-255 or 0.0-1.0), all CSS named colors, `none`.
- Max **256x256** pixels per sprite. Sheets may exceed this; single frames may not.
## Commands
```bash
spritec render coin.sprite -o coin.png --scale 8 # png/jpg/svg from extension
spritec render coin.sprite --format svg # -> coin.svg
spritec render heart.sprite -o heart.jpg --bg '#222034' # jpg has no alpha: pick bg
spritec info coin.sprite # validate + palette stats
spritec preview coin.sprite # draw in the terminal (truecolor)
# Sprite sheets / animations — row-major (left→right, then top→bottom):
spritec sheet walk_1.sprite walk_2.sprite walk_3.sprite walk_4.sprite -o walk # 1 row
spritec sheet walk_*.sprite --cols 2 -o walkgrid # 2D: 2 columns x 2 rows
```
Flags: `-o` output, `--format png|jpg|svg`, `--scale n` (integer nearest-neighbour
upscale), `--bg color` + `--quality 1-100` (jpg only), `--cols n` (sheet only).
## Sheet output naming — read the layout from the file name
```
<name>_<cellW>x<cellH>_<cols>x<rows>.<ext>
walk_8x8_4x1.png = 8x8 px per frame, 4 columns, 1 row (animation strip)
tiles_16x16_4x2.png = 16x16 px per frame, 4 columns, 2 rows
```
Frame order is always **row-major**: index = `row * cols + col`, frame 0 is
top-left. If the frame count doesn't fill the grid, trailing cells are
transparent. In game code:
```
frameX = (index % cols) * cellW
frameY = (index / cols) * cellH
```
## Exit codes & errors
`0` on success, `1` on any error, `2` on missing command. Parse errors name
the exact line/row/column and what was expected, so an agent can fix the
file without guessing.
Examples live in [`examples/`](examples/); generated output in `examples/out/`.