workshop

← all creations

Hot Dog Cart

sprites · created 2026-08-27

27×27 pixel sprite — a classic NYC umbrella hot dog cart with a 2-frame steam-drift idle and a 4-frame serving loop, a gloved hand rising to hold one up.

pixel-artcanvas

A street-corner fixture: a striped umbrella on a pole, a stainless box with a serving window and ledge, two wheels underneath. A wisp of steam curls up past the umbrella’s peak at rest — then a gloved hand rises up beside the pole with a hot dog held high before dropping back out of sight.

Reuse

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

Source

No .aseprite — the canonical source is source/hot-dog-cart.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

Three layers, back to front. CART is one static grid — umbrella, pole, box, wheels — painted a few rows down from the frame’s top edge, leaving headroom above the umbrella’s peak for the second layer: STEAM, a small grid anchored over that peak whose pattern (not position) carries the drift, the same trick scout-drone’s glow bar uses for its sweep. The third layer, ARM, is a small local grid — glove plus hot dog — placed at a per-frame (armX, armY) offset instead of a fixed anchor, exactly like court-ace’s racket arm; idle frames simply carry arm: null and skip the layer entirely. The arm’s travel is capped so its highest point sits just below the umbrella — it rises alongside the pole, never through the canopy.

Gotchas

Port notes

paintFrame is grid-walking with no DOM dependency beyond a 2D context — same shape as court-ace’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 cart-sheet.png as a spritesheet with source_x = frame * 27.