diff --git a/src/game-v4.js b/src/game-v4.js index 6cf7b14..58d9547 100644 --- a/src/game-v4.js +++ b/src/game-v4.js @@ -373,6 +373,7 @@ class GameScene extends Phaser.Scene { } this.processPlayerHits(); + this.ensureLivePlayerState(); if (this.gameState !== 'playing') { this.drawHud(); this.publishHudState(); @@ -691,27 +692,26 @@ class GameScene extends Phaser.Scene { playPlayerHitReaction(damage = PIRATE_SHOT_DAMAGE) { if (!this.player?.active) return; - this.tweens.killTweensOf(this.player); - this.player.setAlpha(1); this.player.setTint(0xffd7d7); - - this.tweens.add({ - targets: this.player, - alpha: 0.45, - duration: 65, - yoyo: true, - repeat: 1, - ease: 'Quad.easeOut', - onComplete: () => { - if (!this.player?.active) return; - this.player.setAlpha(1); - this.player.clearTint(); - }, + this.time.delayedCall(110, () => { + if (this.player?.active && this.gameState === 'playing') this.player.clearTint(); }); this.cameras.main.shake(120, clamp(0.0035 + damage * 0.00055, 0.004, 0.012)); } + ensureLivePlayerState() { + if (this.gameState !== 'playing' || this.playerHull <= 0 || !this.player) return; + + if (!this.player.active) this.player.setActive(true); + if (!this.player.visible) this.player.setVisible(true); + if (this.player.alpha !== 1) this.player.setAlpha(1); + + if (this.player.body && !this.player.body.enable) { + this.player.body.enable = true; + } + } + buildHudState() { const player = this.player; if (!player) return null; diff --git a/tests/wiring.test.mjs b/tests/wiring.test.mjs index 1a9b45a..f90817e 100644 --- a/tests/wiring.test.mjs +++ b/tests/wiring.test.mjs @@ -208,9 +208,9 @@ test('processed player hits drive sprite and HUD hit reactions', async () => { assert.match(game, /this\.playerHitSequence \+= 1/); assert.match(game, /playPlayerHitReaction\(damage = PIRATE_SHOT_DAMAGE\)/); - assert.match(game, /alpha: 0\.45/); - assert.match(game, /repeat: 1/); + assert.match(game, /this\.player\.setTint\(0xffd7d7\)/); assert.match(game, /this\.cameras\.main\.shake\(120/); + assert.doesNotMatch(game, /targets: this\.player/); assert.doesNotMatch(game, /scaleX: this\.playerBaseScaleX/); assert.match(hud, /steam-player-card\.steam-hit/); assert.match(hud, /pulsePlayerHit\(state\.player\.hitSequence \?\? 0\)/); @@ -224,3 +224,15 @@ test('processed pirate shots are consumed and later projectiles start clean', as assert.match(source, /for \(const impact of hits\) \{[\s\S]*?if \(impact\.shot\?\.active\) impact\.shot\.destroy\(\)/); assert.match(source, /if \(shot\.getData\('playerHitQueued'\)\) return/); }); + + +test('non-lethal damage preserves the live player sprite and body', async () => { + const source = await read('src/game-v4.js'); + + assert.match(source, /this\.processPlayerHits\(\);\s*this\.ensureLivePlayerState\(\)/); + assert.match(source, /if \(this\.gameState !== 'playing' \|\| this\.playerHull <= 0 \|\| !this\.player\) return/); + assert.match(source, /if \(!this\.player\.active\) this\.player\.setActive\(true\)/); + assert.match(source, /if \(!this\.player\.visible\) this\.player\.setVisible\(true\)/); + assert.match(source, /if \(this\.player\.alpha !== 1\) this\.player\.setAlpha\(1\)/); + assert.match(source, /if \(this\.player\.body && !this\.player\.body\.enable\)/); +});