Move goal-scored logic to behavior system with faceoff positioning
- Add isGoalScored flag to GameState for behavior tree decision-making - Update SkaterBehavior to skate to center ice (0,0) when goal scored - Update GoalieBehavior to return to center of goal when goal scored - Remove update loop freeze from GameScene, now handled by behaviors - Update CLAUDE.md with comprehensive subsystem documentation All player logic now contained within the behavior system instead of GameScene update loop, improving separation of concerns and making post-goal behavior more realistic (players skate to faceoff positions). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
29885d1992
commit
581574fa1c
427
CLAUDE.md
427
CLAUDE.md
@ -37,74 +37,397 @@ pnpm run preview
|
|||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
config/
|
config/
|
||||||
constants.ts # All game constants (rink dimensions, colors, speeds)
|
constants.ts # All game constants (rink dimensions, colors, speeds, AI parameters)
|
||||||
game/
|
game/
|
||||||
main.ts # Phaser game initialization and config
|
main.ts # Phaser game initialization and config
|
||||||
GameScene.ts # Main game scene (rendering, game loop)
|
GameScene.ts # Main game scene (rendering, game loop, physics, event handling)
|
||||||
Goal.ts # Goal structure with physics bodies
|
Goal.ts # Goal structure with physics bodies and scoring detection
|
||||||
entities/ # Player and Puck classes (planned)
|
entities/
|
||||||
systems/ # BehaviorTree, PositioningSystem, PuckSystem (planned)
|
Player.ts # Player entity with physics, movement, and detection systems
|
||||||
|
Puck.ts # Puck entity with physics and state management
|
||||||
|
systems/
|
||||||
|
BehaviorTree.ts # Main behavior tree system for AI decision-making
|
||||||
|
BehaviorNodes.ts # Base classes (Selector, Sequence, Condition, Action)
|
||||||
|
behaviors/
|
||||||
|
SkaterBehavior.ts # Top-level skater AI (context selector)
|
||||||
|
GoalieBehavior.ts # Goalie-specific AI
|
||||||
|
TransitionBehavior.ts # Loose puck / neutral zone behavior
|
||||||
|
offensive/
|
||||||
|
PuckCarrierBehavior.ts # Shoot/carry/evade decisions
|
||||||
|
OffensiveSupportBehavior.ts # Support when teammate has puck (planned)
|
||||||
|
defensive/
|
||||||
|
DefensiveBehavior.ts # Chase and pressure opponent
|
||||||
|
types/
|
||||||
|
game.ts # TypeScript types and interfaces
|
||||||
|
utils/
|
||||||
|
coordinates.ts # Game ↔ screen coordinate conversion
|
||||||
|
math.ts # Distance, angle utilities
|
||||||
```
|
```
|
||||||
|
|
||||||
### Implementation Phases (from PLAN.md)
|
### Implementation Status
|
||||||
|
|
||||||
The project follows a phased approach:
|
**✓ Completed Phases:**
|
||||||
1. **Phase 1** (✓): Environment setup, rink rendering
|
- **Phase 1**: Environment setup, rink rendering
|
||||||
2. **Phase 2** (Next): Player entities (12 players: 10 skaters + 2 goalies) with smooth movement
|
- **Phase 2**: Player entities with smooth acceleration/deceleration and rotation
|
||||||
3. **Phase 3**: Puck entity and possession mechanics
|
- **Phase 3**: Puck physics and possession mechanics
|
||||||
4. **Phase 4**: Behavior tree for puck carrier decisions (shoot/pass/carry)
|
- **Phase 4**: Puck carrier behavior (shoot/carry/evade)
|
||||||
5. **Phase 5**: Team offensive positioning system
|
- **Phase 6**: Basic defensive behavior (chase puck carrier)
|
||||||
6. **Phase 6**: Defensive behaviors and pressure mechanics
|
- **Phase 7**: Basic goalie AI (track puck position)
|
||||||
7. **Phase 7**: Goalie AI
|
- **Phase 8**: Goal detection, scoring system, pause-aware reset timers
|
||||||
8. **Phase 8**: Game flow (goals, faceoffs, scoring)
|
|
||||||
9. **Phase 9**: Polish and tuning
|
|
||||||
|
|
||||||
### Key Systems (Planned)
|
**🚧 In Progress / Partial:**
|
||||||
|
- **Phase 5**: Offensive support (placeholder only)
|
||||||
|
- Tackle mechanics (implemented but needs tuning)
|
||||||
|
- Puck reception (implemented with skill-based probability)
|
||||||
|
|
||||||
**Behavior Trees**: Decision-making engine that runs every tick
|
**📋 Planned:**
|
||||||
- Evaluates game state (possession, positions, threats)
|
- Passing AI (identify and execute passes)
|
||||||
- Weights actions by player attributes (Hockey IQ, Skill, Speed)
|
- Advanced offensive positioning (heat maps, formations)
|
||||||
- Outputs: move, pass, shoot, or defensive actions
|
- Faceoffs and game flow states
|
||||||
|
- Save mechanics for goalies
|
||||||
|
|
||||||
**Tactical Positioning**: Heat map-based positioning
|
---
|
||||||
- Different formations based on game situation (offense/defense)
|
|
||||||
- Players move toward ideal positions modified by:
|
|
||||||
- Puck location
|
|
||||||
- Teammate spacing
|
|
||||||
- Opponent positions
|
|
||||||
- Player stamina/speed
|
|
||||||
|
|
||||||
**Puck Movement**:
|
## Core Systems Documentation
|
||||||
- Pass success = f(passer skill, distance, pressure, receiver skill)
|
|
||||||
- Shots use trajectory calculation with goalie save probability
|
|
||||||
- Smooth interpolation for visual feedback
|
|
||||||
|
|
||||||
## Technical Details
|
### 1. Behavior Tree System
|
||||||
|
|
||||||
- **Framework**: Phaser 3.90.0 (with Arcade Physics)
|
**Location:** [src/systems/BehaviorTree.ts](src/systems/BehaviorTree.ts), [src/systems/BehaviorNodes.ts](src/systems/BehaviorNodes.ts)
|
||||||
|
|
||||||
|
**Purpose:** AI decision-making engine that runs at 60 FPS for each player.
|
||||||
|
|
||||||
|
**Architecture:**
|
||||||
|
- **BehaviorNode**: Abstract base class for all nodes
|
||||||
|
- **Selector**: OR logic - tries children until one succeeds
|
||||||
|
- **Sequence**: AND logic - all children must succeed
|
||||||
|
- **Condition**: Boolean predicate functions
|
||||||
|
- **Action**: Leaf nodes that return PlayerAction
|
||||||
|
|
||||||
|
**Decision Tree Structure:**
|
||||||
|
```
|
||||||
|
Root Selector
|
||||||
|
├─ Goalie? → GoalieBehavior
|
||||||
|
└─ Skater? → SkaterBehavior
|
||||||
|
├─ Has puck? → PuckCarrierBehavior (shoot/carry/evade)
|
||||||
|
├─ Teammate has puck? → OffensiveSupportBehavior (planned)
|
||||||
|
├─ Opponent has puck? → DefensiveBehavior (chase)
|
||||||
|
└─ Loose puck → TransitionBehavior (chase loose puck)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Files:**
|
||||||
|
- [BehaviorTree.ts:26-60](src/systems/BehaviorTree.ts#L26-L60): Main tree evaluation
|
||||||
|
- [SkaterBehavior.ts:21-39](src/systems/behaviors/SkaterBehavior.ts#L21-L39): Context-based selector
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Player Entity System
|
||||||
|
|
||||||
|
**Location:** [src/entities/Player.ts](src/entities/Player.ts)
|
||||||
|
|
||||||
|
**Purpose:** Player physics, movement, rotation, and nearby player detection.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
|
||||||
|
**Movement System** ([Player.ts:186-286](src/entities/Player.ts#L186-L286)):
|
||||||
|
- Smooth acceleration with ease-out curve (PLAYER_ACCELERATION)
|
||||||
|
- Speed-dependent rotation (faster = wider turns)
|
||||||
|
- Deceleration when near target or after goals
|
||||||
|
- Stop threshold to prevent jittering (MOVEMENT_STOP_THRESHOLD)
|
||||||
|
|
||||||
|
**Player Detection System** ([Player.ts:324-387](src/entities/Player.ts#L324-L387)):
|
||||||
|
- Physics-based circular sensor (NEAR_PLAYER_DETECTION_RADIUS = 4m)
|
||||||
|
- Field-of-view filtering (NEAR_PLAYER_DETECTION_ANGLE = 180°)
|
||||||
|
- Maintains sets: `nearbyPlayers`, `nearbyOpponents`, `nearbyTeammates`
|
||||||
|
- Methods: `getDetectedOpponents()`, `getDetectedTeammates()`
|
||||||
|
|
||||||
|
**Tackle System** ([Player.ts:290-312](src/entities/Player.ts#L290-L312)):
|
||||||
|
- Cooldown timer (TACKLE_COOLDOWN = 1000ms)
|
||||||
|
- Fall duration when tackled (TACKLE_FALL_DURATION = 500ms)
|
||||||
|
- Speed requirement (TACKLE_MIN_SPEED = 2 m/s)
|
||||||
|
- Angle-based effectiveness modifiers
|
||||||
|
|
||||||
|
**Player Attributes** ([types/game.ts:27-33](src/types/game.ts#L27-L33)):
|
||||||
|
- `speed`: Movement speed (0-100) → m/s via SPEED_SCALE_FACTOR
|
||||||
|
- `skill`: Pass/shot accuracy, decision quality
|
||||||
|
- `tackling`: Tackle success probability
|
||||||
|
- `balance`: Resist being tackled
|
||||||
|
- `handling`: Puck reception and control
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Puck Entity System
|
||||||
|
|
||||||
|
**Location:** [src/entities/Puck.ts](src/entities/Puck.ts)
|
||||||
|
|
||||||
|
**Purpose:** Puck physics, state management, and possession tracking.
|
||||||
|
|
||||||
|
**Puck States** ([types/game.ts:22](src/types/game.ts#L22)):
|
||||||
|
- `loose`: Free on ice, physics-driven
|
||||||
|
- `carried`: Held by player (carrier ID tracked)
|
||||||
|
- `passing`: In flight between players (future)
|
||||||
|
- `shot`: Shot toward goal
|
||||||
|
|
||||||
|
**Physics Configuration** ([Puck.ts:36-56](src/entities/Puck.ts#L36-L56)):
|
||||||
|
- Circular collision body (PUCK_RADIUS = 0.2m)
|
||||||
|
- Max velocity: MAX_PUCK_VELOCITY = 50 m/s
|
||||||
|
- Drag (ice friction): PUCK_DRAG = 200 pixels/s²
|
||||||
|
- Bounce coefficient: PUCK_BOUNCE = 0.6 (loses energy)
|
||||||
|
- World bounds collision enabled
|
||||||
|
|
||||||
|
**Key Methods:**
|
||||||
|
- `setCarrier(playerId, team)`: Assign possession
|
||||||
|
- `setLoose()`: Release to physics simulation
|
||||||
|
- `update()`: Sync game coordinates with physics body
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Puck Carrier Behavior
|
||||||
|
|
||||||
|
**Location:** [src/systems/behaviors/offensive/PuckCarrierBehavior.ts](src/systems/behaviors/offensive/PuckCarrierBehavior.ts)
|
||||||
|
|
||||||
|
**Purpose:** Tactical decisions when player has possession.
|
||||||
|
|
||||||
|
**Decision Priority:**
|
||||||
|
1. **Evade** if opponent threatens head-on ([PuckCarrierBehavior.ts:104-254](src/systems/behaviors/offensive/PuckCarrierBehavior.ts#L104-L254))
|
||||||
|
2. **Shoot** if good opportunity ([PuckCarrierBehavior.ts:262-308](src/systems/behaviors/offensive/PuckCarrierBehavior.ts#L262-L308))
|
||||||
|
3. **Carry** toward opponent's net (default)
|
||||||
|
|
||||||
|
**Evasion System:**
|
||||||
|
- Uses physics-based player detection (NEAR_PLAYER_DETECTION_RADIUS)
|
||||||
|
- Checks if opponent is within 60° of goal direction
|
||||||
|
- Maintains consistent evasion direction per opponent (stored in `activeEvasions` map)
|
||||||
|
- Evasion angle: ±60° (EVASION_ANGLE) from goal direction
|
||||||
|
- Clears evasion when opponent leaves detection zone
|
||||||
|
|
||||||
|
**Shooting Logic:**
|
||||||
|
- Must be in front of goal (not behind)
|
||||||
|
- Distance ≤ SHOOTING_RANGE (10m)
|
||||||
|
- Angle-based accuracy:
|
||||||
|
- Close range (≤3m): 120° shooting angle allowed
|
||||||
|
- Normal range: 60° shooting angle required
|
||||||
|
- Aims at center of net (targetY = 0)
|
||||||
|
|
||||||
|
**Debug Visualization** (when DEBUG = true):
|
||||||
|
- Green line to goal
|
||||||
|
- Red circle around threats being evaded
|
||||||
|
- Yellow arrow showing evasion direction
|
||||||
|
- Orange circles for detected opponents
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. GameScene System
|
||||||
|
|
||||||
|
**Location:** [src/game/GameScene.ts](src/game/GameScene.ts)
|
||||||
|
|
||||||
|
**Purpose:** Main game loop, physics management, collision detection, event handling.
|
||||||
|
|
||||||
|
**Key Responsibilities:**
|
||||||
|
|
||||||
|
**Physics Setup:**
|
||||||
|
- Player-player collisions (including tackle mechanics)
|
||||||
|
- Player-puck overlaps (pickup and reception)
|
||||||
|
- Puck-goal post collisions with bounce
|
||||||
|
- Detection sensor overlaps (nearby player tracking)
|
||||||
|
|
||||||
|
**Puck Management:**
|
||||||
|
- Carrier positioning: puck stays 1m in front of carrier
|
||||||
|
- Pickup radius: PUCK_PICKUP_RADIUS = 1.5m
|
||||||
|
- Reception skill checks (PUCK_RECEPTION_BASE_CHANCE)
|
||||||
|
- Speed-based reception difficulty
|
||||||
|
|
||||||
|
**Shooting System:**
|
||||||
|
- Shot speed: SHOT_SPEED = 30 m/s (or 0.6× for close range)
|
||||||
|
- Post bounce: reduces speed and adds random angle variation
|
||||||
|
- Goal detection via overlap with scoring zone
|
||||||
|
|
||||||
|
**Tackle System:**
|
||||||
|
- Cooldown enforcement (TACKLE_COOLDOWN)
|
||||||
|
- Angle-based effectiveness (head-on = 100%, side = 70%, etc.)
|
||||||
|
- Closing speed modifiers
|
||||||
|
- Puck loose probability (TACKLE_PUCK_LOOSE_CHANCE = 60%)
|
||||||
|
|
||||||
|
**Goal System:**
|
||||||
|
- Freeze game on goal event
|
||||||
|
- 3-second pause-aware timer
|
||||||
|
- Player deceleration (GOAL_DECELERATION_RATE)
|
||||||
|
- Reset positions to center ice
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. Coordinate System
|
||||||
|
|
||||||
|
**Location:** [src/utils/coordinates.ts](src/utils/coordinates.ts)
|
||||||
|
|
||||||
|
**Purpose:** Convert between game coordinates (meters) and screen coordinates (pixels).
|
||||||
|
|
||||||
|
**Critical Details:**
|
||||||
|
- **Game coordinates:** Origin (0, 0) at center of rink, meters as floats
|
||||||
|
- **Screen coordinates:** Origin at top-left, pixels
|
||||||
|
- **Scale factor:** 1 meter = 20 pixels (SCALE constant)
|
||||||
|
- **Y-axis inversion:** Game Y increases upward, screen Y increases downward
|
||||||
|
|
||||||
|
**Key Methods:**
|
||||||
|
- `gameToScreen(scene, gameX, gameY)`: Meters → pixels
|
||||||
|
- `screenToGame(scene, screenX, screenY)`: Pixels → meters
|
||||||
|
- `getScreenCenter(scene)`: Canvas center in pixels
|
||||||
|
|
||||||
|
**Rink Layout:**
|
||||||
|
- Rink: 60m × 30m
|
||||||
|
- Left goal: x = -26m (GOAL_LINE_OFFSET)
|
||||||
|
- Right goal: x = +26m
|
||||||
|
- Blue lines: x = ±9m (BLUE_LINE_OFFSET)
|
||||||
|
- Center ice: (0, 0)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. Constants Configuration
|
||||||
|
|
||||||
|
**Location:** [src/config/constants.ts](src/config/constants.ts)
|
||||||
|
|
||||||
|
**Purpose:** Centralized configuration for all game parameters.
|
||||||
|
|
||||||
|
**Categories:**
|
||||||
|
|
||||||
|
**Game Settings:**
|
||||||
|
- DEBUG, FPS, UI_BOTTOM_PADDING
|
||||||
|
|
||||||
|
**Rink Dimensions:**
|
||||||
|
- RINK_LENGTH, RINK_WIDTH, SCALE, corner radius, zone lines
|
||||||
|
|
||||||
|
**Player Constants:**
|
||||||
|
- Radius (goalie vs skater), rotation speed, acceleration/deceleration
|
||||||
|
- Speed scale factor, movement threshold
|
||||||
|
|
||||||
|
**Puck Constants:**
|
||||||
|
- Radius, pickup range, carry distance, max velocity
|
||||||
|
- Drag, bounce, shot speed, reception parameters
|
||||||
|
|
||||||
|
**AI/Behavior:**
|
||||||
|
- Shooting range and angle thresholds (normal vs close-range)
|
||||||
|
- Goalie range, detection radius and angle
|
||||||
|
- Evasion angle
|
||||||
|
|
||||||
|
**Tackle Mechanics:**
|
||||||
|
- Success modifiers, cooldown, fall duration
|
||||||
|
- Angle thresholds and modifiers
|
||||||
|
- Closing speed thresholds
|
||||||
|
|
||||||
|
**Collision/Physics:**
|
||||||
|
- Post bounce reduction, puck loose chance
|
||||||
|
- Reception skill scaling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Definitions
|
||||||
|
|
||||||
|
**Location:** [src/types/game.ts](src/types/game.ts)
|
||||||
|
|
||||||
|
**Key Types:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
PlayerPosition: 'LW' | 'C' | 'RW' | 'LD' | 'RD' | 'G'
|
||||||
|
TeamSide: 'home' | 'away'
|
||||||
|
PlayerState: 'offensive' | 'defensive'
|
||||||
|
PuckState: 'loose' | 'carried' | 'passing' | 'shot'
|
||||||
|
|
||||||
|
PlayerAttributes: {
|
||||||
|
speed, skill, tackling, balance, handling
|
||||||
|
}
|
||||||
|
|
||||||
|
GameState: {
|
||||||
|
puck: Puck
|
||||||
|
allPlayers: Player[]
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerAction: {
|
||||||
|
type: 'move' | 'chase_puck' | 'skate_with_puck' | 'shoot' | 'idle'
|
||||||
|
targetX?, targetY?
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Stack
|
||||||
|
|
||||||
|
- **Framework**: Phaser 3.90.0 (Arcade Physics engine)
|
||||||
- **TypeScript**: Strict mode enabled
|
- **TypeScript**: Strict mode enabled
|
||||||
- **Build Tool**: Vite 5.4
|
- **Build Tool**: Vite 5.4
|
||||||
- **Target FPS**: 60 (constant in constants.ts)
|
- **Target FPS**: 60 (configured in constants.ts)
|
||||||
- **Physics**: Arcade physics with zero gravity (top-down view)
|
- **Physics**: Arcade physics with zero gravity (top-down view)
|
||||||
|
- **Coordinate System**: Centered origin (0,0), meters as float values
|
||||||
|
- **Rendering Scale**: 1 meter = 20 pixels
|
||||||
|
|
||||||
## Configuration
|
---
|
||||||
|
|
||||||
All magic numbers and game constants are centralized in `src/config/constants.ts`:
|
## Debug Features
|
||||||
- Rink dimensions and zone lines
|
|
||||||
- Goal dimensions
|
|
||||||
- Colors (ice, boards, lines)
|
|
||||||
- Scale factor (meters to pixels)
|
|
||||||
- Game settings (FPS)
|
|
||||||
|
|
||||||
Future constants will include:
|
**Toggle:** Set `DEBUG = true` in [constants.ts](src/config/constants.ts)
|
||||||
- Player speeds, shot speeds, pass speeds
|
|
||||||
- AI decision probabilities
|
|
||||||
- Attribute ranges
|
|
||||||
|
|
||||||
## Development Notes
|
**Visual Overlays:**
|
||||||
|
- **Player movement:** Line and marker showing target position
|
||||||
|
- **Player detection:** Magenta wedge showing field-of-view sensor
|
||||||
|
- **Puck carrier evasion:**
|
||||||
|
- Green line to goal
|
||||||
|
- Red circles around detected threats
|
||||||
|
- Yellow/green arrows showing evasion direction
|
||||||
|
- Orange circles for all nearby opponents
|
||||||
|
|
||||||
- **Incremental testing**: Test each phase thoroughly before proceeding
|
**Console Logging:**
|
||||||
- **Debug visualization**: Add toggleable overlays for targets, zones, etc.
|
- Goal events with team and goal location
|
||||||
- **Tuning over precision**: Numbers are starting points; tune based on feel
|
- Shot attempts with player ID
|
||||||
- Refer to PLAN.md for detailed phase requirements and validation criteria
|
- Tackle results and success calculations
|
||||||
- Refer to NOTES.md for architectural decisions and design notes
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
**Hot Reload Development:**
|
||||||
|
```bash
|
||||||
|
pnpm run dev # Starts on localhost:3000 with hot reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**Testing Approach:**
|
||||||
|
- Test each subsystem incrementally before integration
|
||||||
|
- Use DEBUG mode to visualize AI decision-making
|
||||||
|
- Tune constants based on gameplay feel (see [constants.ts](src/config/constants.ts))
|
||||||
|
- Validate physics with edge cases (goal posts, rink boundaries)
|
||||||
|
|
||||||
|
**Key Tuning Parameters:**
|
||||||
|
- Player acceleration/deceleration curves → smooth movement feel
|
||||||
|
- Detection radius/angle → evasion responsiveness
|
||||||
|
- Shooting angles → goal frequency balance
|
||||||
|
- Tackle modifiers → physical gameplay intensity
|
||||||
|
- Puck drag/bounce → realistic puck physics
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[PLAN.md](PLAN.md)**: Phase-by-phase implementation plan
|
||||||
|
- **[NOTES.md](NOTES.md)**: Architecture decisions and design rationale
|
||||||
|
- **[REVIEW.md](REVIEW.md)**: Progress reviews and lessons learned
|
||||||
|
- **[CLAUDE.md](CLAUDE.md)** (this file): System reference for AI assistant
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Patterns
|
||||||
|
|
||||||
|
**Adding New Behaviors:**
|
||||||
|
1. Create behavior class extending `BehaviorNode` in `src/systems/behaviors/`
|
||||||
|
2. Implement `tick(player, gameState)` method
|
||||||
|
3. Add to appropriate selector in `SkaterBehavior` or `GoalieBehavior`
|
||||||
|
4. Test in isolation before integration
|
||||||
|
|
||||||
|
**Adding New Constants:**
|
||||||
|
1. Add to appropriate section in [constants.ts](src/config/constants.ts)
|
||||||
|
2. Use semantic names (e.g., `SHOOTING_RANGE` not `MAX_DIST`)
|
||||||
|
3. Include units in comments (meters, m/s, radians, pixels)
|
||||||
|
4. Export for use across codebase
|
||||||
|
|
||||||
|
**Physics Bodies:**
|
||||||
|
- Players: Circular bodies (radius varies by position)
|
||||||
|
- Puck: Circular body with drag and bounce
|
||||||
|
- Goals: Static rectangular bodies for posts/bars
|
||||||
|
- Sensors: Physics zones with `overlap` not `collide`
|
||||||
|
|
||||||
|
**Coordinate Conversions:**
|
||||||
|
- Always use `CoordinateUtils.gameToScreen()` and `screenToGame()`
|
||||||
|
- Never mix coordinate systems in calculations
|
||||||
|
- Store positions in game coordinates (meters), convert for rendering
|
||||||
|
|||||||
@ -348,7 +348,8 @@ export class GameScene extends Phaser.Scene {
|
|||||||
this.events.off('goal');
|
this.events.off('goal');
|
||||||
this.scene.restart();
|
this.scene.restart();
|
||||||
}
|
}
|
||||||
return; // Don't update anything while waiting for reset
|
// Continue updating with isGoalScored flag set
|
||||||
|
// This allows behavior trees to handle the freeze logic
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updatePuck();
|
this.updatePuck();
|
||||||
@ -362,10 +363,11 @@ export class GameScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updatePlayers(delta: number) {
|
private updatePlayers(delta: number) {
|
||||||
// Build game state
|
// Build game state with goal freeze status
|
||||||
const gameState = {
|
const gameState = {
|
||||||
puck: this.puck,
|
puck: this.puck,
|
||||||
allPlayers: this.players
|
allPlayers: this.players,
|
||||||
|
isGoalScored: this.isWaitingForReset
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update all players with behavior tree decisions
|
// Update all players with behavior tree decisions
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { GOAL_LINE_OFFSET, GOALIE_RANGE } from '../../config/constants';
|
|||||||
* Goalie-specific behavior tree
|
* Goalie-specific behavior tree
|
||||||
*
|
*
|
||||||
* Goalies have unique behaviors:
|
* Goalies have unique behaviors:
|
||||||
|
* - Return to center of goal when goal scored (highest priority)
|
||||||
* - Stay near goal line
|
* - Stay near goal line
|
||||||
* - Track puck Y position
|
* - Track puck Y position
|
||||||
* - Challenge shooters (future)
|
* - Challenge shooters (future)
|
||||||
@ -14,6 +15,16 @@ import { GOAL_LINE_OFFSET, GOALIE_RANGE } from '../../config/constants';
|
|||||||
*/
|
*/
|
||||||
export class GoalieBehavior extends BehaviorNode {
|
export class GoalieBehavior extends BehaviorNode {
|
||||||
tick(player: Player, gameState: GameState): PlayerAction {
|
tick(player: Player, gameState: GameState): PlayerAction {
|
||||||
|
// Priority check: If goal was scored, return to center of goal
|
||||||
|
if (gameState.isGoalScored) {
|
||||||
|
const goalX = player.team === 'home' ? -GOAL_LINE_OFFSET : GOAL_LINE_OFFSET;
|
||||||
|
return {
|
||||||
|
type: 'move',
|
||||||
|
targetX: goalX,
|
||||||
|
targetY: 0 // Center of goal
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Stay near goal line
|
// Stay near goal line
|
||||||
const goalX = player.team === 'home' ? -GOAL_LINE_OFFSET : GOAL_LINE_OFFSET;
|
const goalX = player.team === 'home' ? -GOAL_LINE_OFFSET : GOAL_LINE_OFFSET;
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import { TransitionBehavior } from './TransitionBehavior';
|
|||||||
* Skater behavior tree - Context-based decision making
|
* Skater behavior tree - Context-based decision making
|
||||||
*
|
*
|
||||||
* The selector evaluates children in priority order:
|
* The selector evaluates children in priority order:
|
||||||
* 1. PuckCarrier - If this player has the puck (highest priority)
|
* 0. Goal Scored - Return to center faceoff circle (highest priority)
|
||||||
|
* 1. PuckCarrier - If this player has the puck
|
||||||
* 2. OffensiveSupport - If teammate has puck (support offense)
|
* 2. OffensiveSupport - If teammate has puck (support offense)
|
||||||
* 3. Defensive - If opponent has puck (play defense)
|
* 3. Defensive - If opponent has puck (play defense)
|
||||||
* 4. Transition - Loose puck or neutral situations (fallback)
|
* 4. Transition - Loose puck or neutral situations (fallback)
|
||||||
@ -34,6 +35,15 @@ export class SkaterBehavior extends BehaviorNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tick(player: Player, gameState: GameState): PlayerAction {
|
tick(player: Player, gameState: GameState): PlayerAction {
|
||||||
|
// Priority check: If goal was scored, skate to center faceoff circle
|
||||||
|
if (gameState.isGoalScored) {
|
||||||
|
return {
|
||||||
|
type: 'move',
|
||||||
|
targetX: 0, // Center ice
|
||||||
|
targetY: 0 // Center ice
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return this.tree.tick(player, gameState) as PlayerAction;
|
return this.tree.tick(player, gameState) as PlayerAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@ export interface PlayerAttributes {
|
|||||||
export interface GameState {
|
export interface GameState {
|
||||||
puck: Puck;
|
puck: Puck;
|
||||||
allPlayers: Player[];
|
allPlayers: Player[];
|
||||||
|
isGoalScored: boolean; // True when goal scored and game frozen
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user