Skip to content

Resonance Draw — Build Detail

What was built

Full implementation of site/games/resonance-draw/game.js (~370 lines, vanilla JS, zero deps).

Mechanic

  • 5 rounds, one wave type per round (Sine, Triangle, Sawtooth, Square, Complex — shuffled each game)
  • Top panel: static reference waveform rendered via Canvas2D; player must memorize/copy its shape
  • Bottom panel: player draws left-to-right with mouse or finger
  • Timer bar (9 seconds) counts down between the panels
  • On lift or timeout: scoring fires, audio stops, reveal overlay appears for 2.4s then auto-advances
  • Final screen: per-round bar chart + 80% win threshold

Scoring

score = max(0, round((1 - meanErr * 2.4) * 100))

Samples 120 evenly-spaced x-positions. At each x, computes |target_y - drawn_y| in normalized 0..1 space. Linear interpolation fills gaps in the drawn stroke. Missing coverage defaults to midline (0.5), penalizing partial draws. A flat midline scores ~24%; a close shape match scores 70-90%.

Audio

Web Audio API only — no audio files. OscillatorNode types match wave names (sine/triangle/sawtooth/square). "Complex" uses three layered sine oscillators at 220/660/1100 Hz. Wrapped in try/catch so it degrades gracefully if AudioContext is blocked. Master gain fades in over 200ms on round start, fades out on round end.

Input

  • pointerdown in draw zone starts a stroke; clears previous points
  • pointermove appends points; only rightward motion accepted (x must not regress >0.8%)
  • pointerup ends stroke and triggers scoring if >3 points
  • Keyboard: Enter/Space to start game or restart

Tradeoffs

  • Wave is static (not scrolling during drawing) — makes fair comparison possible; concept says "scrolls" but playability wins
  • Rightward-only constraint prevents scribbling; natural for pencil-like drawing
  • Reveal overlay auto-advances after 2.4s rather than requiring a tap — keeps pace up
  • No localStorage leaderboard — 5-round session score only

Files modified

  • site/games/resonance-draw/game.js — full implementation (was stub)
  • manifest.jsonplayable: true added for resonance-draw slug