Add player enhancements and debug features

- Add away team defender (LD) for testing behaviors
- Add direction indicator (white line) showing player facing direction
- Initialize player facing angle based on team (home faces right, away faces left)
- Implement speed-based turning physics (faster = wider turns, rotation drops to 30% at max speed)
- Add debug visualizations for player targets (line and X marker) when DEBUG is true
- Increase rotation speed constant from 1 to 3 rad/s for more responsive turning

🤖 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 10:08:00 +02:00
parent a3ffc94916
commit ff97b227c2
3 changed files with 101 additions and 7 deletions

View File

@ -25,12 +25,12 @@ export const COLOR_GOAL_CREASE = 0x87ceeb;
// Game settings
export const FPS = 60;
export const DEBUG = true;
export const DEBUG = false;
// Player constants
export const PLAYER_RADIUS_GOALIE = 12; // pixels
export const PLAYER_RADIUS_SKATER = 10; // pixels
export const PLAYER_ROTATION_SPEED = 1; // radians per second
export const PLAYER_ROTATION_SPEED = 3; // radians per second
export const SPEED_SCALE_FACTOR = 10; // speed attribute (0-100) / 10 = m/s
export const GOAL_DECELERATION_RATE = 0.9; // Speed multiplier reduction after goal

View File

@ -6,7 +6,8 @@ import {
PLAYER_RADIUS_SKATER,
SPEED_SCALE_FACTOR,
MOVEMENT_STOP_THRESHOLD,
GOAL_DECELERATION_RATE
GOAL_DECELERATION_RATE,
DEBUG
} from '../config/constants';
import { CoordinateUtils } from '../utils/coordinates';
import { MathUtils } from '../utils/math';
@ -38,6 +39,13 @@ export class Player extends Phaser.GameObjects.Container {
// Rotation (angle in radians, 0 = facing right)
private currentAngle: number = 0;
// Debug visualizations
private debugTargetGraphics?: Phaser.GameObjects.Graphics;
private debugLineGraphics?: Phaser.GameObjects.Graphics;
// Direction indicator
private directionIndicator!: Phaser.GameObjects.Graphics;
constructor(
scene: Phaser.Scene,
id: string,
@ -62,6 +70,10 @@ export class Player extends Phaser.GameObjects.Container {
this.attributes = attributes;
this.state = 'defensive';
// Initialize facing direction based on team
// Home team (left side) faces right, Away team (right side) faces left
this.currentAngle = this.team === 'home' ? 0 : Math.PI;
// Listen for goal events
this.scene.events.on('goal', this.onGoal, this);
@ -78,6 +90,12 @@ export class Player extends Phaser.GameObjects.Container {
this.body.setCollideWorldBounds(true);
this.createSprite();
// Create debug graphics if DEBUG is enabled
if (DEBUG) {
this.debugTargetGraphics = scene.add.graphics();
this.debugLineGraphics = scene.add.graphics();
}
}
private createSprite() {
@ -105,7 +123,28 @@ export class Player extends Phaser.GameObjects.Container {
});
label.setOrigin(0.5, 0.5);
this.add([graphics, label]);
// Create direction indicator (small line showing facing direction)
this.directionIndicator = this.scene.add.graphics();
this.updateDirectionIndicator();
this.add([graphics, label, this.directionIndicator]);
}
/**
* Update the direction indicator to show current facing angle
*/
private updateDirectionIndicator() {
this.directionIndicator.clear();
const radius = this.playerPosition === 'G' ? PLAYER_RADIUS_GOALIE : PLAYER_RADIUS_SKATER;
// Draw line pointing right (container rotation will orient it correctly)
// Line goes from behind center to near the edge (0=center, 1=edge)
const startX = -radius * -0.5; // Start
const endX = radius * 1.0; // End
this.directionIndicator.lineStyle(3, 0x999999, 1);
this.directionIndicator.lineBetween(startX, 0, endX, 0); // Horizontal line, rotation handled by container
}
/**
@ -166,8 +205,13 @@ export class Player extends Phaser.GameObjects.Container {
const targetAngle = Math.atan2(dy, dx);
// Smoothly rotate toward target angle
// Scale rotation speed inversely with current velocity (faster = wider turns)
const deltaSeconds = delta / 1000;
const maxRotation = PLAYER_ROTATION_SPEED * deltaSeconds;
const currentSpeed = Math.sqrt(this.body.velocity.x ** 2 + this.body.velocity.y ** 2);
const maxSpeed = (this.attributes.speed / SPEED_SCALE_FACTOR) * SCALE;
const speedRatio = maxSpeed > 0 ? currentSpeed / maxSpeed : 0;
const turnPenalty = 1 - (speedRatio * 0.7); // At max speed, rotation is 30% of base
const maxRotation = PLAYER_ROTATION_SPEED * turnPenalty * deltaSeconds;
// Calculate shortest angular difference
const angleDiff = MathUtils.angleDifference(this.currentAngle, targetAngle);
@ -199,5 +243,44 @@ export class Player extends Phaser.GameObjects.Container {
const gamePos = CoordinateUtils.screenToGame(this.scene, bodyX, bodyY);
this.gameX = gamePos.x;
this.gameY = gamePos.y;
// Update debug visualizations
this.updateDebugVisuals();
}
/**
* Update debug visualizations (target position and path line)
*/
private updateDebugVisuals() {
if (!DEBUG || !this.debugTargetGraphics || !this.debugLineGraphics) return;
// Convert target position to screen coordinates
const targetScreen = CoordinateUtils.gameToScreen(this.scene, this.targetX, this.targetY);
const playerScreen = CoordinateUtils.gameToScreen(this.scene, this.gameX, this.gameY);
// Clear previous debug graphics
this.debugTargetGraphics.clear();
this.debugLineGraphics.clear();
// Draw line from player to target
const lineColor = this.team === 'home' ? 0x0000ff : 0xff0000;
this.debugLineGraphics.lineStyle(1, lineColor, 0.5);
this.debugLineGraphics.lineBetween(playerScreen.x, playerScreen.y, targetScreen.x, targetScreen.y);
// Draw target marker (X)
const markerSize = 5;
this.debugTargetGraphics.lineStyle(2, lineColor, 0.8);
this.debugTargetGraphics.lineBetween(
targetScreen.x - markerSize,
targetScreen.y - markerSize,
targetScreen.x + markerSize,
targetScreen.y + markerSize
);
this.debugTargetGraphics.lineBetween(
targetScreen.x + markerSize,
targetScreen.y - markerSize,
targetScreen.x - markerSize,
targetScreen.y + markerSize
);
}
}

View File

@ -49,11 +49,22 @@ export class GameScene extends Phaser.Scene {
'home',
'C',
-10,
-10,
-5,
{ speed: 80, skill: 75 }
);
this.players.push(homeCenter);
// Create one away defender at (15, 0) - right side for defending
const awayDefender = new Player(
this,
'away-LD',
'away',
'LD',
15,
0,
{ speed: 75, skill: 70 }
);
this.players.push(homeCenter, awayDefender);
}
private setupEventListeners() {