Spaces:
Running
Running
<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; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="hud" id="hud"> | |
<p>Current Type: <span id="currentType">Swan 🦢</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); | |
// 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 } | |
]; | |
// Particle system for motion simulation | |
const particleSystem = new THREE.Group(); | |
scene.add(particleSystem); | |
// 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.1, 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() }; | |
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; | |
particle.position.add(direction.multiplyScalar(0.01)); | |
// Bounce off edges of the board | |
if (particle.position.x < -boardSize / 2 || particle.position.x > boardSize / 2) { | |
direction.x = -direction.x; | |
} | |
if (particle.position.z < -boardSize / 2 || particle.position.z > boardSize / 2) { | |
direction.z = -direction.z; | |
} | |
}); | |
} | |
// 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> | |