Splatter: clear the wave by hand, tougher 2-hit shamblers, set cards, free depth
Feedback batch from a phone playtest: - Winning a game no longer auto-sweeps the court. The survivors stay and must be killed by hand (no new spawns, no scoring during the mop-up); only once the court is clear does play advance to the changeover / next game / set. Replaces sweepCourt() with a G.clearing gate + proceedAfterClear(). "CLEAR THE COURT". - Classic shamblers (a/b) now soak one splat-quality wound before they drop (shamblerHp=2) — swapping to new z_aw/z_bw wound skins that bleed the thin dynamic trickle plus a small impact pop. Only the runner stays one-shot glass; brute/boss unchanged. Ball, pellets and triple side-balls all respect hp. - Winning a SET shows a centered milestone card (a real pause) before the horde; one reusable drawCard() now backs both it and the reworded sudden-death card. - Player is no longer pinned to the baseline: free to advance up-court on keyboard (bounded at the net); touch keeps the baseline (drag is the serve-aim) and the horde/GUN burst re-brace there. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
13416ee749
commit
6df0ddb00f
10 files changed
+91
-42
No files matched your search
@@ -68,7 +68,7 @@ for (const n of ['p_idle1','p_idle2','p_bounce','p_bounce2','p_toss','p_smash','
|
||||
'x_ump','x_boyrun1','x_boyrun2','x_boyrun3','x_boyrun4','x_crowd','x_ads',
|
||||
'z_a1','z_a2','z_a3','z_a4','z_b1','z_b2','z_b3','z_b4','z_c1','z_c2',
|
||||
'z_f1','z_f2','z_f3','z_f4','z_g1','z_g2','z_gw','z_s1','z_s2','z_s3',
|
||||
'z_cw1','z_cw2', // wounded skins for multi-hit enemies (brute, racket boss)
|
||||
'z_cw1','z_cw2','z_aw','z_bw', // wounded skins for multi-hit enemies (racket boss, brute, and now the classic shamblers)
|
||||
'w_ball','w_bomb','w_triple','w_fire','w_gun', // weapon-rack icons
|
||||
'scoreboard']) {
|
||||
const img = new Image();
|
||||
@@ -153,6 +153,7 @@ function drawZombie(zb) {
|
||||
// zombies.js). Fall back to the healthy sprite until the wounded PNG has loaded.
|
||||
let name = 'z_' + v + frame;
|
||||
if (zb.variant === 'g' && zb.hp < TUNE.bruteHp && SPR.z_gw) name = 'z_gw';
|
||||
else if ((zb.variant === 'a' || zb.variant === 'b') && zb.hp < TUNE.shamblerHp && SPR['z_' + zb.variant + 'w']) name = 'z_' + zb.variant + 'w'; // gashed shambler
|
||||
else if (rk && zb.hp <= 1 && SPR.z_cw2) { name = 'z_cw2'; h = 1.52; } // headless: a head shorter, so the shoulders land where a whole zombie's do
|
||||
else if (rk && zb.hp === 2 && SPR.z_cw1) name = 'z_cw1';
|
||||
drawStatic(name, zb.x, zb.z, h, Math.floor(zb.walkT * 5.2) % 2);
|
||||
@@ -315,6 +316,17 @@ function drawRack() {
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// the centered milestone 'block': a real pause, front and center. Shared by the sudden-death duel
|
||||
// and the SET announcement so both read as the same interruption. Assumes textAlign is already set.
|
||||
function drawCard(title, sub1, sub2, color) {
|
||||
ctx.fillStyle = 'rgba(10,6,8,0.66)'; ctx.fillRect(0, H / 2 - 36, W, 64);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillStyle = color; ctx.font = 'bold 18px monospace'; ctx.fillText(title, W / 2, H / 2 - 26);
|
||||
ctx.fillStyle = '#e8e8dc'; ctx.font = 'bold 8px monospace';
|
||||
if (sub1) ctx.fillText(sub1, W / 2, H / 2 - 2);
|
||||
if (sub2) ctx.fillText(sub2, W / 2, H / 2 + 12);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ frame ----
|
||||
export function render() {
|
||||
ctx.setTransform(RES, 0, 0, RES, 0, 0); // logical W x H coordinates at RES density
|
||||
@@ -523,14 +535,11 @@ export function render() {
|
||||
ctx.font = 'bold 14px monospace'; ctx.fillStyle = '#ffffff';
|
||||
ctx.fillText(G.flash.text, W / 2, 60 + Math.sin(G.flash.t * 20) * 1);
|
||||
}
|
||||
if (G.interlude && G.interlude.introT > 0) { // the duel card: a real pause, front and center
|
||||
ctx.fillStyle = 'rgba(10,6,8,0.66)'; ctx.fillRect(0, H / 2 - 36, W, 64);
|
||||
ctx.fillStyle = '#ff5050'; ctx.font = 'bold 18px monospace';
|
||||
ctx.fillText('SUDDEN DEATH', W / 2, H / 2 - 26);
|
||||
ctx.fillStyle = '#e8e8dc'; ctx.font = 'bold 8px monospace';
|
||||
ctx.fillText('ONE POINT · THE LINES ARE LIVE', W / 2, H / 2 - 2);
|
||||
ctx.fillText('WIN IT FOR THE NEXT TIN', W / 2, H / 2 + 12);
|
||||
}
|
||||
// the sudden-death duel card, then (below it in priority) the SET milestone card — same block
|
||||
if (G.interlude && G.interlude.introT > 0)
|
||||
drawCard('SUDDEN DEATH', 'WIN THE POINT · THE LINES ARE LIVE', 'THE POINT WINS YOU A NEW WEAPON', '#ff5050');
|
||||
else if (G.card && G.card.t > 0)
|
||||
drawCard(G.card.title, G.card.sub1, G.card.sub2, G.card.color);
|
||||
if (TUNE.missHud && G.lastMiss && G.idleT - G.lastMiss.at < 3.5) { // last miss reason, live
|
||||
ctx.font = 'bold 8px monospace'; ctx.fillStyle = '#ff9060';
|
||||
ctx.fillText(G.lastMiss.text.toUpperCase(), W / 2, H - 28);
|
||||
|
||||
Reference in new issue
Block a user