Commit Graph
6 Commits
Author SHA1 Message Date
wuwiandClaude Opus 5 4f49a0b4e1 Give staging its own address rather than a spare room in the main house
A subdomain means a separate origin, so a staging run can no longer overwrite
the localStorage the testteam is playing on. That makes the /staging alias
pointless, so the Dockerfile goes back to exactly what is deployed today.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 14:21:18 +02:00
wuwiandClaude Opus 5 708ed9c57f Serve the same court twice, so staging can be tried before the crowd arrives
The image now answers at /staging/ as well as /, via an alias to the same
root — that way the staging deploy works whether or not Coolify strips the
path prefix, and the staging branch needs no diff of its own to merge.

The manifest MIME moved from an exact-match location into the stock types
map: an exact match would have missed the /staging/ copy, and a regex
location would have out-ranked the prefix and resolved against root.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 14:20:08 +02:00
wuwiandClaude Opus 5 ff77922e85 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>
2026-07-27 05:58:18 +03: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
wuwiandClaude Fable 5 dc1e12b9b6 Recorded umpire voice, court staff, out-zone borders, intro overlay, no-cache deploys
- 23 pre-recorded umpire lines (macOS say, en-GB Daniel) played via WebAudio,
  works on mobile; speechSynthesis stays as fallback only
- umpire chair + two ball boys (generated sprites) dress the court
- court redrawn: doubles alleys, white perimeter border, clearly darker out area
- intro overlay with control symbols; first tap dismisses it and unlocks audio
- nginx now serves everything Cache-Control: no-cache so a reload always
  revalidates and picks up new deploys

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 13:38:28 +02:00
wuwiandClaude Fable 5 c2ba256b3b Add touch controls and nginx Dockerfile for Coolify deploy
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 09:30:26 +02:00