Commit Graph
10 Commits
Author SHA1 Message Date
wuwiandClaude Opus 4.8 b6119c937b Phase 2: multi-kill applause + umpire appreciation
A single shot that splatters ≥2 zombies now escalates: DOUBLE KILL /
TRIPLE KILL / MASSACRE ×N flash, louder crowd, and a new umpire line
(double_kill / triple_kill / unbelievable m4a, recorded say -v Daniel).
ball.kills tracks the streak, reset on every fresh shot (doHit + hitServe).
zombies.js imports cheer (now exported from gameplay). The splatter pace
cut is now TUNE.zPierce (0.75, was hardcoded 0.5) so a hot ball plows
through a lined-up lane instead of stalling on the first kill.

Verified via window.T: a low ball down a one-side lane kills 3→TRIPLE and
5→MASSACRE ×5 with escalating flash, streak resets on the next serve, the
three new lines serve 200 and match the existing m4a format, no crash when
the ball dies mid-streak, no console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:57:19 +02:00
wuwiandClaude Opus 4.8 795ddeb425 Phase 1: tighten the splatter shooting loop
Input during the 'over' beat is no longer swallowed: a tap/flick while
G.phase==='over' (splatter only) resets inline and falls through to the
serve logic, so the finger is the only cadence limit. Spent balls
(lastHit 'X' after a stagger bounce) and hopeless balls (out of the
z/x bounds) are retired immediately instead of lingering until they roll
out. New TUNE.splatterOverT (0.1) replaces the hardcoded 0.25 over-timer.

The out-of-bounds z-bounds gate on travel direction so a quick-serve born
behind the baseline (P.z up to 26, heading vz<0 to the far court) isn't
killed on frame one.

Verified via window.T: flick/tap during 'over' serves same frame; spent
ball dies the frame it bounces; serve->serve latency 0 frames with
immediate flicks; tennis 'over' unchanged (2.2s pause, tap ignored);
tennis CPU still returns 11/12 serves; no console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:49:50 +02:00
wuwiandClaude Fable 5 8fd5055e5c Half-volleys: a rising ball is always scoopable; scoreboard tap shows the swing log
Field data (miss log) showed the dominant unfair miss: the assist parks
you on the landing spot, the ball spends the whole swing window below
minY rising off the bounce at your feet, and becomes hittable one frame
after the window closes. Root fix: the below-ankles rejection now only
applies to a DROPPING ball — rising post-bounce balls can be scooped at
any height (a half-volley). Feet-bounce taps go from ~0 to 19/30 winning
frames; 30 simulated real points now log 50 hits, 0 whiffs.

Also: swing-log snapshots record the same swing-timer value trySwing
tests (removes the one-frame misclassification behind 'unclassified'),
and tapping the scoreboard toggles an on-screen dump of the last 9 log
entries so live situations can be screenshotted from the phone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:14:34 +02:00
wuwiandClaude Fable 5 d6d00929bb Miss log: every tennis swing logs why it failed, last reason shown on HUD
Whiffed swings sample the ball's approach each frame and classify the
miss at swing expiry: tap too early (with ms), tap too late, ball line
wide, too high/low, out of reach. Balls that die on your side without
a swing log as PASSED with closest-approach data. Ring buffer of 50 at
T.G.missLog; the latest miss reason flashes on the HUD for 3.5s
(TUNE.missHud to disable). CPU serve-return benchmark still 11/12.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:02:11 +02:00
wuwiandClaude Fable 5 943b7da9fd Zombies get faster over time; when one reaches you, you're eaten
splatT now ticks while in splatter mode and scales spawn speed by
1 + min(1.5, splatT/70). A zombie within 0.7m of the player ends the
run: gore burst, 'game, set, massacre', dark EATEN. overlay with final
games and a tap-to-restart (gated 0.7s so death-spam doesn't skip it).
Zombies keep shambling on the end screen but no longer score. Also
verified the two prior unverified items: quick-serve cadence (0.25s
between balls, flick = instant aimed serve) and flick aiming across
the net (far/near lane selection works as designed). HANDOFF updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:54:09 +02:00
wuwiandClaude Fable 5 a5a6f550a3 Volleys get wider reach and swing window; serve volleys no longer fault
A ball passing pre-bounce moves at full pace with no bounce cue to time
against, so marker-behind volleys needed frame-tight taps. Pre-bounce
player contact now widens reach x1.4 and the swing window x1.8 (VOLLEY
in config.js). Also clear G.wasServe in doHit so a serve returned out
of the air doesn't fault-check the return, and launch.json uses
autoPort.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:46:36 +02:00
wuwiandClaude Fable 5 e7aab295d4 WIP splatter feedback round + HANDOFF.md for session continuation
Done (unverified): faster serve cadence in splatter (overT 0.25, serve from
where you stand, flick = instant aimed quick serve), aim-anywhere targeting
relative to the player. Not done: zombie speed ramp (G.splatT exists but is
never incremented), eaten-on-touch death + restart screen. Full state and
plans in HANDOFF.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:28:00 +02:00
wuwiandClaude Fable 5 60c5f72a0a Splatter aiming targets zombies anywhere; triple-tap the umpire to skip ahead
- doHit/hitServe in splatter mode lock onto zombies instead of tennis court
  depths: your flick picks the lane and depth band, the shot targets the best
  match anywhere on the court (including your own side) with a walking lead;
  serves auto-track the most advanced shambler
- hidden shortcut: tap/click the umpire three times within 1.6s during tennis
  mode to summon the transition immediately

Verified: near-side and far zombies killable, cheat triggers transition,
tennis mode targeting untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:38:27 +02:00
wuwiandClaude Fable 5 69e3a0c310 Zombie town: the match continues
Win your first game and the applause cuts off mid-clap. The palette drains,
the umpire lowers his voice ('Quiet... please'), your opponent turns — torn
red polo, dragging his racket — and shamblers come over the billboard wall.
The scoreboard rewrites CPU to THEM. 'Play.'

- zombies.js: shamblers walk your way; quality shots splatter them (gore
  decal + particle burst + wet synth splat), weak sitters only stagger them
  back; one crossing your baseline is a point for THEM
- tennis scoring machinery keeps running untouched: fifteen, thirty, deuce,
  and 'Game, set... massacre' on a game win, all in recorded umpire English
- ball boys mop the gore they pass (their destiny fulfilled)
- transition: palette lerp, scripted spawns incl. the turned opponent,
  new recorded lines (quiet_dark, remain_seated, play, new_balls)
- moan ambience, drained splatter palette, all zombie params in TUNE

Verified: transition triggers on first game win, splat/stagger/baseline
scoring all correct, dead-ball flow feeds fresh serves, tennis mode
regression clean (6/6 returns, 6/6 points resolved).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:26:49 +02:00
wuwiandClaude Fable 5 c506a631c2 Split the monolith into ES modules; hoist scattered magic numbers
game.js (830 lines) -> 9 modules, native ES modules so still zero build step:
  dom      canvas handles (imports nothing; keeps cycles harmless)
  config   TUNE (live-tunable) + structural constants
  state    all mutable game state (G) + setupPoint/sendBoy
  audio    sfx synthesis, recorded umpire voice, reverb, speech fallback
  input    keyboard + touch, exports axes and takeFlickAim()
  gameplay ballistics, swings, serve, rules, AI, update loop
  render   camera, viewport, sprites, crowd, all drawing
  panel    T tuning UI
  main     boot, loop, intro, window.T test hooks

Deduped into named constants: bounce tempo (was in 3 places), contact
height band, intercept zone depth, home positions, player bounds, toss
params, shot depths, pose hold time, sprite scale, actor heights. Also
extracted drawShadow/drawBall/expirePose from repeated code.

One intentional import cycle (input <-> gameplay), safe: both sides only
call functions at runtime, never during module evaluation.

Regression-verified in browser sims: point cycle, CPU returns 11/12,
assist contract 8/8, corner-winner gradient intact (0/12 perfect corners
returned, 10/12 center balls returned).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 15:38:15 +02:00