diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..03dabd9 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,185 @@ +# VINYL GAUNTLET — depth design doc + +*Where to take the game after the core loop. Written 2026-07-15, after Steps 1–7 shipped +and the game went live at partly.party/vinylgauntlet. Companion to plan.md (which is done).* + +## Where we are + +The Gauntlet II skeleton works and is fun-as-rectangles-now-sprites: vibe drain, discount-bin +generators, swarms, Sound Guy, airhorn, trainspot-to-exit, 3 hand-authored levels, announcer. +What it lacks is exactly what Gauntlet II had that we haven't used yet — **classes, treasure, +secrets, "shot the food", infinite depth** — plus the thing only WE can do: **real record data.** + +Design constraints: +- **cratewars owns buy/sell economy** (DopeWars clone). No shop/economy sim here — a nod at most. +- All art is free via MODELBEAST flux_local (assets/queue.json → enqueue → collect → process). +- partly.party audience includes phones (GAMES/CLAUDE.md: test Pixel-6-Pro width). Keyboard-only + is leaving players on the table. +- 9 generated assets already sitting unwired: record_pirate, crate_ghoul, goldrecord, turntable, + lamp, checker/carpet floors, shelf/poster walls. + +## The one big idea: trainspotting is real + +We have `discogs_full` (10.4M records, local Postgres). Extract a curated JSON — say 100–500 +canonical records per genre (house, techno, hip hop, jungle, disco...) with artist / title / +label / year. When you clear a level, the DJ Booth reveals **an actual record**: + +> *TUNE IDENTIFIED: Rhythim Is Rhythim — Strings of Life (Transmat, 1987)* + +Every ID goes into your **Trainspotter's Notebook** (localStorage): a persistent collection log +across runs. "I've identified 74 of 500 tunes" is a real meta-progression hook that costs almost +nothing to build, can't be copied by anyone without the data, and literally teaches record +culture while you play. Genre = level theme (see Level Themes below), so your notebook fills by +scene. Rare pulls (a 1-in-50 "grail" ID, gold-tinted in the notebook) give the gambling dopamine. + +This is the game's soul. Everything else below is good arcade meat, but this is the hook. + +## Gameplay depth + +### Classes (Gauntlet II's core, still unused) +Pick your digger at the title screen. Stats only — no new mechanics, huge replay value: + +| Class | Tweak | Fantasy | +|---|---|---| +| **The Digger** | +25% move speed | fast fingers, first to the bins | +| **The Selector** | vinyl does 2 dmg (kills nerds in 1... no — kills faster, 2-shot bins) | taste is a weapon | +| **The Promoter** | starts with 1 lanyard, +1 airhorn | knows everyone | +| **The Sound Tech** | Sound Guy drains half; immune to Shazam projectiles | speaks his language | + +Implementation: a `CLASSES` table + 4 title-screen sprites. One session. + +### Vibe states (DeepSeek's best mechanic idea) +- **> 75%: Peak Time** — vinyl flies 20% faster +- **25–75%: normal** +- **< 25%: Burning Out** — 15% slower move, red vignette, desperate announcer +Three thresholds, ~20 lines, makes espresso *feel* like relief. + +### "Shot the espresso!" +Vinyl destroys espresso pickups on contact. Announcer: *"Selector... shot the espresso."* +The single most-remembered Gauntlet mechanic, nearly free to add, comedy + aim discipline. + +### Enemy roster v2 (art already generated or one queue-run away) +| Enemy | Behavior | Art | +|---|---|---| +| **Record Pirate** | beelines for the nearest *pickup*, steals it, flees to a wall and despawns. Kill him → drops it back + bonus gold record | ✅ generated | +| **Crate Ghoul** | slow tank, 3 HP, spawns from bins on later levels (30% roll) | ✅ generated | +| **Shazam Zombie** | stationary, lobs slow "what song is this?" projectiles (new pool) | queue it | +| **Dust Mite** | tiny, fast, 1HP, spawns in packs of 5 from floor cracks in Archive levels | queue it | +| **Mite Queen** | miniboss every 4th level: fat, slow, periodically vomits mites; 12 HP | queue it | + +### Bosses (the Elite, from the bestiary) +- **The Spectral Conductor** — level 8 boss. Doesn't attack; *conducts*: while alive, all + generators spawn at 2x and enemies move 1.5x. Kill the conductor, the room calms. 20 HP, + teleports between corners when hit 5 times. +- **The Monstrous 78 RPM** — final(ish) boss: a giant spinning record that ricochets around + the room Pong-style, spitting warped-record shards. Only vulnerable when it stops to + "change sides" every 10s. Beat it → it IS the White Label (see Lore). + +### Digging (hold E at crate walls) +2-second channel, vulnerable, at any *wall_crate* tile (once per tile): +- 70% common: +200 vibe · 25% rare: gold record (score) · 4% **Grail**: full vibe + flash +- 1% **Bootleg**: every enemy on screen aggros you, announcer cackles +Injects push-your-luck into wall geometry. The bestiary's "digging minigame" idea, minimal form. + +### Treasure rooms (Gauntlet II secret sauce) +Every 3rd level, a 20-second bonus maze: no enemies, floor covered in gold records, exit +closes when timer ends. Pure greed, pure joy. One special map + a timer. + +### Scoring & the arcade frame +Score (kills ×10, gold records ×100, level clear ×500, notebook first-ID ×1000), lives = none +(vibe IS lives, correct), **local high-score table** with 3-letter initials — it's going on +partly.party next to an arcade landing; it should feel like a cab. Attract mode: title screen +cycles logo → high scores → lore card → bestiary card (all art we can generate). + +### Level themes (tilesets already half-generated) +| Theme | Tiles | Enemy mix | Trainspot genre pool | +|---|---|---|---| +| **Record Shop** (lv 1–3) | parquet + crate walls ✅ | posers, nerds | disco, soul, funk | +| **Record Fair** (lv 4–6) | carpet + shelf walls ✅ | + pirates, gatekeepers | hip hop, jazz | +| **Club Night** (lv 7–9) | checker + poster walls ✅ | + shazam zombies, 2x sound guys | house, techno | +| **The Archive** (lv 10+) | dark! radial light around player | mites, ghouls, queen | jungle, hardcore, white labels | + +The Archive uses a darkness overlay (RenderTexture mask or Phaser Light2D) — visibility ~5 tiles, +lamps (✅ generated) as light sources. Cheap dread. + +### Procedural mazes after level 12 +Simple recursive-division maze gen seeded per-level-number: infinite game, deterministic +(same level = same maze = speedrunnable). Hand-authored maps stay for levels 1–12. + +### Mobile controls +Twin-stick touch: left thumb = move (floating joystick), right thumb = fire direction, +double-tap right = airhorn. Phaser pointer events, ~100 lines. Unlocks the actual partly.party +audience. **This is Tier 1 important, not polish.** + +### Co-op (later, honestly) +Gauntlet is 4-player, and same-keyboard 2P (WASD+ZX vs arrows+,.) is one session of work — +generators already stress-tested for swarms. Netplay: no (YAGNI until someone asks). + +## Lore (arcade-thin, GODVERSE-flavored) + +Keep it to attract-mode cards + one line between levels. The frame: + +> **The last night of VINYL GAUNTLET** — the city's oldest record shop, closing forever at +> dawn. Somewhere in its sub-basement Archive spins **The White Label**: a record with no +> name, no artist, no year — the only tune never trainspotted. The shop won't let it go +> quietly: the aisles rearrange, the bargain bins boil over with posers, and the Sound Guy +> walks the walls like he owns them. You have until your vibe runs out. +> **Dig deep. Name every tune. Reach the bottom.** + +- Levels descend: Shop → Fair floor → Club in the basement → the Archive. +- The announcer is the shop's ancient PA, half-senile, fully judgmental. +- The Spectral Conductor was the shop's founder; the Monstrous 78 RPM is the White Label + defending itself. Beat it and the notebook logs: *"??? — ??? (???, ????)" — identified.* + Then the game loops harder (NG+ density), because the shop reopens in your dreams. +- Cross-game nods, one-liners only: a poster tile for "CRATE WARS", a morp squeaking in a + treasure room. partly.party shared-universe glue, zero mechanical weight. + +## Art plan (all free on MODELBEAST) + +Everything via the existing pipeline: add rows to `assets/queue.json` → `enqueue.py` → +`collect.py` → `process_sprites.py`. klein-4b, ~12s/image, $0. + +**Wire what exists first (0 generation):** pirate, ghoul, goldrecord, alt floors/walls, +lamp, turntable (decor prop in shops). + +**Queue batch 2 (~25 images, ~5 min GPU):** +- Enemies: shazam_zombie, dust_mite, mite_queen, gatekeeper, warped_record_shard +- Bosses at 768px→96px: spectral_conductor, monstrous_78rpm (2 frames: spinning/vulnerable) +- Class portraits ×4 (256px busts for title screen) + 4 in-game player variants (palette-swap + the digger via prompt: "red cap", "green hoodie"...) +- UI: notebook icon, logo/title card, lore card art, boss splash cards +- Tiles: archive_floor (dark stone), crack_in_floor (mite spawner), lamp_glow + +**Direction/animation strategy (keep it lazy):** stay single-frame + code juice (bob, squash +on hit, flip-x for left/right). FLUX won't give consistent 4-direction sheets without a fight; +top-down Gauntlet reads fine with flip + bob. Revisit only if it looks wrong in play. + +**Trainspot data:** one-off script `assets/extract_tunes.py` against local `discogs_full` → +`public/tunes.json` ({genre: [{artist,title,label,year,grail}]}). Curate via +have/want counts (Discogs popularity proxies) so the pool is canon, not noise. + +## Build order (each tier = one working, shippable state) + +**Tier 1 — "it's a real arcade game now" (1–2 sessions)** +1. Wire the 9 existing assets: level themes per tileset, pirate + ghoul enemies, gold records +2. Classes (4) + title-screen select +3. Vibe states + shot-the-espresso + new announcer lines +4. Score + high-score table (localStorage) +5. Mobile twin-stick touch +6. Cloudflare purge on deploy + +**Tier 2 — "the hook" (1–2 sessions)** +7. Trainspotter's Notebook + real-record reveals (discogs extract, genre pools per theme) +8. Digging at crate walls + treasure rooms +9. The Archive: darkness + lamps + mites + Mite Queen +10. Procedural mazes past level 12 + +**Tier 3 — "the legend" (when it's earning attention)** +11. Bosses: Spectral Conductor, Monstrous 78 RPM + White Label ending + NG+ +12. Attract mode (lore/bestiary/high-score cycle) +13. Same-keyboard 2P co-op +14. Arcade-landing menu entry + +Not doing (and why): buy/sell economy (cratewars owns it), netplay (no demand), +4-direction animation sheets (flip+bob reads fine), sound design beyond announcer+airhorn +(Web Speech + oscillators ARE the aesthetic).