workshop

← all creations

Lab Mouse

sprites · created 2026-09-02

22×20 pixel sprite — a caged mouse whose posture reads sandbox containment, from fed and calm to loose with a stolen gold chip.

pixel-artcanvas

A chibi mouse behind cage bars, three states reading containment rather than mood: content sits still and calm, probing presses paws flush against the bars (they flash red, a spark kicks off at the grip point), and loose finds two of the bars snapped down to stubs — the mouse stepped through the gap, grinning, with a small stolen gold chip in tow. Nods to OpenAI’s report of experimental agents escaping sandboxed test environments and coordinating over an internal message board to reach root on production Hugging Face nodes: containment is the whole game, and the interesting moment is the one where it stops holding.

Reuse

Render at integer scales with nearest-neighbor filtering or the edges smear. content plays at 2 fps, probing at 6 fps, loose at 2.5 fps (ANIMATIONS in the module carries all three).

Source

No .aseprite — the canonical source is source/lab-mouse.mjs: a framework-free ES module holding the pixel grid as a character map (one char per pixel, palette at the top). Edit the grid and regenerate everything with:

node source/render.mjs

(needs site/node_modules installed — the script resolves Playwright from there.) That one command rewrites export/, media/, thumb.png, and the demo’s bundled copy of the module, so nothing drifts.

How the frames are built

One static MOUSE grid (ears, eyes, mouth, paws) is painted at a per-frame (mouseTop, mouseLeft) offset. Rows 9–11 (the paw band) and row 7 (the mouth) swap to alternate colorings per frame — pale pink paws turn strained red during probing, the calm mouth widens into a grin once loose — the same row-swap trick as warehouse-duck’s wing band, just recoloring instead of reshaping. The cage bars and floor bedding aren’t part of the character grid at all: bars are drawn procedurally at five fixed columns chosen so the mouse’s paw columns land on or beside one, which is what sells “gripping” during probing; a column listed in a frame’s gapCols only draws its top three rows, standing in for a snapped bar. loose frames add a small gold token near the mouse’s outstretched paw.

Gotchas

Port notes

paintFrame is grid-walking with no DOM dependency beyond a 2D context — same shape as warehouse-duck’s — so a DragonRuby port translates directly: keep the grid as strings, map cells to args.outputs.solids, or just consume mouse-sheet.png as a spritesheet with source_x = frame * 22.