mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-23 16:59:10 +00:00
376 lines
No EOL
15 KiB
HTML
376 lines
No EOL
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Diplomacy Animation Test</title>
|
|
<!-- Import map for Three.js and dependencies -->
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js",
|
|
"three/examples/jsm/controls/OrbitControls.js": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/controls/OrbitControls.js",
|
|
"three/examples/jsm/loaders/GLTFLoader.js": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/loaders/GLTFLoader.js",
|
|
"three/examples/jsm/loaders/TextureLoader.js": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/loaders/TextureLoader.js",
|
|
"three/examples/jsm/loaders/OBJLoader.js": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/loaders/OBJLoader.js"
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
.animation-container {
|
|
width: 100%;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
padding: 20px;
|
|
}
|
|
.loading-overlay {
|
|
text-align: center;
|
|
padding: 40px;
|
|
}
|
|
h1 {
|
|
color: #333;
|
|
text-align: center;
|
|
}
|
|
h2 {
|
|
color: #444;
|
|
border-bottom: 1px solid #ddd;
|
|
padding-bottom: 8px;
|
|
margin-top: 30px;
|
|
}
|
|
button {
|
|
padding: 10px 15px;
|
|
background-color: #4a5568;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
transition: background-color 0.2s;
|
|
margin-right: 8px;
|
|
margin-bottom: 8px;
|
|
}
|
|
button:hover {
|
|
background-color: #2d3748;
|
|
}
|
|
button:disabled {
|
|
background-color: #a0aec0;
|
|
cursor: not-allowed;
|
|
}
|
|
.test-controls {
|
|
margin-top: 20px;
|
|
padding: 15px;
|
|
background-color: #f0f0f0;
|
|
border-radius: 5px;
|
|
}
|
|
.test-section {
|
|
margin-bottom: 20px;
|
|
}
|
|
.test-section h3 {
|
|
margin-top: 0;
|
|
border-bottom: 1px solid #ddd;
|
|
padding-bottom: 5px;
|
|
}
|
|
.scenario-description {
|
|
background-color: #e6f7ff;
|
|
border-left: 4px solid #1890ff;
|
|
padding: 10px 15px;
|
|
margin-bottom: 15px;
|
|
border-radius: 0 4px 4px 0;
|
|
}
|
|
.test-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
gap: 15px;
|
|
margin-top: 15px;
|
|
}
|
|
.test-card {
|
|
background-color: #fff;
|
|
border: 1px solid #ddd;
|
|
border-radius: 5px;
|
|
padding: 15px;
|
|
}
|
|
.test-card h4 {
|
|
margin-top: 0;
|
|
color: #333;
|
|
}
|
|
#debug-info {
|
|
margin-top: 20px;
|
|
padding: 10px;
|
|
background-color: #ffe6e6;
|
|
border: 1px solid #ffcccc;
|
|
border-radius: 4px;
|
|
display: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="animation-container" id="animation-container">
|
|
<div class="loading-overlay" id="loading-overlay">
|
|
<h1>Diplomacy Animation Test</h1>
|
|
<p>This page tests the Three.js animation system for Diplomacy with enhanced order visualization and unit movement.</p>
|
|
<button id="load-game-btn">Load Game File</button>
|
|
<div id="debug-info"></div>
|
|
<div class="test-controls" id="test-controls" style="display: none;">
|
|
<h2>Phase 3 Test Scenarios</h2>
|
|
<p>The following test scenarios demonstrate the capabilities implemented in Phase 3 of the animation system.</p>
|
|
|
|
<div class="test-section">
|
|
<h3>Basic Movement Tests</h3>
|
|
<div class="scenario-description">
|
|
Tests basic unit movement between provinces with full animation.
|
|
</div>
|
|
<button id="test-movement">Test Basic Movement</button>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>Order Visualization Tests</h3>
|
|
<div class="scenario-description">
|
|
Tests various order types and their visual representation, including moves, holds, supports, and convoys.
|
|
</div>
|
|
<div class="test-grid">
|
|
<div class="test-card">
|
|
<h4>Basic Orders</h4>
|
|
<button id="test-basic-orders">Test Basic Orders</button>
|
|
<p>Move, Hold, and Support orders</p>
|
|
</div>
|
|
<div class="test-card">
|
|
<h4>Complex Orders</h4>
|
|
<button id="test-complex-orders">Test Complex Orders</button>
|
|
<p>Support moves, Convoys, and multi-unit moves</p>
|
|
</div>
|
|
<div class="test-card">
|
|
<h4>Failed Orders</h4>
|
|
<button id="test-failed-orders">Test Failed Orders</button>
|
|
<p>Bounces, cuts, and dislodges</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>Retreat Tests</h3>
|
|
<div class="scenario-description">
|
|
Tests retreat scenarios where units are dislodged and must retreat or be disbanded.
|
|
</div>
|
|
<button id="test-retreat">Test Retreat Phase</button>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>Build Tests</h3>
|
|
<div class="scenario-description">
|
|
Tests build/adjustment phase with unit creation and removal.
|
|
</div>
|
|
<button id="test-build">Test Build Phase</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
console.log('Script starting...');
|
|
const debugInfo = document.getElementById('debug-info');
|
|
debugInfo.style.display = 'block';
|
|
debugInfo.textContent = 'Loading script...';
|
|
|
|
try {
|
|
// Check if modules are available
|
|
debugInfo.textContent += '\nChecking modules...';
|
|
|
|
// Add cache busting for JavaScript files
|
|
const cacheBust = `?v=${Date.now()}`;
|
|
|
|
import(`./index.js${cacheBust}`)
|
|
.then(module => {
|
|
debugInfo.textContent += '\nindex.js loaded successfully.';
|
|
|
|
// Store all exported functions from index.js in the global scope
|
|
window.initializeAnimation = module.initializeAnimation;
|
|
window.loadGameForAnimation = module.loadGameForAnimation;
|
|
|
|
console.log('Available exports from index.js:', Object.keys(module));
|
|
debugInfo.textContent += `\nAvailable exports from index.js: ${Object.keys(module).join(', ')}`;
|
|
|
|
return import(`./utils/GameStateManager.js${cacheBust}`);
|
|
})
|
|
.then(module => {
|
|
debugInfo.textContent += '\nGameStateManager.js loaded successfully.';
|
|
const { GameStateManager } = module;
|
|
|
|
// DOM elements
|
|
const loadingOverlay = document.getElementById('loading-overlay');
|
|
const animationContainer = document.getElementById('animation-container');
|
|
const loadGameBtn = document.getElementById('load-game-btn');
|
|
const testControls = document.getElementById('test-controls');
|
|
|
|
debugInfo.textContent += '\nDOM elements retrieved.';
|
|
|
|
// Initialize animation system
|
|
const gameStateManager = new GameStateManager();
|
|
|
|
// Add event listeners for test buttons
|
|
document.getElementById('load-game-btn').addEventListener('click', () => {
|
|
// Use the existing loadGameFromDisk method instead of trying to fetch a file
|
|
gameStateManager.loadGameFromDisk()
|
|
.then(gameData => {
|
|
console.log('Game data loaded successfully');
|
|
return gameStateManager;
|
|
})
|
|
.then(() => {
|
|
console.log('Game loaded successfully');
|
|
document.getElementById('loading-overlay').style.display = 'none';
|
|
|
|
// Create an animation player container if it doesn't exist
|
|
let animationPlayer = document.getElementById('animation-player');
|
|
if (!animationPlayer) {
|
|
animationPlayer = document.createElement('div');
|
|
animationPlayer.id = 'animation-player';
|
|
document.getElementById('animation-container').appendChild(animationPlayer);
|
|
}
|
|
|
|
animationPlayer.style.display = 'block';
|
|
|
|
// Initialize the animation player
|
|
initializeAnimationPlayer(gameStateManager);
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading game:', error);
|
|
document.getElementById('debug-info').style.display = 'block';
|
|
document.getElementById('debug-info').innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
});
|
|
});
|
|
|
|
// Manually trigger a click to ensure it's working
|
|
debugInfo.textContent += '\nEvent listener set up! Try clicking the button.';
|
|
|
|
// Define the initializeAnimationPlayer function
|
|
function initializeAnimationPlayer(gameStateManager) {
|
|
console.log('Initializing animation player with game state manager');
|
|
|
|
// Create a map container if it doesn't exist
|
|
let mapContainer = document.getElementById('map-container');
|
|
if (!mapContainer) {
|
|
mapContainer = document.createElement('div');
|
|
mapContainer.id = 'map-container';
|
|
mapContainer.style.width = '100%';
|
|
mapContainer.style.height = '600px';
|
|
mapContainer.style.position = 'relative';
|
|
mapContainer.style.backgroundColor = '#87CEEB';
|
|
mapContainer.style.marginTop = '20px';
|
|
document.getElementById('animation-player').appendChild(mapContainer);
|
|
}
|
|
|
|
// Create animation controls if they don't exist
|
|
let animationControls = document.getElementById('animation-controls');
|
|
if (!animationControls) {
|
|
animationControls = document.createElement('div');
|
|
animationControls.id = 'animation-controls';
|
|
animationControls.style.marginTop = '20px';
|
|
|
|
// Add play controls
|
|
animationControls.innerHTML = `
|
|
<div class="control-group">
|
|
<button id="prev-phase">◀ Prev</button>
|
|
<button id="play-button">▶ Play</button>
|
|
<button id="next-phase">Next ▶</button>
|
|
<label>Speed: <select id="speed-control">
|
|
<option value="0.5">0.5x</option>
|
|
<option value="1" selected>1x</option>
|
|
<option value="2">2x</option>
|
|
<option value="4">4x</option>
|
|
</select></label>
|
|
<span id="phase-display">Phase: 1 of ${gameStateManager.getPhaseCount()}</span>
|
|
</div>
|
|
<div class="control-group">
|
|
<label><input type="checkbox" id="show-order-viz" checked> Show Order Visualizations</label>
|
|
<label><input type="checkbox" id="animate-units" checked> Animate Unit Movements</label>
|
|
<label><input type="checkbox" id="use-easing" checked> Use Animation Easing</label>
|
|
<label><input type="checkbox" id="auto-advance" checked> Auto-Advance to Next Phase</label>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById('animation-player').prepend(animationControls);
|
|
}
|
|
|
|
// Now use the initializeAnimation function from the index.js module
|
|
if (typeof window.initializeAnimation === 'function') {
|
|
const animationPlayer = window.initializeAnimation({
|
|
containerId: 'map-container',
|
|
gameStateManager: gameStateManager,
|
|
mapVariant: 'standard',
|
|
detailLevel: 'medium'
|
|
});
|
|
|
|
// Set up control event listeners
|
|
document.getElementById('prev-phase')?.addEventListener('click', () => {
|
|
animationPlayer.previousPhase();
|
|
});
|
|
|
|
document.getElementById('play-button')?.addEventListener('click', () => {
|
|
if (animationPlayer.isPlaying) {
|
|
animationPlayer.pause();
|
|
document.getElementById('play-button').textContent = '▶ Play';
|
|
} else {
|
|
animationPlayer.play();
|
|
document.getElementById('play-button').textContent = '⏸ Pause';
|
|
}
|
|
});
|
|
|
|
document.getElementById('next-phase')?.addEventListener('click', () => {
|
|
animationPlayer.nextPhase();
|
|
});
|
|
|
|
document.getElementById('speed-control')?.addEventListener('change', (e) => {
|
|
animationPlayer.setPlaybackSpeed(parseFloat(e.target.value));
|
|
});
|
|
|
|
document.getElementById('show-order-viz')?.addEventListener('change', (e) => {
|
|
animationPlayer.showOrderVisualizations = e.target.checked;
|
|
});
|
|
|
|
document.getElementById('animate-units')?.addEventListener('change', (e) => {
|
|
animationPlayer.animateUnitMovements = e.target.checked;
|
|
});
|
|
|
|
document.getElementById('use-easing')?.addEventListener('change', (e) => {
|
|
animationPlayer.setEasing(e.target.checked);
|
|
});
|
|
|
|
document.getElementById('auto-advance')?.addEventListener('change', (e) => {
|
|
animationPlayer.autoAdvance = e.target.checked;
|
|
});
|
|
|
|
console.log('Animation player initialized successfully');
|
|
} else {
|
|
console.error('initializeAnimation function not found. Available exports:',
|
|
Object.keys(window).filter(k => k.includes('initialize')).join(', '));
|
|
document.getElementById('debug-info').style.display = 'block';
|
|
document.getElementById('debug-info').innerHTML =
|
|
'<strong>Error:</strong> initializeAnimation function not available. Ensure index.js is loaded correctly.';
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading modules:', error);
|
|
debugInfo.textContent += `\nModule import error: ${error.message}`;
|
|
if (error.stack) {
|
|
debugInfo.textContent += `\nStack: ${error.stack}`;
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Error in script:', error);
|
|
debugInfo.textContent += `\nScript error: ${error.message}`;
|
|
if (error.stack) {
|
|
debugInfo.textContent += `\nStack: ${error.stack}`;
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |