From 93cb7321101bc0ffbdb7a1d0ceaafd614db07822 Mon Sep 17 00:00:00 2001 From: Pierre Date: Wed, 1 Oct 2025 14:31:51 +0000 Subject: [PATCH] goal events --- src/entities/Puck.ts | 12 +++++------- src/game/GameScene.ts | 18 +++++++++++++----- src/game/Goal.ts | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/entities/Puck.ts b/src/entities/Puck.ts index 639abd4..3935348 100644 --- a/src/entities/Puck.ts +++ b/src/entities/Puck.ts @@ -4,8 +4,7 @@ import { SCALE } from '../config/constants'; export type PuckState = 'loose' | 'carried' | 'passing' | 'shot'; export class Puck extends Phaser.GameObjects.Container { - private sprite!: Phaser.GameObjects.Graphics; - private body!: Phaser.Physics.Arcade.Body; + declare body: Phaser.Physics.Arcade.Body; // Position in game coordinates (meters) public gameX: number; @@ -39,12 +38,12 @@ export class Puck extends Phaser.GameObjects.Container { this.body.setSize(10, 10); this.body.setOffset(-5, -5); // Center the body on the container - // Prevent physics tunneling - this.body.setMaxVelocity(1000, 1000); + // Set max velocity (allow up to x m/s) + this.body.setMaxVelocity(50 * SCALE, 50 * SCALE); // Set initial velocity (5 m/s in a random direction for testing) - const angle = 3.1415; //Math.random() * Math.PI * 2; - const speed = 30 * SCALE; // 5 m/s converted to pixels/s + const angle = Math.PI * .0; //Math.random() * Math.PI * 2; + const speed = 100 * SCALE; // 5 m/s converted to pixels/s this.body.setVelocity( Math.cos(angle) * speed, Math.sin(angle) * speed @@ -72,7 +71,6 @@ export class Puck extends Phaser.GameObjects.Container { graphics.fillCircle(-1, -1, 2); this.add(graphics); - this.sprite = graphics; } /** diff --git a/src/game/GameScene.ts b/src/game/GameScene.ts index 6ce39c1..a2991ef 100644 --- a/src/game/GameScene.ts +++ b/src/game/GameScene.ts @@ -6,13 +6,10 @@ import { SCALE, BLUE_LINE_OFFSET, GOAL_LINE_OFFSET, - GOAL_WIDTH, - GOAL_DEPTH, COLOR_ICE, COLOR_BOARDS, COLOR_RED_LINE, - COLOR_BLUE_LINE, - COLOR_GOAL_CREASE + COLOR_BLUE_LINE } from '../config/constants'; import { Goal } from './Goal'; import { Puck } from '../entities/Puck'; @@ -30,6 +27,15 @@ export class GameScene extends Phaser.Scene { this.drawRink(); this.createGoals(); this.createPuck(); + this.setupEventListeners(); + } + + private setupEventListeners() { + // Listen for goal events + this.events.on('goal', (data: { team: string; goal: string }) => { + console.log(`[GameScene] Goal scored by ${data.team} team in ${data.goal} goal`); + // Future: update score, trigger celebration, reset to faceoff, etc. + }); } private createPuck() { @@ -105,6 +111,8 @@ export class GameScene extends Phaser.Scene { } update() { - // Game loop - will be used in later phases + // Check for goals + this.leftGoal.checkGoal(this.puck); + this.rightGoal.checkGoal(this.puck); } } diff --git a/src/game/Goal.ts b/src/game/Goal.ts index 2535415..a634c6d 100644 --- a/src/game/Goal.ts +++ b/src/game/Goal.ts @@ -1,5 +1,6 @@ import Phaser from 'phaser'; import { SCALE, GOAL_WIDTH, GOAL_DEPTH } from '../config/constants'; +import type { Puck } from '../entities/Puck'; export class Goal extends Phaser.GameObjects.Container { private leftPost!: Phaser.Physics.Arcade.Image; @@ -7,6 +8,7 @@ export class Goal extends Phaser.GameObjects.Container { private backBar!: Phaser.Physics.Arcade.Image; private scoringZone!: Phaser.GameObjects.Zone; private isLeftGoal: boolean; + private puckInZone: boolean = false; constructor(scene: Phaser.Scene, x: number, y: number, isLeftGoal: boolean = true) { super(scene, x, y); @@ -19,10 +21,10 @@ export class Goal extends Phaser.GameObjects.Container { } private createGoalStructure() { - const postThickness = 0.2 * SCALE; // Post thickness + const postThickness = 0.3 * SCALE; // Post thickness const goalWidth = GOAL_WIDTH * SCALE; // Width of goal opening (top to bottom) const goalDepth = GOAL_DEPTH * SCALE; // Depth extending into zone - const barThickness = 0.2 * SCALE; + const barThickness = 0.3 * SCALE; // Thicker bar to prevent high-speed puck tunneling // Create graphics for visual representation const graphics = this.scene.add.graphics(); @@ -113,4 +115,30 @@ export class Goal extends Phaser.GameObjects.Container { public getScoringZone(): Phaser.GameObjects.Zone { return this.scoringZone; } + + public checkGoal(puck: Puck): void { + const puckBody = puck.body; + const zoneBody = this.scoringZone.body as Phaser.Physics.Arcade.Body; + + if (!puckBody || !zoneBody) return; + + // Check if puck overlaps with scoring zone + const overlap = Phaser.Geom.Intersects.RectangleToRectangle( + new Phaser.Geom.Rectangle(puckBody.x, puckBody.y, puckBody.width, puckBody.height), + new Phaser.Geom.Rectangle(zoneBody.x, zoneBody.y, zoneBody.width, zoneBody.height) + ); + + if (overlap && !this.puckInZone) { + this.puckInZone = true; + const scoringTeam = this.isLeftGoal ? 'away' : 'home'; + + // Emit goal event + this.scene.events.emit('goal', { + team: scoringTeam, + goal: this.isLeftGoal ? 'left' : 'right' + }); + } else if (!overlap && this.puckInZone) { + this.puckInZone = false; + } + } }