function comments
This commit is contained in:
parent
4236d0098d
commit
c09bc6edd5
@ -1,4 +1,13 @@
|
|||||||
class Player {
|
class Player {
|
||||||
|
/**
|
||||||
|
* Creates a hockey player with physics properties, AI behavior, and game attributes
|
||||||
|
* @param {string} id - Unique identifier for the player
|
||||||
|
* @param {string} name - Player's display name
|
||||||
|
* @param {string} team - Team affiliation ('home' or 'away')
|
||||||
|
* @param {string} position - Hockey position ('LW', 'C', 'RW', 'LD', 'RD', 'G')
|
||||||
|
* @param {number} x - Initial x coordinate
|
||||||
|
* @param {number} y - Initial y coordinate
|
||||||
|
*/
|
||||||
constructor(id, name, team, position, x, y) {
|
constructor(id, name, team, position, x, y) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -43,6 +52,13 @@ class Player {
|
|||||||
this.targetAngle = 0;
|
this.targetAngle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main update loop for the player - handles energy, movement, rotation, and AI behavior
|
||||||
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
|
* @param {Object} gameState - Current game state including rink dimensions and game status
|
||||||
|
* @param {Object} puck - Puck object with position and velocity
|
||||||
|
* @param {Array} players - Array of all players on the ice
|
||||||
|
*/
|
||||||
update(deltaTime, gameState, puck, players) {
|
update(deltaTime, gameState, puck, players) {
|
||||||
this.updateEnergy(deltaTime);
|
this.updateEnergy(deltaTime);
|
||||||
this.updateMovement(deltaTime);
|
this.updateMovement(deltaTime);
|
||||||
@ -55,6 +71,11 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates player energy/stamina based on movement and provides recovery when stationary
|
||||||
|
* Energy affects max speed - tired players move slower
|
||||||
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
|
*/
|
||||||
updateEnergy(deltaTime) {
|
updateEnergy(deltaTime) {
|
||||||
const energyDrain = this.velocity.magnitude() / this.maxSpeed * 10 * deltaTime;
|
const energyDrain = this.velocity.magnitude() / this.maxSpeed * 10 * deltaTime;
|
||||||
this.state.energy = Math.max(0, this.state.energy - energyDrain);
|
this.state.energy = Math.max(0, this.state.energy - energyDrain);
|
||||||
@ -68,6 +89,11 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates player physics including movement toward target, velocity limits, and collision bounds
|
||||||
|
* Applies acceleration toward target position with deceleration when close
|
||||||
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
|
*/
|
||||||
updateMovement(deltaTime) {
|
updateMovement(deltaTime) {
|
||||||
const direction = this.targetPosition.subtract(this.position).normalize();
|
const direction = this.targetPosition.subtract(this.position).normalize();
|
||||||
const distance = this.position.distance(this.targetPosition);
|
const distance = this.position.distance(this.targetPosition);
|
||||||
@ -91,6 +117,10 @@ class Player {
|
|||||||
this.keepInBounds();
|
this.keepInBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates player rotation to face target angle with smooth turning animation
|
||||||
|
* @param {number} deltaTime - Time elapsed since last frame in seconds
|
||||||
|
*/
|
||||||
updateAngle(deltaTime) {
|
updateAngle(deltaTime) {
|
||||||
let angleDiff = this.targetAngle - this.angle;
|
let angleDiff = this.targetAngle - this.angle;
|
||||||
angleDiff = Physics.wrapAngle(angleDiff);
|
angleDiff = Physics.wrapAngle(angleDiff);
|
||||||
@ -102,6 +132,13 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main AI decision making system - handles reaction timing, faceoffs, and behavioral switching
|
||||||
|
* Delegates to specific behavior methods based on puck possession
|
||||||
|
* @param {Object} gameState - Current game state including faceoff status
|
||||||
|
* @param {Object} puck - Puck object with position and velocity
|
||||||
|
* @param {Array} players - Array of all players on the ice
|
||||||
|
*/
|
||||||
updateAI(gameState, puck, players) {
|
updateAI(gameState, puck, players) {
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
if (currentTime - this.aiState.lastAction < this.aiState.reactionTime) {
|
if (currentTime - this.aiState.lastAction < this.aiState.reactionTime) {
|
||||||
@ -128,6 +165,14 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offensive AI behavior when player has possession of the puck
|
||||||
|
* Prioritizes shooting, then passing under pressure, then advancing toward goal
|
||||||
|
* @param {Object} gameState - Current game state with rink dimensions
|
||||||
|
* @param {Object} puck - Puck object to shoot or pass
|
||||||
|
* @param {Array} teammates - Array of teammate player objects
|
||||||
|
* @param {Array} opponents - Array of opposing player objects
|
||||||
|
*/
|
||||||
behaviorWithPuck(gameState, puck, teammates, opponents) {
|
behaviorWithPuck(gameState, puck, teammates, opponents) {
|
||||||
const enemyGoal = this.team === 'home' ?
|
const enemyGoal = this.team === 'home' ?
|
||||||
new Vector2(gameState.rink.width - 50, gameState.rink.centerY) :
|
new Vector2(gameState.rink.width - 50, gameState.rink.centerY) :
|
||||||
@ -158,6 +203,15 @@ class Player {
|
|||||||
this.advanceTowardGoal(enemyGoal, opponents, gameState.rink);
|
this.advanceTowardGoal(enemyGoal, opponents, gameState.rink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defensive AI behavior when player doesn't have puck possession
|
||||||
|
* Chooses between chasing loose puck, defending against opponents, or maintaining formation
|
||||||
|
* @param {Object} gameState - Current game state
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Array} teammates - Array of teammate player objects
|
||||||
|
* @param {Array} opponents - Array of opposing player objects
|
||||||
|
* @param {number} distanceToPuck - Pre-calculated distance to puck
|
||||||
|
*/
|
||||||
behaviorWithoutPuck(gameState, puck, teammates, opponents, distanceToPuck) {
|
behaviorWithoutPuck(gameState, puck, teammates, opponents, distanceToPuck) {
|
||||||
const puckOwner = opponents.find(p => p.state.hasPuck) || teammates.find(p => p.state.hasPuck);
|
const puckOwner = opponents.find(p => p.state.hasPuck) || teammates.find(p => p.state.hasPuck);
|
||||||
const isClosestToPuck = this.isClosestPlayerToPuck(puck, teammates);
|
const isClosestToPuck = this.isClosestPlayerToPuck(puck, teammates);
|
||||||
@ -177,6 +231,13 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goalie-specific AI behavior - stays in crease and tracks puck movement
|
||||||
|
* Positions between puck and goal, with more aggressive positioning when puck is close
|
||||||
|
* @param {Object} gameState - Current game state with rink dimensions
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Array} players - Array of all players (unused but maintained for consistency)
|
||||||
|
*/
|
||||||
updateGoalie(gameState, puck, players) {
|
updateGoalie(gameState, puck, players) {
|
||||||
const goal = this.team === 'home' ?
|
const goal = this.team === 'home' ?
|
||||||
new Vector2(10, gameState.rink.centerY) :
|
new Vector2(10, gameState.rink.centerY) :
|
||||||
@ -202,11 +263,22 @@ class Player {
|
|||||||
this.targetPosition.y = Math.max(crease.y, Math.min(crease.y + crease.height, this.targetPosition.y));
|
this.targetPosition.y = Math.max(crease.y, Math.min(crease.y + crease.height, this.targetPosition.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets player target to chase after a loose puck
|
||||||
|
* @param {Object} puck - Puck object with position to chase
|
||||||
|
*/
|
||||||
chasePuck(puck) {
|
chasePuck(puck) {
|
||||||
this.moveToPosition(puck.position);
|
this.moveToPosition(puck.position);
|
||||||
this.aiState.behavior = 'chasing';
|
this.aiState.behavior = 'chasing';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shoots the puck toward a target with power and accuracy based on player attributes
|
||||||
|
* Applies random spread based on shooting accuracy - better shooters are more precise
|
||||||
|
* @param {Object} puck - Puck object to shoot
|
||||||
|
* @param {Vector2} target - Target position to aim for
|
||||||
|
* @returns {boolean} True if shot was taken
|
||||||
|
*/
|
||||||
shoot(puck, target) {
|
shoot(puck, target) {
|
||||||
const direction = target.subtract(puck.position).normalize();
|
const direction = target.subtract(puck.position).normalize();
|
||||||
const power = this.attributes.shooting / 100 * 800;
|
const power = this.attributes.shooting / 100 * 800;
|
||||||
@ -221,6 +293,13 @@ class Player {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes the puck to a teammate with power scaled by distance
|
||||||
|
* Closer passes are softer, longer passes are harder
|
||||||
|
* @param {Object} puck - Puck object to pass
|
||||||
|
* @param {Object} target - Target player object to pass to
|
||||||
|
* @returns {boolean} True if pass was made
|
||||||
|
*/
|
||||||
pass(puck, target) {
|
pass(puck, target) {
|
||||||
const direction = target.position.subtract(puck.position).normalize();
|
const direction = target.position.subtract(puck.position).normalize();
|
||||||
const distance = puck.position.distance(target.position);
|
const distance = puck.position.distance(target.position);
|
||||||
@ -232,6 +311,12 @@ class Player {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to body check an opponent player
|
||||||
|
* If close enough, applies knockback force; otherwise moves toward target
|
||||||
|
* @param {Object} target - Target player to check
|
||||||
|
* @returns {boolean} True if check was successful (contact made)
|
||||||
|
*/
|
||||||
checkPlayer(target) {
|
checkPlayer(target) {
|
||||||
if (this.position.distance(target.position) < 30) {
|
if (this.position.distance(target.position) < 30) {
|
||||||
target.velocity = target.velocity.add(
|
target.velocity = target.velocity.add(
|
||||||
@ -244,11 +329,21 @@ class Player {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the player's target position and facing angle
|
||||||
|
* @param {Vector2} target - Target position to move toward
|
||||||
|
*/
|
||||||
moveToPosition(target) {
|
moveToPosition(target) {
|
||||||
this.targetPosition = target.copy();
|
this.targetPosition = target.copy();
|
||||||
this.targetAngle = target.subtract(this.position).angle();
|
this.targetAngle = target.subtract(this.position).angle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Positions player defensively between opponent and own goal
|
||||||
|
* Uses interpolation to stay closer to opponent than goal
|
||||||
|
* @param {Object} gameState - Current game state with rink dimensions
|
||||||
|
* @param {Object} opponent - Opponent player to defend against
|
||||||
|
*/
|
||||||
defendPosition(gameState, opponent) {
|
defendPosition(gameState, opponent) {
|
||||||
const ownGoal = this.team === 'home' ?
|
const ownGoal = this.team === 'home' ?
|
||||||
new Vector2(50, gameState.rink.centerY) :
|
new Vector2(50, gameState.rink.centerY) :
|
||||||
@ -259,11 +354,24 @@ class Player {
|
|||||||
this.aiState.behavior = 'defending';
|
this.aiState.behavior = 'defending';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves player to their calculated formation position based on game context
|
||||||
|
* @param {Object} gameState - Current game state
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Array} players - Array of all players for formation calculation
|
||||||
|
*/
|
||||||
moveToFormationPosition(gameState, puck, players) {
|
moveToFormationPosition(gameState, puck, players) {
|
||||||
this.moveToPosition(this.getFormationPosition(gameState, puck, players));
|
this.moveToPosition(this.getFormationPosition(gameState, puck, players));
|
||||||
this.aiState.behavior = 'formation';
|
this.aiState.behavior = 'formation';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates ideal formation position for this player based on team state and puck location
|
||||||
|
* @param {Object} gameState - Current game state with rink dimensions
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Array} players - Array of all players to determine puck ownership
|
||||||
|
* @returns {Vector2} Calculated formation position
|
||||||
|
*/
|
||||||
getFormationPosition(gameState, puck, players) {
|
getFormationPosition(gameState, puck, players) {
|
||||||
const side = this.team === 'home' ? -1 : 1;
|
const side = this.team === 'home' ? -1 : 1;
|
||||||
const rink = gameState.rink;
|
const rink = gameState.rink;
|
||||||
@ -276,6 +384,14 @@ class Player {
|
|||||||
return this.getContextualPosition(rink, side, isAttacking, puck);
|
return this.getContextualPosition(rink, side, isAttacking, puck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this player's team is in attacking or defending mode
|
||||||
|
* Based on puck possession and puck location on the rink
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Object} puckOwner - Player object who has puck possession (null if loose)
|
||||||
|
* @param {Object} rink - Rink object with dimensions
|
||||||
|
* @returns {boolean} True if team is attacking, false if defending
|
||||||
|
*/
|
||||||
determineTeamState(puck, puckOwner, rink) {
|
determineTeamState(puck, puckOwner, rink) {
|
||||||
const homeAttackingZone = rink.width * 0.67; // Right side for home team
|
const homeAttackingZone = rink.width * 0.67; // Right side for home team
|
||||||
const awayAttackingZone = rink.width * 0.33; // Left side for away team
|
const awayAttackingZone = rink.width * 0.33; // Left side for away team
|
||||||
@ -298,6 +414,15 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates specific position for player based on role, team state, and puck influence
|
||||||
|
* Different formations for attacking vs defending, with puck tracking adjustments
|
||||||
|
* @param {Object} rink - Rink object with dimensions and center points
|
||||||
|
* @param {number} side - Team side multiplier (-1 for home, 1 for away)
|
||||||
|
* @param {boolean} isAttacking - Whether team is in attacking formation
|
||||||
|
* @param {Object} puck - Puck object for positional influence
|
||||||
|
* @returns {Vector2} Calculated contextual position
|
||||||
|
*/
|
||||||
getContextualPosition(rink, side, isAttacking, puck) {
|
getContextualPosition(rink, side, isAttacking, puck) {
|
||||||
const centerY = rink.centerY;
|
const centerY = rink.centerY;
|
||||||
const puckInfluenceX = (puck.position.x - rink.centerX) * 0.3; // Follow puck horizontally
|
const puckInfluenceX = (puck.position.x - rink.centerX) * 0.3; // Follow puck horizontally
|
||||||
@ -374,6 +499,11 @@ class Player {
|
|||||||
return new Vector2(baseX, baseY);
|
return new Vector2(baseX, baseY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the closest player from a given array of players
|
||||||
|
* @param {Array} players - Array of player objects to search through
|
||||||
|
* @returns {Object|null} Nearest player object, or null if no players provided
|
||||||
|
*/
|
||||||
findNearestPlayer(players) {
|
findNearestPlayer(players) {
|
||||||
let nearest = null;
|
let nearest = null;
|
||||||
let minDistance = Infinity;
|
let minDistance = Infinity;
|
||||||
@ -389,6 +519,12 @@ class Player {
|
|||||||
return nearest;
|
return nearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates teammates to find the best pass target based on distance, skill, and opponent blocking
|
||||||
|
* @param {Array} teammates - Array of teammate player objects
|
||||||
|
* @param {Array} opponents - Array of opponent players that might block the pass
|
||||||
|
* @returns {Object|null} Best teammate to pass to, or null if no good options
|
||||||
|
*/
|
||||||
findBestPassTarget(teammates, opponents) {
|
findBestPassTarget(teammates, opponents) {
|
||||||
let bestTarget = null;
|
let bestTarget = null;
|
||||||
let bestScore = -1;
|
let bestScore = -1;
|
||||||
@ -420,6 +556,13 @@ class Player {
|
|||||||
return bestTarget;
|
return bestTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this player is the closest non-goalie teammate to the puck
|
||||||
|
* Used to decide who should chase loose pucks
|
||||||
|
* @param {Object} puck - Puck object with position
|
||||||
|
* @param {Array} teammates - Array of teammate player objects
|
||||||
|
* @returns {boolean} True if this player is closest to puck on their team
|
||||||
|
*/
|
||||||
isClosestPlayerToPuck(puck, teammates) {
|
isClosestPlayerToPuck(puck, teammates) {
|
||||||
// Check if this player (excluding goalies) is closest to the puck on their team
|
// Check if this player (excluding goalies) is closest to the puck on their team
|
||||||
if (this.role === 'G' || this.state.hasPuck) return false;
|
if (this.role === 'G' || this.state.hasPuck) return false;
|
||||||
@ -444,6 +587,13 @@ class Player {
|
|||||||
return closestPlayer === this;
|
return closestPlayer === this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates whether player has a clear shooting angle to goal
|
||||||
|
* Checks if opponents are blocking the direct path to goal
|
||||||
|
* @param {Vector2} goalPosition - Target goal position
|
||||||
|
* @param {Array} opponents - Array of opponent players that might block shot
|
||||||
|
* @returns {boolean} True if shooting angle is clear
|
||||||
|
*/
|
||||||
hasGoodShootingAngle(goalPosition, opponents) {
|
hasGoodShootingAngle(goalPosition, opponents) {
|
||||||
// Check if there's a clear line to goal (simplified check)
|
// Check if there's a clear line to goal (simplified check)
|
||||||
const directionToGoal = goalPosition.subtract(this.position).normalize();
|
const directionToGoal = goalPosition.subtract(this.position).normalize();
|
||||||
@ -468,6 +618,13 @@ class Player {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intelligently advances player with puck toward the opponent's goal
|
||||||
|
* Uses pathfinding to avoid opponents and direct approach when close
|
||||||
|
* @param {Vector2} goalPosition - Target goal position to advance toward
|
||||||
|
* @param {Array} opponents - Array of opponent players to avoid
|
||||||
|
* @param {Object} rink - Rink object with boundary dimensions
|
||||||
|
*/
|
||||||
advanceTowardGoal(goalPosition, opponents, rink) {
|
advanceTowardGoal(goalPosition, opponents, rink) {
|
||||||
// Create an intelligent path toward the goal
|
// Create an intelligent path toward the goal
|
||||||
let targetPosition = goalPosition.copy();
|
let targetPosition = goalPosition.copy();
|
||||||
@ -493,6 +650,14 @@ class Player {
|
|||||||
this.moveToPosition(targetPosition);
|
this.moveToPosition(targetPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates path adjustments to avoid opponents while advancing toward goal
|
||||||
|
* Creates lateral movement to navigate around blocking opponents
|
||||||
|
* @param {Vector2} goalPosition - Target goal position
|
||||||
|
* @param {Array} opponents - Array of opponent players to avoid
|
||||||
|
* @param {Object} rink - Rink object for boundary awareness
|
||||||
|
* @returns {Vector2} Position adjustment vector to avoid opponents
|
||||||
|
*/
|
||||||
findBestPathToGoal(goalPosition, opponents, rink) {
|
findBestPathToGoal(goalPosition, opponents, rink) {
|
||||||
const currentPos = this.position;
|
const currentPos = this.position;
|
||||||
const adjustment = new Vector2(0, 0);
|
const adjustment = new Vector2(0, 0);
|
||||||
@ -531,11 +696,19 @@ class Player {
|
|||||||
return adjustment;
|
return adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constrains player position to stay within rink boundaries
|
||||||
|
* Uses hardcoded rink dimensions of 1000x600
|
||||||
|
*/
|
||||||
keepInBounds() {
|
keepInBounds() {
|
||||||
this.position.x = Math.max(this.radius, Math.min(1000 - this.radius, this.position.x));
|
this.position.x = Math.max(this.radius, Math.min(1000 - this.radius, this.position.x));
|
||||||
this.position.y = Math.max(this.radius, Math.min(600 - this.radius, this.position.y));
|
this.position.y = Math.max(this.radius, Math.min(600 - this.radius, this.position.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the player on the canvas with team colors, puck indicator, and role text
|
||||||
|
* @param {CanvasRenderingContext2D} ctx - 2D rendering context for drawing
|
||||||
|
*/
|
||||||
render(ctx) {
|
render(ctx) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.translate(this.position.x, this.position.y);
|
ctx.translate(this.position.x, this.position.y);
|
||||||
@ -565,6 +738,12 @@ class Player {
|
|||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles player positioning during faceoff situations
|
||||||
|
* Centers participate directly, other positions maintain legal distance from faceoff circle
|
||||||
|
* @param {Object} gameState - Current game state with faceoff information
|
||||||
|
* @param {Array} players - Array of all players for positioning context
|
||||||
|
*/
|
||||||
handleFaceoffPositioning(gameState, players) {
|
handleFaceoffPositioning(gameState, players) {
|
||||||
const faceoffPos = this.getFaceoffPosition(gameState, players);
|
const faceoffPos = this.getFaceoffPosition(gameState, players);
|
||||||
this.moveToPosition(faceoffPos);
|
this.moveToPosition(faceoffPos);
|
||||||
@ -579,6 +758,13 @@ class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates legal faceoff positioning for each player role
|
||||||
|
* Centers face off directly, other positions must stay outside faceoff circle per hockey rules
|
||||||
|
* @param {Object} gameState - Current game state with faceoff location and rink info
|
||||||
|
* @param {Array} players - Array of all players (unused but maintained for consistency)
|
||||||
|
* @returns {Vector2} Legal faceoff position for this player's role
|
||||||
|
*/
|
||||||
getFaceoffPosition(gameState, players) {
|
getFaceoffPosition(gameState, players) {
|
||||||
const faceoffLocation = gameState.faceoff.location;
|
const faceoffLocation = gameState.faceoff.location;
|
||||||
const side = this.team === 'home' ? -1 : 1;
|
const side = this.team === 'home' ? -1 : 1;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user