From b6119c937bfeac976509aa323a678279f8e11de4 Mon Sep 17 00:00:00 2001 From: Oliver Rieger Date: Sat, 11 Jul 2026 21:57:19 +0200 Subject: [PATCH] Phase 2: multi-kill applause + umpire appreciation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- assets/audio/double_kill.m4a | Bin 0 -> 14760 bytes assets/audio/triple_kill.m4a | Bin 0 -> 13107 bytes assets/audio/unbelievable.m4a | Bin 0 -> 8504 bytes config.js | 1 + gameplay.js | 4 +++- state.js | 2 +- zombies.js | 9 +++++++-- 7 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 assets/audio/double_kill.m4a create mode 100644 assets/audio/triple_kill.m4a create mode 100644 assets/audio/unbelievable.m4a diff --git a/assets/audio/double_kill.m4a b/assets/audio/double_kill.m4a new file mode 100644 index 0000000000000000000000000000000000000000..cf519fdc34328b22b955719df7ee3a432b2b57fe GIT binary patch literal 14760 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 OA68D^t|~#m%l`{;IjWEV literal 0 HcmV?d00001 diff --git a/assets/audio/unbelievable.m4a b/assets/audio/unbelievable.m4a new file mode 100644 index 0000000000000000000000000000000000000000..394b9d42958c6aa4f46a6c87ea43f65e87ff8587 GIT binary patch literal 8504 zcmeHLXEKaoge3K?rWawx!3cowVt)_wf3Ib0{{TM71GODMfeUA00QkDorMK$ zT@j7|fceZ3fp7=I4vy|N7U=wEPqjF-0l)(m0MG^i$j=Wt^$TG8-|!!8_`fCpM*{-@ zFgTGeruJaQ5NZFjCiXuy(bdoZ>;5Aa*rF{w$+-LlkUMyCRW4X8<|6$`x=9&;gv_YRu6D1bP@c zhyS-nxAFewHef$*kpBia9z6jB8}w(O&4OGWG*yuIfHnhi^!Q@X@ z!4(NMo3DcaJ-wr)>Cas?M>z7Kdt36^YP&gEqLra=GIg{>4@F0`RMcfa8f;6lm*qwi+&^?63g+>1r_I{88YK0)G_v zqre{p{wVNAfj@z*&x-T04NO5I;G5s&lusqY~47 zSd7jp^i7{ejORkCebP-yAJSzVOhmYI3i6!(B_UT%sNk61$0S4%kh*QHZbv zSednm=&I&--yBT)Vqh9NzJ!CY9hJun^TY@obNzZyDTox%B4!#v^kfSk;;v$HmaQ`SFMCqyw+>$i)8|hxx1X zE)^QQvmj8qQ5RpH{cusqLrhy;?k^UjdNxc_JyxZ$t6Yj&7Qqi_aCP`@<(r9FQ~3#$ zRmBlHI71c`u(eRI4>s6%a4`oU0$76Fohlze^5TpInufyzDRH5}%#dr*CLuYvqwdr8 zN2RHhv-RQtq>WqGo+w&b0B^n}k|enp@*$S+FBu6PIfmiSPxQ~nyH3Ymf61HR*6Zr3 zJ&)IVHoM1=9nl-bJWQS__=ATBV>bL_7vjzQnQ$8;YbZ zP6({#$k+BcQhOo(4R0cTcq2t8w6Ry0QUHKe?)MJ^T;Zb*=%UtAQ z?lN*5iBRGy84+GtJFQP5Y0JbKP^3|Neq;2`UKzqC7~flaatKNk$&(Y#pCF85g6jzDcOHIu*u|*6`To`W^ey;+ zo;F7WN+y%fKCZjOr^g<7QliMvK9^7XAbaAo(%b}&mzuF?-id7&Dn9#eS& zDZ_-Q)}5g`mE`UIqVlBgXWX#aja{k)(WoA>&ml=T`4!Bt3v0`|0@uF4FxWZ;@KQF2%^p72hbc78I#y)6Nunw#I#Ot3NqBT63SS zkmzc|H|r|}ITZ6GSY3q$Lw0iP`T2V1WGuw`)MF_g!s>SeEBq#TRqfkcLIT`=@R{Dc zeVeWwo0wIPn1bz+e|t#3t7|3zF+K5l`gtmMk(pSlluaQCoSccU5S(EAwalE!i(fHf_r7aOH)<58c%43KCev)Sf zV@2{YmzflJ7YTd%Vyq=c6acO0Sa;?(-kT3=-yigy~egKqA*svTc4m=kIKhuDMh?X6q$5vdt7+qpu01;*iodyl<5G7oWe&gqCJF#49bn=3}yFra%p_Ufo$iz z@8OuGycHbMK9njOZLFT=+X-G*X**My%zVTOqHNVVB{AxJ>L+xzbb`pjy3jwh_hsMqSohh~67_b1TEeEGNr{ zdby@WE2_LPj4!4zVi42ZXBvk;)R>27pD+)vg+cC8B_?XS62SsZA$ONpS0kd9zB6%cq`W*SZ^qy; z&dyU{TjmNR94>mV7_{m`Y3JcPYWDEtX5C103}=FBo&4tyw28vek~(ioOvT%yASFZn z^Usr_?%ik-m9YuiNYjhn(>OpWs%ffH;Z`4y!(!&%UefK2NSAMNWkz={CH8g56_jsA zN?*>!GA^>Q0GK3&9;cb-(%FXh0VPbRf}7F8s#QH4{L0p(LaFDHT@Me�i&SBAatr z{w$3W_3TAF{<`9M)utnU)%z%4?O-FH*ZJ!GlvEBB2ewQL*8DVF=C3V{oPhLQ6Ih0u z9yWJK;H<`+&Vb(fx2dW@-ILgzi!5bqqpAlj*r)F^?P!@^^(rD1)Rmj%N7T9Nw0C%^ z&$F8K_OalQh}xk?YDWCA^Mu5ETq*H``pv{H#o7-^8EbP@^~_xWdhjr1#0B$^Qgbke zE5KO+gZ@sqyK{$p5TN^Hp=wKAVo!QhIZr<@kgEhr&rfipQ<-`3#WkeymXm?EyCIqL z@O3K8iaoEm8YFiOg-Xb@sJdEACpl@cnNL1LSyoe5k~v{sM6Px_l6A7;!P=k*d+wv? zNG#GIyGOL;lsujC@SR*T^Gyxq;_3SUqjuCzke`Sr)bGN&QRBtO&&Y^pX@YVmj$dc1 zY6~kJ)$$Yul(0=olJ9+mB-RT?gfau+a27I>2nGc23Yi9m`s&svhM2lf+=58I&bRCx-Qhb_`QCqRluG(g<$~-A8NEeN%DX| z7M$=v%o_#m!$oY;hrIqLFDd8P(0}>^N{rCTuO}d-AWa)JsehnMJJTkuU3g z>^(eM-`?`*AZAU6vPc%CUBDv!Yk9WH17`rOg3 zHj>f_%aCKu`(Ul8Re#%MP ztCc(YwZ)z9WC)oLZ*Vkz%rZ7OPs~gmE*#i5sylIR=CT#vPm$$~;t`^I<*{z1#?*x9 z05)cv*i?8v<=xUZmSj(t*$ohrNdJ_fEimnN{pE@8-h5a3liQm)!xkZI9E}Res4~K# zD7F!NOTT+wUL7jYhGf+{=g%G`#xw;fWEeD&ReW8@bvS%V?a%`}FInal;8-%Yz=AtN zq`@<6DMi!=g-76UkkF7lU68On5oj7bLf9TI~Q}cXx))2AbS@mOJzFq?V(*RLfvvbdxuXSrYN`<-&LkFZO-6W!sx53y<`!*>F@8B;xC z$3D#o_`deNc4Xl4!G^{K*w zO)Q|i-)kymWT8kjNI*wj1S4RrSByd$!oBSf9{9u9#_FERFta3 zh|5w~q+jvUBfM#SVGvSOKKed6ll<(oza*w3| z;t(mSOwmLYiqHU3R4|Gq6!9dI#V}2RUb)h3z3$B`^_xP*g<>aJx1lp#cFXe# z$2Ylyr=p(TG0f46@32Emjgb=v-K|^g+>FgoalHR-)F10!m%n*mL>;ApC4^6v+&x%M zopW(V?T79dn;B(2t&ZRtmA4427Mav{T9F{s+vdh#E;s32YCjZMDLNk2&`qonm(f|H zd_YKGsaXW83&eWKYLGzJyfUPtF>hre6JXCX<=(FU7T>_`L4S%q!NteM>n6}P%3y(y zIPDK@W<>l*E6;Bt$BjK<7L)_P;9oFIQm!LrpBK&C%Ju> zO%tzyxJu^= -0.02 && tz <= COURT.netZ); G.outMarker = { x: tx, z: tz, out: !ok, t: 1.3 }; @@ -118,6 +119,7 @@ function hitServe(sv, quality, aim = null) { ball.vx = v.vx; ball.vy = v.vy; ball.vz = v.vz; ball.lastHit = sv.side; ball.bounces = 0; ball.pow = quality; + ball.kills = 0; // fresh serve: multi-kill streak restarts if (sv.side === 'P') G.outMarker = { x: boxX, z: tzs, out: G.mode === 'tennis' && !inServeBox(boxX, tzs), t: 1.3 }; G.phase = 'rally'; pock(1, 1100); sv.pose = 'serve'; sv.poseT = 0; @@ -136,7 +138,7 @@ function scoreKey() { return N[s[0]] + '_' + N[s[1]]; } -function cheer(seconds, vol) { +export function cheer(seconds, vol) { applause(seconds, vol); crowd.cheer = Math.max(crowd.cheer, seconds); } diff --git a/state.js b/state.js index 5768334..5ab3be0 100644 --- a/state.js +++ b/state.js @@ -5,7 +5,7 @@ import { HOME } from './config.js'; export const P = { x: 1.3, z: 22.8, side: 'P', pose: 'idle', poseT: 0, swingT: -1, facing: 1, runT: 0 }; export const O = { x: -1.3, z: 1.0, side: 'O', pose: 'idle', poseT: 0, swingT: -1, facing: 1, runT: 0 }; export const ball = { x: 0, y: 1, z: 20, vx: 0, vy: 0, vz: 0, g: 9.2, - active: false, lastHit: 'P', bounces: 0, firstLand: null, collected: false }; + active: false, lastHit: 'P', bounces: 0, firstLand: null, collected: false, kills: 0 }; export const score = { pts: [0, 0], games: [0, 0], server: 'P' }; // pts index 0=P 1=O export const crowd = { cheer: 0, dots: [] }; // dots are (re)built by render.buildCrowd diff --git a/zombies.js b/zombies.js index 13a255b..6e89544 100644 --- a/zombies.js +++ b/zombies.js @@ -6,7 +6,7 @@ import { TUNE, COURT } from './config.js'; import { G, P, ball, sendBoy } from './state.js'; import { splat, moan, pock, voice } from './audio.js'; -import { splatPoint } from './gameplay.js'; +import { splatPoint, cheer } from './gameplay.js'; export const zombies = []; // {x, z, v, walkT, variant: 'a'|'b'|'c'} export const gore = []; // lawn decals {x, z, r, a} @@ -22,6 +22,7 @@ export function spawnZombie(x, z, variant) { function splatter(i) { const zb = zombies[i]; zombies.splice(i, 1); + ball.kills++; // this shot's running streak gore.push({ x: zb.x, z: zb.z, r: 0.45 + Math.random() * 0.35, a: 0.85 }); if (gore.length > 40) gore.shift(); for (let k = 0; k < 14; k++) parts.push({ @@ -30,9 +31,13 @@ function splatter(i) { t: 0.4 + Math.random() * 0.4, }); splat(); - ball.vx *= 0.5; ball.vz *= 0.5; // the kill takes pace off the ball + ball.vx *= TUNE.zPierce; ball.vz *= TUNE.zPierce; // keep enough pace to plow through the next sendBoy(zb.x, zb.z); // a boy sprints out to mop splatPoint('P'); + // escalating multi-kill fanfare — one shot, ≥2 zombies + if (ball.kills === 2) { G.flash = { text: 'DOUBLE KILL', t: 0.9 }; cheer(1.6, 0.45); voice('double_kill', 0.4); } + else if (ball.kills === 3) { G.flash = { text: 'TRIPLE KILL', t: 0.9 }; cheer(2.2, 0.6); voice('triple_kill', 0.4); } + else if (ball.kills >= 4) { G.flash = { text: `MASSACRE ×${ball.kills}`, t: 0.9 }; cheer(2.8, 0.7); voice('unbelievable', 0.4); } } export function updateZombies(dt) {