Spaces:
Sleeping
Sleeping
<html> | |
<head> | |
<title>Minecraft-like 3D Game</title> | |
<style> | |
body { margin: 0; overflow: hidden; } | |
canvas { width: 100%; height: 100%; } | |
</style> | |
</head> | |
<body> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script> | |
<script> | |
// Three.js setup | |
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); | |
const chunkSize = 5; | |
let playerPos = [0, 0]; | |
const chunks = new Map(); | |
// Create a chunk mesh from heightmap | |
function createChunkMesh(chunkData, chunkX, chunkZ) { | |
const geometry = new THREE.BufferGeometry(); | |
const vertices = []; | |
const indices = []; | |
for (let x = 0; x < chunkSize; x++) { | |
for (let z = 0; z < chunkSize; z++) { | |
const y = chunkData[x][z]; | |
const baseX = chunkX * chunkSize + x; | |
const baseZ = chunkZ * chunkSize + z; | |
vertices.push(baseX, y, baseZ); | |
} | |
} | |
for (let x = 0; x < chunkSize - 1; x++) { | |
for (let z = 0; z < chunkSize - 1; z++) { | |
const a = x + z * chunkSize; | |
const b = (x + 1) + z * chunkSize; | |
const c = x + (z + 1) * chunkSize; | |
const d = (x + 1) + (z + 1) * chunkSize; | |
indices.push(a, b, d); | |
indices.push(a, d, c); | |
} | |
} | |
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); | |
geometry.setIndex(indices); | |
geometry.computeVertexNormals(); | |
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true }); | |
const mesh = new THREE.Mesh(geometry, material); | |
scene.add(mesh); | |
return mesh; | |
} | |
// Fetch and update world | |
async function move(dx, dz) { | |
const response = await fetch(`http://broadfeild-dev-mind-craft.hf.space/move?dx=${dx}&dz=${dz}`); | |
const data = await response.json(); | |
playerPos = data.player_pos; | |
const key = `${data.chunk_coords[0]},${data.chunk_coords[1]}`; | |
if (!chunks.has(key)) { | |
const mesh = createChunkMesh(data.chunk, data.chunk_coords[0], data.chunk_coords[1]); | |
chunks.set(key, mesh); | |
} | |
updateCamera(); | |
} | |
// Camera follows player | |
function updateCamera() { | |
camera.position.set(playerPos[0], 10, playerPos[1] + 10); | |
camera.lookAt(playerPos[0], 0, playerPos[1]); | |
} | |
// Animation loop | |
function animate() { | |
requestAnimationFrame(animate); | |
renderer.render(scene, camera); | |
} | |
animate(); | |
// Keyboard controls | |
document.addEventListener('keydown', (event) => { | |
switch (event.key) { | |
case 'ArrowUp': move(0, -1); break; | |
case 'ArrowDown': move(0, 1); break; | |
case 'ArrowLeft': move(-1, 0); break; | |
case 'ArrowRight': move(1, 0); break; | |
} | |
}); | |
// Initial load | |
move(0, 0); | |
</script> | |
</body> | |
</html> |