From 8674e65432777737353893941d7cad3ddff67d8a Mon Sep 17 00:00:00 2001 From: Pierre Wessman <4029607+pierrewessman@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:55:21 +0200 Subject: [PATCH] Fix away team left/right player positioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/engine/game-engine.js | 8 +++--- src/entities/player.js | 53 +++++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/engine/game-engine.js b/src/engine/game-engine.js index 77e42ad..e3f7d2e 100644 --- a/src/engine/game-engine.js +++ b/src/engine/game-engine.js @@ -39,11 +39,11 @@ class GameEngine { const awayTeamPositions = [ { role: 'G', x: 1000 - goalXOffset, y: 300 }, - { role: 'LD', x: 800, y: 220 }, - { role: 'RD', x: 800, y: 380 }, - { role: 'LW', x: 650, y: 200 }, + { role: 'LD', x: 800, y: 380 }, + { role: 'RD', x: 800, y: 220 }, + { role: 'LW', x: 650, y: 400 }, { role: 'C', x: 600, y: 300 }, - { role: 'RW', x: 650, y: 400 } + { role: 'RW', x: 650, y: 200 } ]; homeTeamPositions.forEach((pos, index) => { diff --git a/src/entities/player.js b/src/entities/player.js index 2a43053..0cce319 100644 --- a/src/entities/player.js +++ b/src/entities/player.js @@ -450,6 +450,11 @@ class Player { // Base position is an aggressive offensive formation const side = this.team === 'home' ? 1 : -1; 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; @@ -462,22 +467,22 @@ class Player { case 'LW': // Left wing pushes forward on their side for passing options baseX = attackZone + 40; // Push forward past attack zone - baseY = rink.centerY - 140; + baseY = rink.centerY + leftSideY; break; case 'RW': // Right wing pushes forward on their side for passing options baseX = attackZone + 40; // Push forward past attack zone - baseY = rink.centerY + 140; + baseY = rink.centerY + rightSideY; break; case 'LD': // Left defense supports from the point baseX = attackZone - 120; - baseY = rink.centerY - 100; + baseY = rink.centerY + leftDefenseY; break; case 'RD': // Right defense supports from the point baseX = attackZone - 120; - baseY = rink.centerY + 100; + baseY = rink.centerY + rightDefenseY; break; default: 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 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; if (isAttacking) { @@ -558,19 +573,19 @@ class Player { break; case 'LW': baseX = attackZone - 50; - baseY = centerY - 120; + baseY = centerY + leftSideY; break; case 'RW': baseX = attackZone - 50; - baseY = centerY + 120; + baseY = centerY + rightSideY; break; case 'LD': baseX = attackZone - 150; - baseY = centerY - 80; + baseY = centerY + leftDefenseY; break; case 'RD': baseX = attackZone - 150; - baseY = centerY + 80; + baseY = centerY + rightDefenseY; break; default: return this.homePosition; @@ -586,19 +601,19 @@ class Player { break; case 'LW': baseX = defenseZone + side * 50; - baseY = centerY - 100; + baseY = centerY + leftDefensiveY; break; case 'RW': baseX = defenseZone + side * 50; - baseY = centerY + 100; + baseY = centerY + rightDefensiveY; break; case 'LD': baseX = defenseZone + side * 100; - baseY = centerY - 60; + baseY = centerY + leftDefensiveDefenseY; break; case 'RD': baseX = defenseZone + side * 100; - baseY = centerY + 60; + baseY = centerY + rightDefensiveDefenseY; break; default: return this.homePosition; @@ -969,6 +984,12 @@ class Player { const side = this.team === 'home' ? -1 : 1; 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) { case 'C': // 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 return new Vector2( 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': @@ -990,21 +1011,21 @@ class Player { // Position them further back and outside the circle return new Vector2( 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': // Left defense well outside the faceoff area return new Vector2( faceoffLocation.x + side * (faceoffRadius + 80), - faceoffLocation.y - (faceoffRadius + 40) + faceoffLocation.y + leftDefenseY ); case 'RD': // Right defense well outside the faceoff area return new Vector2( faceoffLocation.x + side * (faceoffRadius + 80), - faceoffLocation.y + (faceoffRadius + 40) + faceoffLocation.y + rightDefenseY ); case 'G':