Fix away team left/right player positioning
Away team Left Defender and Left Winger were incorrectly positioned on the right side due to formation logic not accounting for team orientation. Away team faces opposite direction, so their left/right perspective is flipped. - Fix initial positioning in game-engine.js setupPlayers() - Update formation logic in player.js for all positioning methods: - getOffensiveSupportPosition() - getContextualPosition() - getFaceoffPosition() - Away team left positions now use positive Y (bottom), right positions use negative Y (top) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4bf182c2a9
commit
8674e65432
@ -39,11 +39,11 @@ class GameEngine {
|
|||||||
|
|
||||||
const awayTeamPositions = [
|
const awayTeamPositions = [
|
||||||
{ role: 'G', x: 1000 - goalXOffset, y: 300 },
|
{ role: 'G', x: 1000 - goalXOffset, y: 300 },
|
||||||
{ role: 'LD', x: 800, y: 220 },
|
{ role: 'LD', x: 800, y: 380 },
|
||||||
{ role: 'RD', x: 800, y: 380 },
|
{ role: 'RD', x: 800, y: 220 },
|
||||||
{ role: 'LW', x: 650, y: 200 },
|
{ role: 'LW', x: 650, y: 400 },
|
||||||
{ role: 'C', x: 600, y: 300 },
|
{ role: 'C', x: 600, y: 300 },
|
||||||
{ role: 'RW', x: 650, y: 400 }
|
{ role: 'RW', x: 650, y: 200 }
|
||||||
];
|
];
|
||||||
|
|
||||||
homeTeamPositions.forEach((pos, index) => {
|
homeTeamPositions.forEach((pos, index) => {
|
||||||
|
|||||||
@ -450,6 +450,11 @@ class Player {
|
|||||||
// Base position is an aggressive offensive formation
|
// Base position is an aggressive offensive formation
|
||||||
const side = this.team === 'home' ? 1 : -1;
|
const side = this.team === 'home' ? 1 : -1;
|
||||||
const attackZone = this.team === 'home' ? rink.width * 0.75 : rink.width * 0.25;
|
const attackZone = this.team === 'home' ? rink.width * 0.75 : rink.width * 0.25;
|
||||||
|
// Away team players need their left/right flipped since they face the opposite direction
|
||||||
|
const leftSideY = this.team === 'home' ? -140 : 140;
|
||||||
|
const rightSideY = this.team === 'home' ? 140 : -140;
|
||||||
|
const leftDefenseY = this.team === 'home' ? -100 : 100;
|
||||||
|
const rightDefenseY = this.team === 'home' ? 100 : -100;
|
||||||
|
|
||||||
let baseX, baseY;
|
let baseX, baseY;
|
||||||
|
|
||||||
@ -462,22 +467,22 @@ class Player {
|
|||||||
case 'LW':
|
case 'LW':
|
||||||
// Left wing pushes forward on their side for passing options
|
// Left wing pushes forward on their side for passing options
|
||||||
baseX = attackZone + 40; // Push forward past attack zone
|
baseX = attackZone + 40; // Push forward past attack zone
|
||||||
baseY = rink.centerY - 140;
|
baseY = rink.centerY + leftSideY;
|
||||||
break;
|
break;
|
||||||
case 'RW':
|
case 'RW':
|
||||||
// Right wing pushes forward on their side for passing options
|
// Right wing pushes forward on their side for passing options
|
||||||
baseX = attackZone + 40; // Push forward past attack zone
|
baseX = attackZone + 40; // Push forward past attack zone
|
||||||
baseY = rink.centerY + 140;
|
baseY = rink.centerY + rightSideY;
|
||||||
break;
|
break;
|
||||||
case 'LD':
|
case 'LD':
|
||||||
// Left defense supports from the point
|
// Left defense supports from the point
|
||||||
baseX = attackZone - 120;
|
baseX = attackZone - 120;
|
||||||
baseY = rink.centerY - 100;
|
baseY = rink.centerY + leftDefenseY;
|
||||||
break;
|
break;
|
||||||
case 'RD':
|
case 'RD':
|
||||||
// Right defense supports from the point
|
// Right defense supports from the point
|
||||||
baseX = attackZone - 120;
|
baseX = attackZone - 120;
|
||||||
baseY = rink.centerY + 100;
|
baseY = rink.centerY + rightDefenseY;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return this.getFormationPosition(gameState, puck, [puckCarrier, ...opponents, this]);
|
return this.getFormationPosition(gameState, puck, [puckCarrier, ...opponents, this]);
|
||||||
@ -545,6 +550,16 @@ class Player {
|
|||||||
const puckInfluenceX = (puck.position.x - rink.centerX) * 0.3; // Follow puck horizontally
|
const puckInfluenceX = (puck.position.x - rink.centerX) * 0.3; // Follow puck horizontally
|
||||||
const puckInfluenceY = (puck.position.y - centerY) * 0.2; // Follow puck vertically (less influence)
|
const puckInfluenceY = (puck.position.y - centerY) * 0.2; // Follow puck vertically (less influence)
|
||||||
|
|
||||||
|
// Away team players need their left/right flipped since they face the opposite direction
|
||||||
|
const leftSideY = this.team === 'home' ? -120 : 120;
|
||||||
|
const rightSideY = this.team === 'home' ? 120 : -120;
|
||||||
|
const leftDefenseY = this.team === 'home' ? -80 : 80;
|
||||||
|
const rightDefenseY = this.team === 'home' ? 80 : -80;
|
||||||
|
const leftDefensiveY = this.team === 'home' ? -100 : 100;
|
||||||
|
const rightDefensiveY = this.team === 'home' ? 100 : -100;
|
||||||
|
const leftDefensiveDefenseY = this.team === 'home' ? -60 : 60;
|
||||||
|
const rightDefensiveDefenseY = this.team === 'home' ? 60 : -60;
|
||||||
|
|
||||||
let baseX, baseY;
|
let baseX, baseY;
|
||||||
|
|
||||||
if (isAttacking) {
|
if (isAttacking) {
|
||||||
@ -558,19 +573,19 @@ class Player {
|
|||||||
break;
|
break;
|
||||||
case 'LW':
|
case 'LW':
|
||||||
baseX = attackZone - 50;
|
baseX = attackZone - 50;
|
||||||
baseY = centerY - 120;
|
baseY = centerY + leftSideY;
|
||||||
break;
|
break;
|
||||||
case 'RW':
|
case 'RW':
|
||||||
baseX = attackZone - 50;
|
baseX = attackZone - 50;
|
||||||
baseY = centerY + 120;
|
baseY = centerY + rightSideY;
|
||||||
break;
|
break;
|
||||||
case 'LD':
|
case 'LD':
|
||||||
baseX = attackZone - 150;
|
baseX = attackZone - 150;
|
||||||
baseY = centerY - 80;
|
baseY = centerY + leftDefenseY;
|
||||||
break;
|
break;
|
||||||
case 'RD':
|
case 'RD':
|
||||||
baseX = attackZone - 150;
|
baseX = attackZone - 150;
|
||||||
baseY = centerY + 80;
|
baseY = centerY + rightDefenseY;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return this.homePosition;
|
return this.homePosition;
|
||||||
@ -586,19 +601,19 @@ class Player {
|
|||||||
break;
|
break;
|
||||||
case 'LW':
|
case 'LW':
|
||||||
baseX = defenseZone + side * 50;
|
baseX = defenseZone + side * 50;
|
||||||
baseY = centerY - 100;
|
baseY = centerY + leftDefensiveY;
|
||||||
break;
|
break;
|
||||||
case 'RW':
|
case 'RW':
|
||||||
baseX = defenseZone + side * 50;
|
baseX = defenseZone + side * 50;
|
||||||
baseY = centerY + 100;
|
baseY = centerY + rightDefensiveY;
|
||||||
break;
|
break;
|
||||||
case 'LD':
|
case 'LD':
|
||||||
baseX = defenseZone + side * 100;
|
baseX = defenseZone + side * 100;
|
||||||
baseY = centerY - 60;
|
baseY = centerY + leftDefensiveDefenseY;
|
||||||
break;
|
break;
|
||||||
case 'RD':
|
case 'RD':
|
||||||
baseX = defenseZone + side * 100;
|
baseX = defenseZone + side * 100;
|
||||||
baseY = centerY + 60;
|
baseY = centerY + rightDefensiveDefenseY;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return this.homePosition;
|
return this.homePosition;
|
||||||
@ -969,6 +984,12 @@ class Player {
|
|||||||
const side = this.team === 'home' ? -1 : 1;
|
const side = this.team === 'home' ? -1 : 1;
|
||||||
const faceoffRadius = RINK_CIRCLES.FACEOFF_CIRCLE_RADIUS; // Radius of faceoff circle
|
const faceoffRadius = RINK_CIRCLES.FACEOFF_CIRCLE_RADIUS; // Radius of faceoff circle
|
||||||
|
|
||||||
|
// Away team players need their left/right flipped since they face the opposite direction
|
||||||
|
const leftWingY = this.team === 'home' ? -(faceoffRadius + 20) : (faceoffRadius + 20);
|
||||||
|
const rightWingY = this.team === 'home' ? (faceoffRadius + 20) : -(faceoffRadius + 20);
|
||||||
|
const leftDefenseY = this.team === 'home' ? -(faceoffRadius + 40) : (faceoffRadius + 40);
|
||||||
|
const rightDefenseY = this.team === 'home' ? (faceoffRadius + 40) : -(faceoffRadius + 40);
|
||||||
|
|
||||||
switch (this.role) {
|
switch (this.role) {
|
||||||
case 'C':
|
case 'C':
|
||||||
// Centers line up directly at the faceoff dot, facing each other
|
// Centers line up directly at the faceoff dot, facing each other
|
||||||
@ -982,7 +1003,7 @@ class Player {
|
|||||||
// Position them further back and outside the circle
|
// Position them further back and outside the circle
|
||||||
return new Vector2(
|
return new Vector2(
|
||||||
faceoffLocation.x + side * (faceoffRadius + 30), // Outside circle + buffer
|
faceoffLocation.x + side * (faceoffRadius + 30), // Outside circle + buffer
|
||||||
faceoffLocation.y - (faceoffRadius + 20) // Outside circle on left side
|
faceoffLocation.y + leftWingY // Outside circle on left side
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'RW':
|
case 'RW':
|
||||||
@ -990,21 +1011,21 @@ class Player {
|
|||||||
// Position them further back and outside the circle
|
// Position them further back and outside the circle
|
||||||
return new Vector2(
|
return new Vector2(
|
||||||
faceoffLocation.x + side * (faceoffRadius + 30), // Outside circle + buffer
|
faceoffLocation.x + side * (faceoffRadius + 30), // Outside circle + buffer
|
||||||
faceoffLocation.y + (faceoffRadius + 20) // Outside circle on right side
|
faceoffLocation.y + rightWingY // Outside circle on right side
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'LD':
|
case 'LD':
|
||||||
// Left defense well outside the faceoff area
|
// Left defense well outside the faceoff area
|
||||||
return new Vector2(
|
return new Vector2(
|
||||||
faceoffLocation.x + side * (faceoffRadius + 80),
|
faceoffLocation.x + side * (faceoffRadius + 80),
|
||||||
faceoffLocation.y - (faceoffRadius + 40)
|
faceoffLocation.y + leftDefenseY
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'RD':
|
case 'RD':
|
||||||
// Right defense well outside the faceoff area
|
// Right defense well outside the faceoff area
|
||||||
return new Vector2(
|
return new Vector2(
|
||||||
faceoffLocation.x + side * (faceoffRadius + 80),
|
faceoffLocation.x + side * (faceoffRadius + 80),
|
||||||
faceoffLocation.y + (faceoffRadius + 40)
|
faceoffLocation.y + rightDefenseY
|
||||||
);
|
);
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user