workshop

← all creations

Subway Rat

sprites · created 2026-08-22

30×14 pixel sprite — a chunky subway rat with a 2-frame idle bob-and-blink and a 4-frame scurry cycle, drawn from an editable character map.

pixel-artcanvas

The unofficial fifth member of the Straphanger / Stand Clear / nyc-conductor platform: a rounded, low-slung rat with a pointed snout, one visible ear, and a thin curling tail. Two animation loops — an idle sit (gentle bob, an eye that blinks shut on the second frame) and a scurry (four-frame run cycle, legs alternating plant/lift, tail flicking side to side).

Reuse

Render at integer scales with nearest-neighbor filtering or the edges smear. Idle plays at 2 fps, scurry at 8 fps (ANIMATIONS in the module carries both).

Source

No .aseprite — the canonical source is source/subway-rat.mjs: a framework-free ES module holding the pixel grids as character maps (one char per pixel, palette at the top). Edit a 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

A frame is three layers composited on the 30×14 canvas, back to front: TAIL (fixed anchor at the rump), LEGS (fixed anchor, peek out from under the torso), then BODY on top at the frame’s bob offset — the only layer that moves vertically. Same split as scout-drone’s glow/dome: only the parts that actually move need more than one grid. Six frames come from one body grid, three leg patterns (stand, strideA, strideB), three tail patterns (curl, swishA, swishB), and an eye-color swap for the blink — not six full redraws.

Gotchas

Port notes

paintFrame is ~25 lines of grid walking with no DOM dependency beyond a 2D context — same shape as scout-drone’s and mech-strider’s — so a DragonRuby port translates directly: keep the grids as strings, map cells to args.outputs.solids, or just consume rat-sheet.png as a spritesheet with source_x = frame * 30.