Feedback round: fire actually spreads, brutes lurch, crowd stops flickering

- Fire never spread in play. The flame ball's full pierce wiped its own lane, so
  the bodies that would have caught were already gone. It now ignites everything
  it FLIES PAST (TUNE.burnBallR), with a wider ignition and spread radius. One
  flame serve into a scattered 10-wave kills 9, nine burning at once.
- Wounded brutes slid along like decals: every wound stage is a single frame and
  the brute now spends most of its life wounded. They get a procedural lumber
  instead of eight more sprites — translate + squash, no rotation, so the pixels
  stay on the grid, and the amplitudes scale with the projection or the whole
  thing goes sub-pixel at range.
- The "scoreboard flicker" was the crowd: the cheer bounce was per-column
  Math.random() every frame, i.e. TV static, showing through the scoreboard art's
  transparent ornate edges. Now a smooth per-column sine on idleT.
- Ball boys: mopping is the default in splatter mode now, and the boy is half
  again as tall — at 1.2m he read as a distant speck. The running fetch-boy
  survives for tennis, where there is nothing on the grass but a ball.
- Changeover 7s -> 5s, with the mop crossing timed to fill it.
- Save-to-homescreen: a bloody tennis ball, wired up as apple-touch-icon +
  favicon + webmanifest. The Dockerfile now ships the manifest and gives it its
  own MIME type via an exact-match location (a bare `types {}` block would have
  replaced nginx's whole map and broken .js and .png with it).

Benchmarks re-run: CPU returns 67/72 serves (93.1%, above the 11/12 bar — a
20/24 sample in between was flub noise), 30 human-tapped points = 50 hits /
0 whiffs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-07-27 05:58:18 +03:00
1 parent a09a5d7559
commit ff77922e85
14 files changed
+92 -19

No files matched your search

+8 -5
View File
@@ -30,8 +30,9 @@ export const TUNE = {
zSpawnStep: 0.22, // spawn-gap reduction per finished game
zMax: 3, // shamblers on court in game 1 (cap grows +1 per game to zMaxCap; 0 = spawns off, for tests)
zMaxCap: 14, // absolute shambler cap
changeoverT: 7.0, // s the changeover breather lasts (after odd games, as the rules demand)
boyMopSpeed: 4.0, // m/s a MOPPING ball boy crosses at (a fetching one still sprints at 7.5)
changeoverT: 5.0, // s the changeover breather lasts (after odd games, as the rules demand)
boyMopSpeed: 5.0, // m/s a MOPPING ball boy crosses at (a fetching one still sprints at 7.5).
// Sized so one crossing ~fills the changeover instead of stranding him mid-court.
gameBeatT: 1.6, // s the game-end beat lasts on even (non-changeover) games
eatenR: 0.9, // m a shambler must close to eat you — matches the visual sprite overlap
zSnap: 0.9, // m of lateral slack at zero range — the aim cone's base width (fat-thumb forgiveness)
@@ -85,8 +86,10 @@ export const TUNE = {
// fire: the flame ball no longer just kills what it touches, it starts an epidemic.
burnTime: 3.0, // s a body burns before the fire goes out
burnDps: 2.0, // hp lost per second while burning — burnTime*burnDps must exceed bruteHp or tanks walk out of the fire
burnSpread: 1.3, // m — a burning body ignites anything this close, every frame it burns
burnIgniteR: 2.6, // m — the flame ball's ignition radius around the body it kills
burnSpread: 2.2, // m — a burning body ignites anything this close, every frame it burns
burnIgniteR: 4.5, // m — the flame ball's ignition radius around the body it kills
burnBallR: 2.4, // m — the flame ball also lights anything it FLIES PAST. Without this the ball's
// full pierce simply killed the whole lane outright and nothing was left to catch fire.
burnPanic: 1.0, // walk-speed multiplier while burning (1 = off; crank it for panicked sprinting)
setCardT: 2.0, // s the centered SET card holds (the 'kurze unterbrechung' before the horde)
bruteHp: 5, // splat-quality hits (or pellets) a brute ('g') soaks before it dies — one wound skin per stage
@@ -117,7 +120,7 @@ COURT.svcNear = COURT.netZ + 6.4; // near service line
// world sizes (meters)
export const PLAYER_H = 1.88;
export const BOY_H = 1.2;
export const BOY_H = 1.5; // was 1.2 — the mopping boy read as a distant speck at that scale
export const UMP_H = 3.0;
export const UMP_X = 5.6; // chair right beside the doubles line — x 7.1 projected off-screen in portrait