class DebugSystem { constructor(gameEngine) { this.gameEngine = gameEngine; this.isVisible = false; this.selectedPlayer = null; this.updateInterval = null; this.setupEventListeners(); this.setupGlobalDebugFunctions(); } setupEventListeners() { // Debug toggle button document.getElementById('debug-toggle').addEventListener('click', () => { this.toggleDebugPanel(); }); // Close debug panel document.getElementById('debug-close').addEventListener('click', () => { this.hideDebugPanel(); }); // Canvas click for player selection this.gameEngine.canvas.addEventListener('click', (e) => { if (this.isVisible) { this.handleCanvasClick(e); } }); // Monitor debug mode changes (triggered by existing D key handler) let lastDebugMode = window.debugMode; setInterval(() => { if (window.debugMode !== lastDebugMode) { if (window.debugMode && !this.isVisible) { this.showDebugPanel(); } else if (!window.debugMode && this.isVisible) { this.hideDebugPanel(); } lastDebugMode = window.debugMode; } }, 100); } toggleDebugPanel() { if (this.isVisible) { this.hideDebugPanel(); } else { this.showDebugPanel(); } } showDebugPanel() { this.isVisible = true; document.getElementById('debug-panel').classList.remove('hidden'); // Start real-time updates this.updateInterval = setInterval(() => { this.updateDebugInfo(); }, 100); // Update 10 times per second // Initial update this.updateDebugInfo(); } hideDebugPanel() { this.isVisible = false; document.getElementById('debug-panel').classList.add('hidden'); // Stop real-time updates if (this.updateInterval) { clearInterval(this.updateInterval); this.updateInterval = null; } } handleCanvasClick(e) { const rect = this.gameEngine.canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // Find closest player to click position let closestPlayer = null; let closestDistance = Infinity; this.gameEngine.players.forEach(player => { const distance = Math.sqrt( Math.pow(player.position.x - x, 2) + Math.pow(player.position.y - y, 2) ); if (distance < player.radius + 10 && distance < closestDistance) { closestPlayer = player; closestDistance = distance; } }); if (closestPlayer) { this.selectPlayer(closestPlayer); } } selectPlayer(player) { // Remove previous selection styling document.querySelectorAll('.debug-player').forEach(el => { el.classList.remove('selected'); }); this.selectedPlayer = player; // Add selection styling to the clicked player const playerElement = document.querySelector(`[data-player-id="${player.id}"]`); if (playerElement) { playerElement.classList.add('selected'); } this.updateSelectedPlayerInfo(); } updateDebugInfo() { if (!this.isVisible) return; this.updateGameStateInfo(); this.updatePuckInfo(); this.updatePlayersInfo(); if (this.selectedPlayer) { this.updateSelectedPlayerInfo(); } } updateGameStateInfo() { const gameState = this.gameEngine.gameState; const info = `
Period: ${gameState.getPeriodName()}
Time: ${gameState.formatTime(gameState.timeRemaining)}
Score: ${gameState.homeScore} - ${gameState.awayScore}
Paused: ${gameState.isPaused}
Speed: ${gameState.gameSpeed}x
Faceoff Active: ${gameState.faceoff.isActive}
`; document.getElementById('debug-game-state').innerHTML = info; } updatePuckInfo() { const puck = this.gameEngine.puck; const info = `
Position: (${puck.position.x.toFixed(1)}, ${puck.position.y.toFixed(1)})
Velocity: (${puck.velocity.x.toFixed(1)}, ${puck.velocity.y.toFixed(1)})
Speed: ${puck.getSpeed().toFixed(1)}
Active: ${this.gameEngine.puckActive}
Owner: ${puck.lastTouchedBy || 'None'}
`; document.getElementById('debug-puck').innerHTML = info; } updatePlayersInfo() { const homePlayers = this.gameEngine.players.filter(p => p.team === 'home'); const awayPlayers = this.gameEngine.players.filter(p => p.team === 'away'); this.renderPlayersList('debug-home-players', homePlayers); this.renderPlayersList('debug-away-players', awayPlayers); } renderPlayersList(containerId, players) { const container = document.getElementById(containerId); // Only create elements if they don't exist yet (prevent flickering) if (container.children.length === 0) { this.createPlayerElements(container, players); } // Update existing elements instead of recreating them players.forEach((player, index) => { const playerDiv = container.children[index]; if (!playerDiv) return; // Update selection state if (this.selectedPlayer && this.selectedPlayer.id === player.id) { playerDiv.classList.add('selected'); } else { playerDiv.classList.remove('selected'); } // Update dynamic content only const coordsElement = playerDiv.querySelector('.debug-coords'); const speedElement = playerDiv.querySelector('.debug-speed'); const energyElement = playerDiv.querySelector('.debug-energy'); const puckElement = playerDiv.querySelector('.debug-puck'); const behaviorElement = playerDiv.querySelector('.debug-behavior'); if (coordsElement) coordsElement.textContent = `Pos: (${player.position.x.toFixed(0)}, ${player.position.y.toFixed(0)})`; if (speedElement) speedElement.textContent = player.velocity.magnitude().toFixed(1); if (energyElement) energyElement.textContent = `${player.state.energy.toFixed(0)}%`; if (puckElement) puckElement.textContent = player.state.hasPuck; if (behaviorElement) behaviorElement.textContent = player.aiState.behavior; }); } createPlayerElements(container, players) { players.forEach(player => { const playerDiv = document.createElement('div'); playerDiv.className = 'debug-player'; playerDiv.setAttribute('data-player-id', player.id); playerDiv.innerHTML = `
${player.role} - ${player.name}
Pos: (${player.position.x.toFixed(0)}, ${player.position.y.toFixed(0)})
Speed: ${player.velocity.magnitude().toFixed(1)}
Energy: ${player.state.energy.toFixed(0)}%
Has Puck: ${player.state.hasPuck}
Behavior: ${player.aiState.behavior}
`; // Make the entire div clickable with better event handling playerDiv.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); this.selectPlayer(player); }); // Add mouse events for better feedback playerDiv.addEventListener('mouseenter', (e) => { if (!playerDiv.classList.contains('selected')) { playerDiv.style.background = 'rgba(255, 255, 255, 0.15)'; } }); playerDiv.addEventListener('mouseleave', (e) => { if (!playerDiv.classList.contains('selected')) { playerDiv.style.background = ''; } }); playerDiv.addEventListener('mousedown', (e) => { e.preventDefault(); playerDiv.style.transform = 'scale(0.98)'; }); playerDiv.addEventListener('mouseup', (e) => { e.preventDefault(); playerDiv.style.transform = ''; }); container.appendChild(playerDiv); }); } updateSelectedPlayerInfo() { if (!this.selectedPlayer) return; const player = this.selectedPlayer; const info = `

${player.name} (${player.role})

Team: ${player.team.toUpperCase()}
Position & Physics
Position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})
Velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
Speed: ${player.velocity.magnitude().toFixed(1)}
Target: (${player.targetPosition.x.toFixed(1)}, ${player.targetPosition.y.toFixed(1)})
Game State
Has Puck: ${player.state.hasPuck}
Energy: ${player.state.energy.toFixed(1)}%
Checking: ${player.state.checking}
Injured: ${player.state.injured}
AI State
Behavior: ${player.aiState.behavior}
Target: ${player.aiState.target ? player.aiState.target.constructor.name : 'None'}
Last Action: ${player.aiState.lastAction.toFixed(0)}ms ago
Reaction Time: ${player.aiState.reactionTime.toFixed(0)}ms
Attributes
Speed: ${player.attributes.speed.toFixed(0)}
Shooting: ${player.attributes.shooting.toFixed(0)}
Passing: ${player.attributes.passing.toFixed(0)}
Defense: ${player.attributes.defense.toFixed(0)}
Checking: ${player.attributes.checking.toFixed(0)}
Puck Handling: ${player.attributes.puckHandling.toFixed(0)}
Awareness: ${player.attributes.awareness.toFixed(0)}
`; document.getElementById('debug-selected-player').innerHTML = info; } setupGlobalDebugFunctions() { // Add global debug helper functions to window object window.debugHelpers = { // Get all players getPlayers: () => this.gameEngine.players, // Get players by team getHomeTeam: () => this.gameEngine.players.filter(p => p.team === 'home'), getAwayTeam: () => this.gameEngine.players.filter(p => p.team === 'away'), // Get players by position getPlayersByPosition: (position) => this.gameEngine.players.filter(p => p.role === position), getGoalies: () => this.gameEngine.players.filter(p => p.role === 'G'), getDefense: () => this.gameEngine.players.filter(p => p.role === 'LD' || p.role === 'RD'), getForwards: () => this.gameEngine.players.filter(p => ['LW', 'C', 'RW'].includes(p.role)), // Get specific player getPlayer: (id) => this.gameEngine.players.find(p => p.id === id), // Get puck getPuck: () => this.gameEngine.puck, // Get game state getGameState: () => this.gameEngine.gameState, // Get player with puck getPuckCarrier: () => this.gameEngine.players.find(p => p.state.hasPuck), // Export game state for debugging exportGameState: () => { const state = { gameState: this.gameEngine.gameState.getGameState(), players: this.gameEngine.players.map(p => ({ id: p.id, name: p.name, team: p.team, role: p.role, position: { x: p.position.x, y: p.position.y }, velocity: { x: p.velocity.x, y: p.velocity.y }, targetPosition: { x: p.targetPosition.x, y: p.targetPosition.y }, state: { ...p.state }, aiState: { ...p.aiState }, attributes: { ...p.attributes } })), puck: { position: { x: this.gameEngine.puck.position.x, y: this.gameEngine.puck.position.y }, velocity: { x: this.gameEngine.puck.velocity.x, y: this.gameEngine.puck.velocity.y }, speed: this.gameEngine.puck.getSpeed(), lastTouchedBy: this.gameEngine.puck.lastTouchedBy } }; console.log('Game State Export:', state); return state; }, // Show debug panel showDebug: () => this.showDebugPanel(), // Hide debug panel hideDebug: () => this.hideDebugPanel() }; // Log available debug functions console.log('Debug Helper Functions Available:'); console.log('- debugHelpers.getPlayers() - Get all players'); console.log('- debugHelpers.getHomeTeam() - Get home team players'); console.log('- debugHelpers.getAwayTeam() - Get away team players'); console.log('- debugHelpers.getPlayersByPosition(pos) - Get players by position'); console.log('- debugHelpers.getPlayer(id) - Get specific player by ID'); console.log('- debugHelpers.getPuck() - Get puck object'); console.log('- debugHelpers.getGameState() - Get game state'); console.log('- debugHelpers.getPuckCarrier() - Get player with puck'); console.log('- debugHelpers.exportGameState() - Export full game state'); console.log('- debugHelpers.showDebug() - Show debug panel'); console.log('- debugHelpers.hideDebug() - Hide debug panel'); } }