70882d2dd49f4fba6a171c29b43c8b40435b326c
Runner counter (no new weapon needed — one you don't hold when it shrieks
can't save you): the sprinter is now a GLASS CANNON — any ball contact at
any quality bursts it (main ball and triple-serve side balls; melee and
pellets already killed it). The hold-to-aim auto-lock targets the most
advanced zombie = the charging runner, so touch-and-release is the panic
button. Plus runnerVMax 4.2: the late-game speed ramp is capped so runners
stay humanly reactable.
Battery (iPhone drain):
- TUNE.fps = 30 (T-panel tunable, 0/60 = uncapped): frame-skip cap in the
RAF loop — halves paint work on a 810x1440 canvas, the dominant cost.
dt clamp raised 0.033 -> 0.04 so 30fps doesn't run 1% slow-motion.
- Gore piles pre-rendered to per-pile cached canvases (rebuilt on growth /
orientation change): 1 drawImage per pile per frame instead of ~26
ellipse paths — late-game courts had ~800 path fills per frame.
- matchMedia('(pointer: coarse)') hoisted out of the render loop (was
allocating a MediaQueryList every pretoss frame).
Verified: weak (pow .05) ball kills a runner; max-ramp runner v = 4.2
exactly; piles render from cache (screenshot, pl.cv set); frame-cap
arithmetic yields clean every-other-tick at 60Hz RAF (RAF itself is paused
in this pane — logic deterministic); tennis serve benchmark 30/36 across
runs (flub-band; diff is provably tennis-neutral); no console errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Languages
JavaScript
75.2%
Python
15.8%
HTML
7.3%
Shell
1.4%
Swift
0.2%