457 lines
20 KiB
JavaScript
457 lines
20 KiB
JavaScript
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 = `
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Period:</span>
|
|
<span class="debug-attribute-value">${gameState.getPeriodName()}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Time:</span>
|
|
<span class="debug-attribute-value">${gameState.formatTime(gameState.timeRemaining)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Score:</span>
|
|
<span class="debug-attribute-value">${gameState.homeScore} - ${gameState.awayScore}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Paused:</span>
|
|
<span class="debug-attribute-value">${gameState.isPaused}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Speed:</span>
|
|
<span class="debug-attribute-value">${gameState.gameSpeed}x</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Faceoff Active:</span>
|
|
<span class="debug-attribute-value">${gameState.faceoff.isActive}</span>
|
|
</div>
|
|
`;
|
|
document.getElementById('debug-game-state').innerHTML = info;
|
|
}
|
|
|
|
updatePuckInfo() {
|
|
const puck = this.gameEngine.puck;
|
|
const info = `
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Position:</span>
|
|
<span class="debug-attribute-value debug-coords">(${puck.position.x.toFixed(1)}, ${puck.position.y.toFixed(1)})</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Velocity:</span>
|
|
<span class="debug-attribute-value debug-coords">(${puck.velocity.x.toFixed(1)}, ${puck.velocity.y.toFixed(1)})</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Speed:</span>
|
|
<span class="debug-attribute-value">${puck.getSpeed().toFixed(1)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Active:</span>
|
|
<span class="debug-attribute-value">${this.gameEngine.puckActive}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Owner:</span>
|
|
<span class="debug-attribute-value">${puck.lastTouchedBy || 'None'}</span>
|
|
</div>
|
|
`;
|
|
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 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 (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 = `
|
|
<div class="debug-player-header">${player.role} - ${player.name}</div>
|
|
<div class="debug-player-info">
|
|
<div class="debug-coords">Pos: (${player.position.x.toFixed(0)}, ${player.position.y.toFixed(0)})</div>
|
|
<div>Speed: <span class="debug-value debug-speed">${player.velocity.magnitude().toFixed(1)}</span></div>
|
|
<div>Has Puck: <span class="debug-value debug-puck">${player.state.hasPuck}</span></div>
|
|
<div>Behavior: <span class="debug-value debug-behavior">${player.aiState.behavior}</span></div>
|
|
</div>
|
|
`;
|
|
|
|
// 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 = `
|
|
<div style="border-bottom: 1px solid #333; padding-bottom: 10px; margin-bottom: 15px;">
|
|
<h4 style="margin: 0 0 5px 0; color: #4a90e2;">${player.name} (${player.role})</h4>
|
|
<div style="color: #ccc; font-size: 11px;">Team: ${player.team.toUpperCase()}</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
<h5 style="margin: 0 0 8px 0; color: #ccc;">Position & Physics</h5>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Position:</span>
|
|
<span class="debug-attribute-value debug-coords">(${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Velocity:</span>
|
|
<span class="debug-attribute-value debug-coords">(${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Speed:</span>
|
|
<span class="debug-attribute-value">${player.velocity.magnitude().toFixed(1)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Target:</span>
|
|
<span class="debug-attribute-value debug-coords">(${player.targetPosition.x.toFixed(1)}, ${player.targetPosition.y.toFixed(1)})</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
<h5 style="margin: 0 0 8px 0; color: #ccc;">Game State</h5>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Has Puck:</span>
|
|
<span class="debug-attribute-value">${player.state.hasPuck}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Checking:</span>
|
|
<span class="debug-attribute-value">${player.state.checking}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Injured:</span>
|
|
<span class="debug-attribute-value">${player.state.injured}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
<h5 style="margin: 0 0 8px 0; color: #ccc;">AI State</h5>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Behavior:</span>
|
|
<span class="debug-attribute-value">${player.aiState.behavior}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Target:</span>
|
|
<span class="debug-attribute-value">${player.aiState.target ? player.aiState.target.constructor.name : 'None'}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Last Action:</span>
|
|
<span class="debug-attribute-value">${player.aiState.lastAction.toFixed(0)}ms ago</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Reaction Time:</span>
|
|
<span class="debug-attribute-value">${player.aiState.reactionTime.toFixed(0)}ms</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h5 style="margin: 0 0 8px 0; color: #ccc;">Attributes</h5>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Speed:</span>
|
|
<span class="debug-attribute-value">${player.attributes.speed.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Shooting:</span>
|
|
<span class="debug-attribute-value">${player.attributes.shooting.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Passing:</span>
|
|
<span class="debug-attribute-value">${player.attributes.passing.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Defense:</span>
|
|
<span class="debug-attribute-value">${player.attributes.defense.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Checking:</span>
|
|
<span class="debug-attribute-value">${player.attributes.checking.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Puck Handling:</span>
|
|
<span class="debug-attribute-value">${player.attributes.puckHandling.toFixed(0)}</span>
|
|
</div>
|
|
<div class="debug-attribute">
|
|
<span class="debug-attribute-name">Awareness:</span>
|
|
<span class="debug-attribute-value">${player.attributes.awareness.toFixed(0)}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
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');
|
|
}
|
|
} |