Splatter feel pass: melee, homing, multi-ball, clearer MG mode
From Oliver's feedback round: - Racket melee: any swish (tap) in splatter cleaves shamblers within TUNE.meleeRange (1.7m) — a close-range survival tool. Works during a horde too (tap = swish only, still no serve). The racket-zombie boss (Phase 6, not built) is immune by design. - Zombies home in on you: on YOUR half (z > netZ) they now drift toward P.x instead of walking a straight lane; far half stays an aimless shamble. - Multi-ball / rapid fire: splatter is now a shooter — every tap/flick fires immediately (dropped the toss ritual there), and serving while a ball still flies stashes the old one into a new extraBalls array so it keeps arcing and killing (cap 6). Refactored the kill into a shared killZombie() with no ball coupling, used by ball hits, pellets, melee, and extra balls. - Machine-gun mode clarity: confirmed free-walk (drag/arrows move you, auto-assist off) and tap-doesn't-serve during a horde; added a code-drawn "rambo" racket held forward with a muzzle flash over the player, and a splatter-specific serve prompt. REVIEW on your phone — two opinionated calls, both easy to revert: 1. Dropped the toss in splatter (tap = instant quick-serve, pow 0.62). Rapid fire, but no apex-timing quality/pierce. Want the toss back as an option? 2. MG posture is a code-drawn forward racket, not a real body sprite — good enough, or worth a proper p_mg sprite later? Also: each rapid serve still auto-consumes a stocked bomb, so bombs deplete fast now — flag if that feels wrong. Verified via window.T: melee kills a 1.0m zombie and spares a 4.5m one; a near-half zombie drifts x 3→1.9 toward you; firing twice leaves 1 stashed ball + a fresh serve (barrage screenshot); extra balls kill and pierce; free-walk during a horde (x 0→2.7); horde-tap melees without serving; tennis toss-serve and Phase-4 bomb consume still work; no console errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf9553bd49
commit
9100bd5a23
5 files changed
+89
-28
No files matched your search
+14
-16
@@ -4,7 +4,7 @@ import { TUNE, COURT, CONTACT, VOLLEY, ZONE_DEPTH, HOME, P_BOUNDS, TOSS, SHOT_DE
|
||||
import { P, O, ball, score, crowd, G, other, deuceSide, setupPoint, sendBoy } from './state.js';
|
||||
import { audio, pock, swish, applause, voice } from './audio.js';
|
||||
import { axisX, axisZ, takeFlickAim } from './input.js';
|
||||
import { updateZombies, spawnZombie, zombies, explode } from './zombies.js';
|
||||
import { updateZombies, spawnZombie, zombies, explode, meleeSwipe, stashExtraBall } from './zombies.js';
|
||||
|
||||
// ------------------------------------------------------------- ballistics ----
|
||||
// Launch ball from (x0,y0,z0) so it lands at (tx, tz) with horizontal speed s under gravity g.
|
||||
@@ -375,22 +375,20 @@ function trySwing(ch, isAI) {
|
||||
export function keyPressed(code) {
|
||||
if (code !== 'Space') return;
|
||||
audio(); // unlock on first gesture
|
||||
if (G.horde) return; // horde: the racket auto-fires, taps do nothing — the thumb drag steers you
|
||||
// splatter: a tap/flick during the brief 'over' beat arms the next serve immediately —
|
||||
// reset inline, then fall through to pretoss so the finger is the only cadence limit
|
||||
if (G.mode === 'splatter' && G.phase === 'over') { ball.active = false; setupPoint(); }
|
||||
if (G.phase === 'pretoss' && score.server === 'P') {
|
||||
if (G.mode === 'splatter') {
|
||||
const flick = takeFlickAim();
|
||||
if (flick) { // quick serve: no toss ritual, modest pace, aimed by the flick
|
||||
ball.active = true; ball.collected = false; ball.bounces = 0; ball.firstLand = null;
|
||||
ball.x = P.x + 0.35; ball.z = P.z; ball.y = 2.2; ball.g = TUNE.gravity;
|
||||
hitServe(P, 0.62, flick);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tossBall(P); return;
|
||||
if (G.mode === 'splatter') {
|
||||
// splatter is a shooter: every swish cleaves adjacent shamblers, and — outside a horde —
|
||||
// fires a ball immediately. Serving while one still flies stashes it, so you can barrage.
|
||||
meleeSwipe(P.x, P.z, TUNE.meleeRange);
|
||||
if (G.horde) return; // horde: MG auto-fires, the tap only swishes (no serve)
|
||||
if (ball.active) stashExtraBall(); // keep the in-flight ball alive
|
||||
const flick = takeFlickAim(); // flick aims; a plain tap auto-targets the nearest zombie
|
||||
ball.active = true; ball.collected = false; ball.bounces = 0; ball.firstLand = null;
|
||||
ball.x = P.x + 0.35; ball.z = P.z; ball.y = 2.2; ball.g = TUNE.gravity;
|
||||
hitServe(P, 0.62, flick);
|
||||
return;
|
||||
}
|
||||
// tennis: the toss ritual + rally swing (unchanged)
|
||||
if (G.phase === 'pretoss' && score.server === 'P') { tossBall(P); return; }
|
||||
if (G.phase === 'toss' && score.server === 'P') {
|
||||
// serve timing: distance from apex = quality
|
||||
const dy = Math.abs(ball.y - serveApexY());
|
||||
|
||||
Reference in new issue
Block a user