Add randomized bounce angle and speed reduction for goal post collisions

When the puck hits a goal post, it now:
- Loses 30% of its speed (reduces to 70%)
- Bounces at a slightly randomized angle (±17 degrees variation)

This creates more realistic and unpredictable post bounces.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Pierre Wessman 2025-10-02 14:21:20 +02:00
parent 1d257a5757
commit f342688143
2 changed files with 49 additions and 12 deletions

View File

@ -56,7 +56,10 @@ export const CENTER_DOT_RADIUS = 5; // pixels
// AI/Behavior constants // AI/Behavior constants
export const SHOOTING_RANGE = 10; // meters - max distance to attempt shot export const SHOOTING_RANGE = 10; // meters - max distance to attempt shot
export const SHOOTING_ANGLE_THRESHOLD = Math.PI / 3; // radians (60 degrees) export const SHOOTING_ANGLE_THRESHOLD = Math.PI / 3; // radians (2=90 degrees, 3=60, 4=45)
export const CLOSE_RANGE_DISTANCE = 3; // meters - distance for close-range shots (backhands, etc.)
export const CLOSE_RANGE_ANGLE_THRESHOLD = (2 * Math.PI) / 3; // radians (120°) - wider angle for close shots
export const CLOSE_RANGE_SHOT_SPEED_MULTIPLIER = 0.6; // Close-range shots have less power
export const GOALIE_RANGE = 3; // meters - how far goalie moves from center export const GOALIE_RANGE = 3; // meters - how far goalie moves from center
// Collision avoidance constants // Collision avoidance constants
@ -85,3 +88,7 @@ export const TACKLE_CLOSING_SPEED_WEAK = 1; // m/s - very weak check
export const TACKLE_CLOSING_SPEED_SOLID = 3; // m/s - solid check export const TACKLE_CLOSING_SPEED_SOLID = 3; // m/s - solid check
export const TACKLE_VELOCITY_MODIFIER_MIN = 0.3; // Minimum modifier for very low closing speed export const TACKLE_VELOCITY_MODIFIER_MIN = 0.3; // Minimum modifier for very low closing speed
export const TACKLE_VELOCITY_MODIFIER_MAX = 1.5; // Maximum modifier for high closing speed export const TACKLE_VELOCITY_MODIFIER_MAX = 1.5; // Maximum modifier for high closing speed
// Puck bounce constants
export const POST_BOUNCE_SPEED_REDUCTION = 0.7; // Puck loses 30% speed on post bounce
export const POST_BOUNCE_ANGLE_RANDOMNESS = 0.3; // Radians (~17 degrees) of random angle variation

View File

@ -29,7 +29,9 @@ import {
TACKLE_CLOSING_SPEED_WEAK, TACKLE_CLOSING_SPEED_WEAK,
TACKLE_CLOSING_SPEED_SOLID, TACKLE_CLOSING_SPEED_SOLID,
TACKLE_VELOCITY_MODIFIER_MIN, TACKLE_VELOCITY_MODIFIER_MIN,
TACKLE_VELOCITY_MODIFIER_MAX TACKLE_VELOCITY_MODIFIER_MAX,
POST_BOUNCE_SPEED_REDUCTION,
POST_BOUNCE_ANGLE_RANDOMNESS
} from '../config/constants'; } from '../config/constants';
import { Goal } from './Goal'; import { Goal } from './Goal';
import { Puck } from '../entities/Puck'; import { Puck } from '../entities/Puck';
@ -64,7 +66,7 @@ export class GameScene extends Phaser.Scene {
'home', 'home',
'C', 'C',
-1, -1,
-1, 0,
{ speed: 70, skill: 75, tackling: 70, balance: 75 } { speed: 70, skill: 75, tackling: 70, balance: 75 }
); );
@ -74,7 +76,7 @@ export class GameScene extends Phaser.Scene {
'away-LD', 'away-LD',
'away', 'away',
'LD', 'LD',
15, -15,
0, 0,
{ speed: 80, skill: 70, tackling: 85, balance: 80 } { speed: 80, skill: 70, tackling: 85, balance: 80 }
); );
@ -106,15 +108,15 @@ export class GameScene extends Phaser.Scene {
private createPuck() { private createPuck() {
// Initialize puck at center ice (0, 0 in game coordinates) // Initialize puck at center ice (0, 0 in game coordinates)
this.puck = new Puck(this, 0, 0); this.puck = new Puck(this, 20, 5);
// Add collisions between puck and goal posts // Add collisions between puck and goal posts with custom bounce handler
this.physics.add.collider(this.puck, this.leftGoal.getLeftPost()); this.physics.add.collider(this.puck, this.leftGoal.getLeftPost(), this.handlePuckPostBounce, undefined, this);
this.physics.add.collider(this.puck, this.leftGoal.getRightPost()); this.physics.add.collider(this.puck, this.leftGoal.getRightPost(), this.handlePuckPostBounce, undefined, this);
this.physics.add.collider(this.puck, this.leftGoal.getBackBar()); this.physics.add.collider(this.puck, this.leftGoal.getBackBar(), this.handlePuckPostBounce, undefined, this);
this.physics.add.collider(this.puck, this.rightGoal.getLeftPost()); this.physics.add.collider(this.puck, this.rightGoal.getLeftPost(), this.handlePuckPostBounce, undefined, this);
this.physics.add.collider(this.puck, this.rightGoal.getRightPost()); this.physics.add.collider(this.puck, this.rightGoal.getRightPost(), this.handlePuckPostBounce, undefined, this);
this.physics.add.collider(this.puck, this.rightGoal.getBackBar()); this.physics.add.collider(this.puck, this.rightGoal.getBackBar(), this.handlePuckPostBounce, undefined, this);
} }
private createGoals() { private createGoals() {
@ -260,6 +262,34 @@ export class GameScene extends Phaser.Scene {
}); });
} }
/**
* Handle puck bouncing off goal posts with randomized angle and speed reduction
*/
private handlePuckPostBounce() {
// Get current puck velocity
const vx = this.puck.body.velocity.x;
const vy = this.puck.body.velocity.y;
// Calculate current angle and speed
const currentAngle = Math.atan2(vy, vx);
const currentSpeed = Math.sqrt(vx * vx + vy * vy);
// Add random variation to bounce angle (-0.3 to +0.3 radians, ~±17 degrees)
const randomAngle = (Math.random() - 0.5) * 2 * POST_BOUNCE_ANGLE_RANDOMNESS;
const newAngle = currentAngle + randomAngle;
// Reduce speed by 30%
const newSpeed = currentSpeed * POST_BOUNCE_SPEED_REDUCTION;
// Apply new velocity
this.puck.body.setVelocity(
Math.cos(newAngle) * newSpeed,
Math.sin(newAngle) * newSpeed
);
console.log(`[Post bounce] Speed: ${(currentSpeed / SCALE).toFixed(1)}${(newSpeed / SCALE).toFixed(1)} m/s, Angle variation: ${(randomAngle * 180 / Math.PI).toFixed(1)}°`);
}
private executeShot(player: Player, targetX: number, targetY: number) { private executeShot(player: Player, targetX: number, targetY: number) {
console.log(`${player.id} shoots toward (${targetX}, ${targetY})`); console.log(`${player.id} shoots toward (${targetX}, ${targetY})`);