From a1f675194aafe5341b6b10f20af3e97c152856a9 Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 18 Sep 2026 00:13:06 +0000 Subject: [PATCH] Queue player hits outside physics overlap --- src/game-v4.js | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/game-v4.js b/src/game-v4.js index ff48fae..c235ac7 100644 --- a/src/game-v4.js +++ b/src/game-v4.js @@ -43,6 +43,7 @@ class GameScene extends Phaser.Scene { this.gameState = 'playing'; this.lastPlayerShot = 0; this.lastPlayerHitAt = -Infinity; + this.pendingPlayerHits = []; this.wave = 1; this.defeated = 0; } @@ -305,6 +306,12 @@ class GameScene extends Phaser.Scene { return; } + this.processPlayerHits(); + if (this.gameState !== 'playing') { + this.drawHud(); + return; + } + this.updatePlayer(dt, deltaMs); this.updatePirates(dt); this.updateProjectiles(); @@ -430,21 +437,37 @@ class GameScene extends Phaser.Scene { hitPlayer(shot) { if (!shot?.active || this.gameState !== 'playing') return; + if (shot.getData('playerHitQueued')) return; const rawDamage = Number(shot.getData('damage')); const damage = clamp(Number.isFinite(rawDamage) ? rawDamage : PIRATE_SHOT_DAMAGE, 1, 25); - // Keep enemy -> player collision deliberately side-effect-light until the - // freeze is isolated. Projectile removal and hull mutation only. - shot.destroy(); + // The Arcade overlap callback only records the collision. Object removal + // and hull mutation happen from the scene update after the physics step. + shot.setData('playerHitQueued', true); + this.pendingPlayerHits.push({ shot, damage }); + } - if (this.time.now - this.lastPlayerHitAt < PLAYER_HIT_COOLDOWN_MS) return; - this.lastPlayerHitAt = this.time.now; + processPlayerHits() { + if (!this.pendingPlayerHits.length || this.gameState !== 'playing') return; - const currentHull = Number.isFinite(this.playerHull) ? this.playerHull : PLAYER_MAX_HULL; - this.playerHull = Math.max(0, currentHull - damage); + const hits = this.pendingPlayerHits; + this.pendingPlayerHits = []; - if (this.playerHull <= 0) this.finishGame(); + for (const { shot, damage } of hits) { + if (shot?.active) shot.destroy(); + + if (this.time.now - this.lastPlayerHitAt < PLAYER_HIT_COOLDOWN_MS) continue; + this.lastPlayerHitAt = this.time.now; + + const currentHull = Number.isFinite(this.playerHull) ? this.playerHull : PLAYER_MAX_HULL; + this.playerHull = Math.max(0, currentHull - damage); + + if (this.playerHull <= 0) { + this.finishGame(); + break; + } + } } spawnExplosion(x, y, scale = 1) {