Skip to content

Generate block-robot pixel art sprites programmatically #235

Description

@williamthorsen

Problem

The catwalk visualization uses placeholder SVG sprite sheets (subagent.svg and orchestrator.svg) that render as simple colored rounded rectangles with text labels (e.g., "S0", "O0"). These were introduced in PR #228 as temporary stand-ins. The result is that all animation states look identical — you can't visually distinguish idle from working from celebrating.

Context

  • Generator script: packages/factory/scripts/generate-placeholder-pngs.ts — writes SVG sprite sheets to catwalk/sprites/assets/
  • Sprite format: 128×96 SVG, 4-column × 3-row grid of 32×32 frames
  • Frame layout (from sprite-definitions.ts):
Col 0 Col 1 Col 2 Col 3
Row 0 Idle 1 Idle 2 Walking Resting 1
Row 1 Working 1 Working 2 Working 3 Resting 2
Row 2 Celebrating 1 Celebrating 2 Concerned Resting 3

Solution

Enhance generate-placeholder-pngs.ts to draw block-style robot silhouettes using SVG <rect> elements as individual pixels.

Composable body parts approach

Rather than defining full 32×32 pixel grids for each of the 24 frames, define reusable body parts (head, torso, arms, legs) as small pixel arrays with position offsets. Each animation frame is a pose — a composition of body parts placed at specific positions:

interface BodyPart {
  pixels: number[][];  // small grid, e.g. 8×6 for a head
  offsetX: number;
  offsetY: number;
}

type Pose = BodyPart[];

This makes poses easy to author (change an arm position, not redraw 1024 pixels) and keeps body proportions consistent across frames.

Robot silhouettes

  • Subagent (~14×22px): Compact worker robot — boxy head with visor strip, rectangular torso, short sturdy limbs. Neutral metallic palette.
  • Orchestrator (~16×24px): Taller command unit — wider head with antenna/crown element, broader chest. Gold-tinted palette.

Color palettes

Subagent (neutral metallic):

Index Role Color
0 Transparent
1 Shadow #2a2a3e
2 Dark #4a4a6e
3 Mid #7777aa
4 Light #9999cc
5 Highlight #bbbbee

Orchestrator (gold command-unit):

Index Role Color
0 Transparent
1 Shadow #3a2a0e
2 Dark #6e5a2e
3 Mid #aa8844
4 Light #ccaa44
5 Highlight #eedd88

Code organization

Multi-file module under packages/factory/scripts/:

generate-placeholder-pngs.ts   # entry point — orchestrates + writes SVGs
sprites/
  palettes.ts                  # Palette type + color ramp definitions
  subagent-poses.ts            # Subagent body parts + 12 pose compositions
  orchestrator-poses.ts        # Orchestrator body parts + 12 pose compositions
  svg-renderer.ts              # Types (BodyPart, Pose) + pose→SVG rendering

Pose descriptions per frame

Position State Pose
(0,0) Idle 1 Standing, arms at sides
(1,0) Idle 2 Subtle variation (slight arm/head shift)
(2,0) Walking Mid-stride, one leg forward
(3,0) Resting 1 Relaxed stance, arms down
(0,1) Working 1 Arms raised, start of work motion
(1,1) Working 2 Arms extended, mid-work
(2,1) Working 3 Arms lowered, completing work cycle
(3,1) Resting 2 Slight slouch variation
(0,2) Celebrating 1 Arms raised high
(1,2) Celebrating 2 Arms in V-shape
(2,2) Concerned Hunched, arms close to body
(3,2) Resting 3 Powered-down look

Why this approach

  • Zero new dependencies — pure SVG generation, same as today
  • Deterministic and reproducible — run the script, get the same sprites
  • Composable — change a body part once, all poses using it update
  • Drop-in replacement — same output paths, dimensions, and grid layout; no loader or actor changes
  • Bridge to Create pixel art for catwalk visualization #222 — provides usable sprites now while real pixel art is created later

Key files

  • packages/factory/scripts/generate-placeholder-pngs.ts — entry point to enhance
  • packages/factory/src/client/game/sprites/sprite-definitions.ts — frame layout reference (read-only)
  • packages/factory/src/client/visualizations/catwalk/sprites/assets/ — output directory

Acceptance criteria

Must have

  • Enhanced generate-placeholder-pngs.ts generates block-robot sprite sheets (not simple rectangles)
  • Subagent and orchestrator have visually distinct silhouettes
  • All 12 frames (4×3 grid) have state-appropriate poses matching the layout in sprite-definitions.ts
  • Sprites have transparent backgrounds
  • Generated SVGs are drop-in replacements (same path, dimensions, grid layout)
  • Code organized as multi-file module (scripts/sprites/ with palettes, poses, renderer)
  • Poses built from composable body parts, not full 32×32 grids
  • No new runtime dependencies (dev script dependencies acceptable if justified)
  • All existing tests pass (typecheck, lint, test)

Should have

  • Subagent uses neutral metallic palette that reads well against midnight blue (#1a1a2e)
  • Orchestrator uses gold-tinted palette visually distinct from subagent
  • Animation frames within each state show meaningful pose variation (not just color shifts)
  • Palette constants extracted for easy tuning

Nice to have

  • HTML preview page generated alongside sprites for visual verification
  • Comments documenting body part dimensions and pose descriptions

Related issues

Metadata

Metadata

Labels

featureAdded or improved external functionalityscope:factory

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions