Add pause-aware goal reset timer with proper scene cleanup
- Add 3-second countdown timer after goal that resets the scene - Timer pauses when game is paused, respecting pause state - Freeze all game updates (puck, players, goals) during countdown - Properly reset timer flags in create() to fix post-restart state - Add safety checks in Player and Puck update to handle destroyed entities - Remove player goal deceleration behavior (superseded by scene freeze) - Add destroy() method to Player for proper resource cleanup - Clean up goal event listeners before scene restart 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ca6a444dec
commit
29885d1992
@ -6,7 +6,6 @@ import {
|
|||||||
PLAYER_RADIUS_SKATER,
|
PLAYER_RADIUS_SKATER,
|
||||||
SPEED_SCALE_FACTOR,
|
SPEED_SCALE_FACTOR,
|
||||||
MOVEMENT_STOP_THRESHOLD,
|
MOVEMENT_STOP_THRESHOLD,
|
||||||
GOAL_DECELERATION_RATE,
|
|
||||||
DEBUG,
|
DEBUG,
|
||||||
TACKLE_COOLDOWN,
|
TACKLE_COOLDOWN,
|
||||||
TACKLE_FALL_DURATION,
|
TACKLE_FALL_DURATION,
|
||||||
@ -97,8 +96,7 @@ export class Player extends Phaser.GameObjects.Container {
|
|||||||
// Home team (left side) faces right, Away team (right side) faces left
|
// Home team (left side) faces right, Away team (right side) faces left
|
||||||
this.currentAngle = this.team === 'home' ? 0 : Math.PI;
|
this.currentAngle = this.team === 'home' ? 0 : Math.PI;
|
||||||
|
|
||||||
// Listen for goal events
|
// Note: Goal events are handled by GameScene (freezes game and resets after 3s)
|
||||||
this.scene.events.on('goal', this.onGoal, this);
|
|
||||||
|
|
||||||
// Note: Player must be added to scene via scene.add.existing(player) and scene.physics.add.existing(player)
|
// Note: Player must be added to scene via scene.add.existing(player) and scene.physics.add.existing(player)
|
||||||
// This is handled by GameScene.addPlayer() method, which also sets up the physics body
|
// This is handled by GameScene.addPlayer() method, which also sets up the physics body
|
||||||
@ -182,28 +180,13 @@ export class Player extends Phaser.GameObjects.Container {
|
|||||||
this.targetY = targetY;
|
this.targetY = targetY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle goal event
|
|
||||||
*/
|
|
||||||
private onGoal(_data: { team: string; goal: string }) {
|
|
||||||
// Gradually decelerate player after goal
|
|
||||||
const decelerate = () => {
|
|
||||||
this.speedMultiplier *= GOAL_DECELERATION_RATE;
|
|
||||||
|
|
||||||
if (this.speedMultiplier > 0.01) {
|
|
||||||
this.scene.time.delayedCall(50, decelerate);
|
|
||||||
} else {
|
|
||||||
this.speedMultiplier = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
decelerate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update player movement each frame
|
* Update player movement each frame
|
||||||
*/
|
*/
|
||||||
public update(delta: number) {
|
public update(delta: number) {
|
||||||
|
// Skip update if body doesn't exist (player being destroyed)
|
||||||
|
if (!this.body) return;
|
||||||
|
|
||||||
const deltaSeconds = delta / 1000;
|
const deltaSeconds = delta / 1000;
|
||||||
|
|
||||||
// Check if player is fallen and should stay still
|
// Check if player is fallen and should stay still
|
||||||
@ -466,4 +449,17 @@ export class Player extends Phaser.GameObjects.Container {
|
|||||||
this.debugDetectionCircle.fillPath();
|
this.debugDetectionCircle.fillPath();
|
||||||
this.debugDetectionCircle.strokePath();
|
this.debugDetectionCircle.strokePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up resources when player is destroyed
|
||||||
|
*/
|
||||||
|
destroy(fromScene?: boolean) {
|
||||||
|
// Destroy detection sensor
|
||||||
|
if (this.detectionSensor) {
|
||||||
|
this.detectionSensor.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent destroy
|
||||||
|
super.destroy(fromScene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,6 +112,9 @@ export class Puck extends Phaser.GameObjects.Container {
|
|||||||
* Update puck game coordinates based on physics body position
|
* Update puck game coordinates based on physics body position
|
||||||
*/
|
*/
|
||||||
public update() {
|
public update() {
|
||||||
|
// Skip update if body doesn't exist (puck being destroyed)
|
||||||
|
if (!this.body) return;
|
||||||
|
|
||||||
// Use body center position (body.x/y is top-left, need to account for that)
|
// Use body center position (body.x/y is top-left, need to account for that)
|
||||||
const bodyX = this.body.x + this.body.width / 2;
|
const bodyX = this.body.x + this.body.width / 2;
|
||||||
const bodyY = this.body.y + this.body.height / 2;
|
const bodyY = this.body.y + this.body.height / 2;
|
||||||
|
|||||||
@ -61,17 +61,28 @@ export class GameScene extends Phaser.Scene {
|
|||||||
private isPaused: boolean = false;
|
private isPaused: boolean = false;
|
||||||
private pauseButton!: Phaser.GameObjects.Text;
|
private pauseButton!: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
|
// Goal reset timer
|
||||||
|
private goalResetTimer: number = 0;
|
||||||
|
private isWaitingForReset: boolean = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({ key: 'GameScene' });
|
super({ key: 'GameScene' });
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
|
console.log('[GameScene] Creating scene...');
|
||||||
|
|
||||||
|
// Reset goal timer flags
|
||||||
|
this.goalResetTimer = 0;
|
||||||
|
this.isWaitingForReset = false;
|
||||||
|
|
||||||
this.drawRink();
|
this.drawRink();
|
||||||
this.createGoals();
|
this.createGoals();
|
||||||
this.createPuck();
|
this.createPuck();
|
||||||
this.createPlayers();
|
this.createPlayers();
|
||||||
this.setupEventListeners();
|
this.setupEventListeners();
|
||||||
this.createPauseButton();
|
this.createPauseButton();
|
||||||
|
console.log('[GameScene] Scene created. Players:', this.players.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPlayers() {
|
private createPlayers() {
|
||||||
@ -210,7 +221,9 @@ export class GameScene extends Phaser.Scene {
|
|||||||
// Stop the puck (caught by net)
|
// Stop the puck (caught by net)
|
||||||
this.puck.body.setVelocity(0, 0);
|
this.puck.body.setVelocity(0, 0);
|
||||||
|
|
||||||
// Future: update score, trigger celebration, reset to faceoff, etc.
|
// Start 3-second countdown to reset
|
||||||
|
this.goalResetTimer = 3000;
|
||||||
|
this.isWaitingForReset = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,6 +340,17 @@ export class GameScene extends Phaser.Scene {
|
|||||||
update(_time: number, delta: number) {
|
update(_time: number, delta: number) {
|
||||||
if (this.isPaused) return;
|
if (this.isPaused) return;
|
||||||
|
|
||||||
|
// Handle goal reset timer
|
||||||
|
if (this.isWaitingForReset) {
|
||||||
|
this.goalResetTimer -= delta;
|
||||||
|
if (this.goalResetTimer <= 0) {
|
||||||
|
// Clean up before restart
|
||||||
|
this.events.off('goal');
|
||||||
|
this.scene.restart();
|
||||||
|
}
|
||||||
|
return; // Don't update anything while waiting for reset
|
||||||
|
}
|
||||||
|
|
||||||
this.updatePuck();
|
this.updatePuck();
|
||||||
this.updatePlayers(delta);
|
this.updatePlayers(delta);
|
||||||
this.checkGoals();
|
this.checkGoals();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user