workshop

← all creations

Platform Pigeon

sprites · created 2026-08-23

30×20 pixel sprite — a chunky rock pigeon with a 2-frame idle bob-and-blink and a 4-frame head-bob strut cycle, drawn from an editable character map.

pixel-artcanvas

The unofficial sixth member of the Straphanger / Stand Clear / nyc-conductor / Subway Rat platform: a rock pigeon, dark head fading into an iridescent green-to-violet neck, light gray body with two black wing bars, orange-red eye and legs. Two animation loops — an idle sit (gentle bob, an eye that blinks shut on the second frame) and a strut (four-frame walk with the head snapping forward on the plant beat and pulling back on the lift beat — the actual mechanism behind a pigeon’s head-bob, not just a vertical wobble).

Reuse

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

Source

No .aseprite — the canonical source is source/platform-pigeon.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 composites three layers, back to front: BODY (torso, tail, wing bars and neck markings — all baked into one static grid, since none of it moves), LEGS (a full-width layer, three foot-placement patterns for the walk), and HEAD — a small local grid placed at a per-frame (headX, headY) offset instead of a fixed anchor. That’s the actual mechanism behind the strut: the head isn’t just bobbing vertically, it’s traveling forward on the plant beat and pulling back on the lift beat, same as a real pigeon using its head as a fixed visual reference while the body moves underneath it. Six frames come from one body grid, three leg patterns, and two head positions — not six full redraws.

Gotchas

Port notes

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