<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Harmonies Game 3D - Dynamic Simulation</title> <style> body { margin: 0; overflow: hidden; } canvas { display: block; } .hud { position: absolute; top: 10px; left: 10px; background: rgba(0, 0, 0, 0.5); color: white; padding: 10px; border-radius: 5px; font-family: Arial, sans-serif; } .sidebar { position: absolute; top: 0; right: 0; width: 200px; height: 100%; background: rgba(0, 0, 0, 0.8); color: white; padding: 10px; overflow-y: auto; font-family: Arial, sans-serif; } .character { margin-bottom: 10px; padding: 5px; border: 1px solid white; border-radius: 5px; } .timer { position: absolute; top: 10px; right: 10px; background: rgba(0, 0, 0, 0.5); color: white; padding: 10px; border-radius: 5px; font-family: Arial, sans-serif; } </style> </head> <body> <div class="hud" id="hud"> <p>Current Type: <span id="currentType">Swan 🦢</span></p> </div> <div class="sidebar" id="sidebar"> <h3>Population Stats</h3> </div> <div class="timer" id="timer"> <p>Simulation Time: <span id="simulationTime">0</span> seconds</p> <p>Epoch: <span id="epoch">1</span></p> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script> <script> // Initialize scene, camera, and renderer const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // Timer variables let simulationTime = 0; let epoch = 1; const timerElement = document.getElementById('simulationTime'); const epochElement = document.getElementById('epoch'); // Game board parameters const boardSize = 50; // Gigantic board const tileSize = 1; const tiles = []; const tileTypes = [ { type: 'water', color: 0x87ceeb }, { type: 'forest', color: 0x228b22 }, { type: 'grass', color: 0x98fb98 } ]; // Sidebar for stats const sidebar = document.getElementById('sidebar'); // Particle system for motion simulation const particleSystem = new THREE.Group(); scene.add(particleSystem); // Generate random character stats function generateCharacter() { const names = ["Swift Feather", "Bold Antler", "Mighty Claw", "Gentle Leaf", "Shadow Pelt"]; return { name: names[Math.floor(Math.random() * names.length)], attack: Math.floor(Math.random() * 10) + 1, hitPoints: Math.floor(Math.random() * 50) + 10, strength: Math.floor(Math.random() * 10) + 1, intelligence: Math.floor(Math.random() * 10) + 1, wisdom: Math.floor(Math.random() * 10) + 1, charisma: Math.floor(Math.random() * 10) + 1, }; } // Create tiles and particles for (let x = 0; x < boardSize; x++) { for (let z = 0; z < boardSize; z++) { const tileType = tileTypes[Math.floor(Math.random() * tileTypes.length)]; const geometry = new THREE.BoxGeometry(tileSize, 0.1, tileSize); const material = new THREE.MeshBasicMaterial({ color: tileType.color }); const tile = new THREE.Mesh(geometry, material); tile.position.set(x - boardSize / 2, 0, z - boardSize / 2); tile.userData = { type: tileType.type, occupied: false }; scene.add(tile); tiles.push(tile); // Add particles for motion simulation const particleGeometry = new THREE.SphereGeometry(0.2, 16, 16); const particleMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const particle = new THREE.Mesh(particleGeometry, particleMaterial); particle.position.set( x - boardSize / 2 + Math.random(), 0.2, z - boardSize / 2 + Math.random() ); particle.userData = { direction: new THREE.Vector3(Math.random(), 0, Math.random()).normalize(), rotation: new THREE.Vector3(0, Math.random() * 2 * Math.PI, 0), accelerate: Math.random() * 0.05 + 0.01, brake: 0.02, reverse: -0.02, stats: generateCharacter(), }; // Add stats to the sidebar const characterDiv = document.createElement('div'); characterDiv.className = 'character'; characterDiv.innerHTML = ` <strong>${particle.userData.stats.name}</strong><br> Attack: ${particle.userData.stats.attack}<br> HP: ${particle.userData.stats.hitPoints}<br> Strength: ${particle.userData.stats.strength}<br> Intelligence: ${particle.userData.stats.intelligence}<br> Wisdom: ${particle.userData.stats.wisdom}<br> Charisma: ${particle.userData.stats.charisma}<br> `; sidebar.appendChild(characterDiv); particleSystem.add(particle); } } // Add light const light = new THREE.AmbientLight(0xffffff, 0.8); scene.add(light); // HUD for displaying the current type const hud = document.getElementById('hud'); const currentTypeDisplay = document.getElementById('currentType'); // Current type with emoji const animalTypes = [ { name: 'Swan', emoji: '🦢' }, { name: 'Deer', emoji: '🦌' }, { name: 'Bear', emoji: '🐻' } ]; let currentTypeIndex = 0; function updateCurrentType() { currentTypeDisplay.textContent = `${animalTypes[currentTypeIndex].name} ${animalTypes[currentTypeIndex].emoji}`; } updateCurrentType(); // Handle key presses to switch types window.addEventListener('keydown', (event) => { if (event.key === 'ArrowRight') { currentTypeIndex = (currentTypeIndex + 1) % animalTypes.length; updateCurrentType(); } else if (event.key === 'ArrowLeft') { currentTypeIndex = (currentTypeIndex - 1 + animalTypes.length) % animalTypes.length; updateCurrentType(); } }); // Particle motion simulation function updateParticles() { particleSystem.children.forEach(particle => { const direction = particle.userData.direction; const position = particle.position; // Move particle position.add(direction.multiplyScalar(particle.userData.accelerate)); // Detect collisions and adjust behavior particleSystem.children.forEach(otherParticle => { if (particle !== otherParticle) { const distance = position.distanceTo(otherParticle.position); if (distance < 0.5) { // Reverse direction on collision direction.negate(); particle.userData.accelerate = particle.userData.reverse; } } }); // Gradually brake if (particle.userData.accelerate > 0) { particle.userData.accelerate -= particle.userData.brake; if (particle.userData.accelerate < 0) { particle.userData.accelerate = 0; } } // Bounce off edges of the board if (position.x < -boardSize / 2 || position.x > boardSize / 2) { direction.x = -direction.x; } if (position.z < -boardSize / 2 || position.z > boardSize / 2) { direction.z = -direction.z; } }); } // Timer update function function updateTimer() { simulationTime++; timerElement.textContent = simulationTime; if (simulationTime % 10 === 0) { epoch++; epochElement.textContent = epoch; } } setInterval(updateTimer, 1000); // Set camera position camera.position.set(0, 50, 50); camera.lookAt(0, 0, 0); // Animation loop function animate() { requestAnimationFrame(animate); updateParticles(); renderer.render(scene, camera); } animate(); </script> </body> </html>