Spaces:
Sleeping
Sleeping
Update templates/index.html
Browse files- templates/index.html +100 -1
templates/index.html
CHANGED
@@ -1 +1,100 @@
|
|
1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>Minecraft-like 3D Game</title>
|
5 |
+
<style>
|
6 |
+
body { margin: 0; overflow: hidden; }
|
7 |
+
canvas { width: 100%; height: 100%; }
|
8 |
+
</style>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
|
12 |
+
<script>
|
13 |
+
// Three.js setup
|
14 |
+
const scene = new THREE.Scene();
|
15 |
+
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
16 |
+
const renderer = new THREE.WebGLRenderer();
|
17 |
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
18 |
+
document.body.appendChild(renderer.domElement);
|
19 |
+
|
20 |
+
const chunkSize = 5;
|
21 |
+
let playerPos = [0, 0];
|
22 |
+
const chunks = new Map();
|
23 |
+
|
24 |
+
// Create a chunk mesh from heightmap
|
25 |
+
function createChunkMesh(chunkData, chunkX, chunkZ) {
|
26 |
+
const geometry = new THREE.BufferGeometry();
|
27 |
+
const vertices = [];
|
28 |
+
const indices = [];
|
29 |
+
|
30 |
+
for (let x = 0; x < chunkSize; x++) {
|
31 |
+
for (let z = 0; z < chunkSize; z++) {
|
32 |
+
const y = chunkData[x][z];
|
33 |
+
const baseX = chunkX * chunkSize + x;
|
34 |
+
const baseZ = chunkZ * chunkSize + z;
|
35 |
+
vertices.push(baseX, y, baseZ);
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
for (let x = 0; x < chunkSize - 1; x++) {
|
40 |
+
for (let z = 0; z < chunkSize - 1; z++) {
|
41 |
+
const a = x + z * chunkSize;
|
42 |
+
const b = (x + 1) + z * chunkSize;
|
43 |
+
const c = x + (z + 1) * chunkSize;
|
44 |
+
const d = (x + 1) + (z + 1) * chunkSize;
|
45 |
+
indices.push(a, b, d);
|
46 |
+
indices.push(a, d, c);
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
|
51 |
+
geometry.setIndex(indices);
|
52 |
+
geometry.computeVertexNormals();
|
53 |
+
|
54 |
+
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
|
55 |
+
const mesh = new THREE.Mesh(geometry, material);
|
56 |
+
scene.add(mesh);
|
57 |
+
return mesh;
|
58 |
+
}
|
59 |
+
|
60 |
+
// Fetch and update world
|
61 |
+
async function move(dx, dz) {
|
62 |
+
const response = await fetch(`http://localhost:8000/move?dx=${dx}&dz=${dz}`);
|
63 |
+
const data = await response.json();
|
64 |
+
playerPos = data.player_pos;
|
65 |
+
const key = `${data.chunk_coords[0]},${data.chunk_coords[1]}`;
|
66 |
+
if (!chunks.has(key)) {
|
67 |
+
const mesh = createChunkMesh(data.chunk, data.chunk_coords[0], data.chunk_coords[1]);
|
68 |
+
chunks.set(key, mesh);
|
69 |
+
}
|
70 |
+
updateCamera();
|
71 |
+
}
|
72 |
+
|
73 |
+
// Camera follows player
|
74 |
+
function updateCamera() {
|
75 |
+
camera.position.set(playerPos[0], 10, playerPos[1] + 10);
|
76 |
+
camera.lookAt(playerPos[0], 0, playerPos[1]);
|
77 |
+
}
|
78 |
+
|
79 |
+
// Animation loop
|
80 |
+
function animate() {
|
81 |
+
requestAnimationFrame(animate);
|
82 |
+
renderer.render(scene, camera);
|
83 |
+
}
|
84 |
+
animate();
|
85 |
+
|
86 |
+
// Keyboard controls
|
87 |
+
document.addEventListener('keydown', (event) => {
|
88 |
+
switch (event.key) {
|
89 |
+
case 'ArrowUp': move(0, -1); break;
|
90 |
+
case 'ArrowDown': move(0, 1); break;
|
91 |
+
case 'ArrowLeft': move(-1, 0); break;
|
92 |
+
case 'ArrowRight': move(1, 0); break;
|
93 |
+
}
|
94 |
+
});
|
95 |
+
|
96 |
+
// Initial load
|
97 |
+
move(0, 0);
|
98 |
+
</script>
|
99 |
+
</body>
|
100 |
+
</html>
|