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>
This commit is contained in:
1 parent
f221ff84df
commit
69e3a0c310
20 files changed
+247
-25
No files matched your search
@@ -11,6 +11,11 @@ export const crowd = { cheer: 0, dots: [] }; // dots are (re)built by render.bui
|
||||
|
||||
// everything that used to be loose top-level lets
|
||||
export const G = {
|
||||
mode: 'tennis', // tennis | transition | splatter
|
||||
transT: 0, // transition timeline clock
|
||||
tFlags: null, // one-shot markers within the transition
|
||||
hideO: false, // the opponent has... left the match
|
||||
everTransitioned: false,
|
||||
phase: 'pretoss', // pretoss | toss | rally | over
|
||||
serveNum: 1,
|
||||
overT: 0,
|
||||
@@ -30,6 +35,12 @@ export const deuceSide = () => (score.pts[0] + score.pts[1]) % 2 === 0; // even
|
||||
|
||||
export function setupPoint() {
|
||||
G.phase = 'pretoss'; ball.active = false; ball.bounces = 0; ball.firstLand = null;
|
||||
if (G.mode === 'splatter') { // always your serve; the receiver is... plural now
|
||||
score.server = 'P';
|
||||
P.x = deuceSide() ? 1.3 : -1.3; P.z = 24.3;
|
||||
P.pose = 'idle'; P.swingT = -1; P.facing = 1;
|
||||
return;
|
||||
}
|
||||
const sv = score.server === 'P' ? P : O, rc = score.server === 'P' ? O : P;
|
||||
const sx = deuceSide() ? 1.3 : -1.3;
|
||||
sv.x = sv.side === 'P' ? sx : -sx; // deuce side mirrors across the net
|
||||
@@ -40,8 +51,8 @@ export function setupPoint() {
|
||||
G.aiServeT = score.server === 'O' ? 1.4 : 0;
|
||||
}
|
||||
|
||||
export function sendBoy() {
|
||||
if (ball.z < -3 || ball.z > 27) return; // ball left the field lengthwise, let it go
|
||||
const dir = ball.x > 0 ? 1 : -1; // enter from the opposite side so the pickup is mid-run
|
||||
G.boy = { x: dir > 0 ? -13 : 13, z: ball.z, dir, runT: 0 };
|
||||
export function sendBoy(tx = ball.x, tz = ball.z) { // fetch a dead ball — or mop a splat
|
||||
if (tz < -3 || tz > 27) return; // target left the field lengthwise, let it go
|
||||
const dir = tx > 0 ? 1 : -1; // enter from the opposite side so the pickup is mid-run
|
||||
G.boy = { x: dir > 0 ? -13 : 13, z: tz, dir, runT: 0 };
|
||||
}
|
||||
Reference in new issue
Block a user