Stop the brute pulsing, and let a boss die where you can see it
The pulse was drawStatic being told a height instead of reading one. _slice.py common-scales a sheet, so a crouched frame is genuinely shorter — 211 px against its neighbours' 224 — and forcing every frame to the same on-screen height stretched it back up, so the body swelled and shrank once per stride. Worst on the brute because it is the biggest and slowest. The rule already existed for the wound stages; it now applies to every frame, once, which also settles the shamblers and the steward (their cycles vary by up to 9%). A chapter boss now dies in its own beat instead of under the card announcing it: the world drops to a third speed for 1.2 s, the screen kicks, a shockwave ring blows out through 90 extra particles and six stains, and the CHAPTER DOWN card holds off until the pieces have landed — about 1.4 s, measured. Cards can hold off in general now (`wait`). First cut only delayed the card's countdown while still drawing it, which is worse than no delay: caught it in a screenshot before it shipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7d307d90b9
commit
b7899f122c
7 files changed
+61
-8
No files matched your search
+10
-3
@@ -484,8 +484,9 @@ export function endBossFight() {
|
||||
shots.length = 0;
|
||||
cheer(3.4, 0.9); voice('unbelievable', 0.3);
|
||||
G.card = { title: 'CHAPTER ' + c + ' DOWN', sub1: 'THE STANDS ARE ON THEIR FEET',
|
||||
sub2: 'GAME ' + (G.runGames + 1) + ' NEXT', color: UI.pick, t: TUNE.setCardT };
|
||||
ball.active = false; G.phase = 'over'; G.overT = TUNE.setCardT;
|
||||
sub2: 'GAME ' + (G.runGames + 1) + ' NEXT', color: UI.pick, t: TUNE.setCardT,
|
||||
wait: TUNE.bossDeathT }; // ...after the body has finished coming apart
|
||||
ball.active = false; G.phase = 'over'; G.overT = TUNE.setCardT + TUNE.bossDeathT;
|
||||
// hand back the game beat the boss interrupted — same contract resolveInterlude uses
|
||||
if (G.afterDuel) { G.afterClear = G.afterDuel; G.afterDuel = null; proceedAfterClear(); }
|
||||
}
|
||||
@@ -919,8 +920,14 @@ export function update(dt) {
|
||||
return;
|
||||
}
|
||||
if (G.flash) { G.flash.t -= dt; if (G.flash.t <= 0) G.flash = null; }
|
||||
if (G.card) { G.card.t -= dt; if (G.card.t <= 0) G.card = null; }
|
||||
// A card can wait before it shows. The chapter card used to land on the same frame as the boss
|
||||
// died, so the biggest gore burst in the game happened underneath it and nobody ever saw it.
|
||||
if (G.card) {
|
||||
if (G.card.wait > 0) G.card.wait -= dt;
|
||||
else { G.card.t -= dt; if (G.card.t <= 0) G.card = null; }
|
||||
}
|
||||
if (G.shake && (G.shake.t -= dt) <= 0) G.shake = null;
|
||||
if (G.bossBurst && (G.bossBurst.t -= dt) <= 0) G.bossBurst = null;
|
||||
if (G.boomFlash > 0) G.boomFlash -= dt;
|
||||
// A modal freezes the WORLD, not the clock: no zombie steps, no ball flight, no spawn timers,
|
||||
// so nobody gets eaten while reading a popup. idleT keeps running for the blink.
|
||||
|
||||
Reference in new issue
Block a user