Fill the screen, and let the swish keep up with a late horde

The portrait canvas is adaptive now. A fixed 270x480 is 9:16 while a modern
iPhone is taller, so width bound the fit and ~150 CSS px of screen went unused
at the bottom. Height is derived from the device aspect, and TUNE.horizon rides
with it — proj() places the court in absolute pixels, so leaving horizon fixed
just grew a dead green band between the court and the rack instead of moving
the court down. RES 3 to 4 for the extra pixels: an iPhone gives ~1125 device
px across and we were rendering 810. That is the first knob to turn back down
if the phone stutters.

The swish cooldown scales with how swarmed you are — 1.00s at one body, 0.47 at
four, 0.22 from fourteen. Oliver died on every game-20 horde because the wave
grows with hordeGrow while the panic button stayed a flat second; he chose
scaling the melee over shrinking the horde. The first version measured the
crowd after meleeSwipe had already killed it, so it counted survivors and
barely moved.

Winning a duel while wounded lost the weapon popup entirely: showModal never
clobbers an open modal, so the heal modal opened first and the tin's was
dropped. One popup carries both now.

And the mop boy stays off the court unless a stain actually passes the test
mopRound uses to pick a target. He was walking on, finding nothing reachable,
and walking straight off again.

Tennis untouched: 50 hits / 0 whiffs. 45-game soak clean, all four chapters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-07-30 17:43:48 +02:00
1 parent 49d391dc64
commit ae64daa0fb
6 files changed
+108 -19

No files matched your search

+7
View File
@@ -163,6 +163,13 @@ export const TUNE = {
backstopKeep: 0.55, // pace a ball keeps after the rebound — still lethal, slower
backstopPop: 1.8, // m/s of lift off the fence, so the rebound travels back instead of dying at the net posts
meleeCool: 1.0, // s between racket swishes — melee is the panic button, not the default
meleeCrowd: 0.38, // ...but the panic button PANICS. The cooldown shortens with how many bodies are
// actually on top of you, so a late horde stops outrunning your only close-range
// answer: cool = meleeCool / (1 + (near-1)*meleeCrowd), floored at meleeCoolMin.
// 1 body 1.00s, 4 bodies 0.47s, 8 bodies 0.28s.
meleeCoolMin: 0.22,
meleeCrowdR: 3.4, // m — the radius that counts as "on top of you" for that scaling (> meleeRange,
// so the swish speeds up as they close in, not only once they are already on you)
zPierce: 0.75, // pace a ball keeps after a splatter — hot balls plow through lined-up pairs
// The schedule calls the DUEL, not the tin: weapons are only ever won, but a duel comes round
// on its own so there is always a chance at one. Fires off the next hand-cleared wave.