Phase 7: the scoreboard is the progression — spawn director, changeovers, sets, permadeath

- Spawn director: gap and court cap scale with games finished (runGames);
  game 1 is three lonely shamblers, late runs approach zSpawnMin/zMaxCap
- Changeover after odd games: 4.5s forced breather, no spawns, no serving
  (melee still works), boys mop, umpire calls 'Time.' (new time.m4a)
- 6 games = a set; set end launches the horde (replaces the splatGames>=2 trigger)
- Zombies taking a game sets shameGame (phase 9 withholds the delivery)
- Eaten = the run is over: GAME, SET, MASSACRE summary with games/sets survived
  and best run (localStorage); HUD shows sets in splatter (SETS·GAMES PTS)
- spentBall() helper so dead-ball paths can't clobber a changeover's beat
- T surface: splatPoint + explode exposed for verify scripts

Verified: game-1 cap 3 held 25s; changeover blocks taps+spawns then resumes;
6 games -> set+horde -> racket zombie; runGames=6 tempo ~6 spawns/10s;
eaten writes best; tennis regression 11/12 CPU returns; no console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-07-12 09:54:01 +02:00
1 parent 25db84ed87
commit 5a7f71fdba
7 files changed
+80 -27

No files matched your search

+3 -3
View File
@@ -5,10 +5,10 @@
import { TUNE, COURT, UMP_H } from './config.js';
import { P, O, ball, score, G, setupPoint } from './state.js';
import { update, keyPressed, solveShot, inServeBox, inCourt, forceZombies } from './gameplay.js';
import { update, keyPressed, solveShot, inServeBox, inCourt, forceZombies, splatPoint } from './gameplay.js';
import { fitViewport, render, proj } from './render.js';
import { voice } from './audio.js';
import { zombies, spawnZombie, piles, gore, parts, pellets } from './zombies.js';
import { zombies, spawnZombie, piles, gore, parts, pellets, explode } from './zombies.js';
import { cv } from './dom.js';
import './input.js';
@@ -54,6 +54,6 @@ cv.addEventListener('pointerdown', e => {
requestAnimationFrame(frame);
// exposed for in-browser sanity checks and simulated playtests
window.T = { TUNE, ball, P, O, score, G, zombies, spawnZombie, piles, gore, parts, pellets, solveShot, inServeBox, inCourt, proj, setupPoint, forceZombies,
window.T = { TUNE, ball, P, O, score, G, zombies, spawnZombie, piles, gore, parts, pellets, explode, splatPoint, solveShot, inServeBox, inCourt, proj, setupPoint, forceZombies,
step: dt => update(dt), render, press: keyPressed,
get phase() { return G.phase; }, set phase(v) { G.phase = v; } };