workshop

← all creations

Platform Cat

sprites · created 2026-08-23

32×22 pixel sprite — a chunky black platform cat with a 2-frame idle bob-and-blink and a 4-frame grooming wash-up, drawn from an editable character map.

pixel-artcanvas

The unofficial eighth member of the Straphanger / Stand Clear / nyc-conductor / Subway Rat / Platform Pigeon / Subway Cockroach platform: a sooty black cat sitting on its haunches, front paw tucked, tail wrapped around toward the front — the one who’s seen everything and clocks out at the end of the shift like everyone else. Two animation loops — an idle (still body, a slow tail-tip lift, blink) and a grooming wash-up (four-frame paw raise: chest, cheek, ear, back down) — plus amber eyes and tiny pink toe beans, because even a soot-black transit cat gets one bright detail.

Reuse

Render at integer scales with nearest-neighbor filtering or the edges smear. Idle plays at 2 fps, groom at 6 fps (ANIMATIONS in the module carries both). The cat is drawn near-black — pick a mid-to-light background behind it (the demo uses a warm platform gray) or it disappears the way it would on an actual subway platform at 2am.

Source

No .aseprite — the canonical source is source/platform-cat.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 up to three layers composited on the 32×22 canvas, back to front: TAIL (a full-width layer, fixed anchor row — the rump silhouette already covers everything above it, so the tail only needs to fill the open gap underneath: drop below the body, sweep right toward the front paws, curl the tip up into the pocket between rump and paw), BODY (the sitting silhouette — head, ears, torso, tucked front leg and paw, all baked into one static grid, drawn at the frame’s bob offset — the only layer that moves vertically), then PAW (a small local grid placed at a per-frame {left, top}, present only in groom frames — the raised mitt that sells the wash-up, same “small piece travels alone” trick platform-pigeon uses for its head-bob strut). Idle frames carry no paw entry at all — that absence is “not grooming right now,” not a fourth empty-pattern lookup.

Gotchas

Port notes

paintFrame is ~25 lines of grid walking with no DOM dependency beyond a 2D context — same shape as platform-pigeon’s (fixed body + a small traveling local grid) — so a DragonRuby port translates directly: keep the grids as strings, map cells to args.outputs.solids, or just consume cat-sheet.png as a spritesheet with source_x = frame * 32.