3D-World / index.html
ayush-thakur02's picture
Upload index.html
c5e4d57 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infinite Auto-Generating FPV Open World Simulation</title>
<style>
body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; }
#gameContainer { position: relative; width: 100vw; height: 100vh; }
#instructions {
position: absolute; top: 10px; left: 10px; color: white;
background-color: rgba(0, 0, 0, 0.5); padding: 10px; border-radius: 5px;
}
</style>
</head>
<body>
<div id="gameContainer">
<div id="instructions">
Use WASD to move, and mouse to look around.<br>
Press ESC to toggle mouse lock.
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>
<script>
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.getElementById('gameContainer').appendChild(renderer.domElement);
scene.background = new THREE.Color(0x87CEEB); // Sky blue
const chunkSize = 16;
const renderDistance = 5;
const chunks = new Map();
const simplex = new SimplexNoise();
// Player object
const player = new THREE.Object3D();
player.position.set(0, 10, 0);
scene.add(player);
player.add(camera);
function getTerrainHeight(x, z) {
return simplex.noise2D(x / 100, z / 100) * 10;
}
function generateTerrain(x, z) {
const geometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkSize - 1, chunkSize - 1);
geometry.rotateX(-Math.PI / 2);
const vertices = geometry.attributes.position.array;
for (let i = 0; i < vertices.length; i += 3) {
const vx = vertices[i] + x * chunkSize;
const vz = vertices[i + 2] + z * chunkSize;
vertices[i + 1] = getTerrainHeight(vx, vz);
}
geometry.computeVertexNormals();
const material = new THREE.MeshPhongMaterial({ color: 0x3d9970, wireframe: false });
const terrain = new THREE.Mesh(geometry, material);
terrain.position.set(x * chunkSize, 0, z * chunkSize);
return terrain;
}
function generateChunk(x, z) {
const chunk = new THREE.Group();
chunk.add(generateTerrain(x, z));
// Add trees
for (let i = 0; i < 5; i++) {
const treeX = Math.random() * chunkSize + x * chunkSize;
const treeZ = Math.random() * chunkSize + z * chunkSize;
const treeY = getTerrainHeight(treeX, treeZ);
const trunk = new THREE.Mesh(
new THREE.CylinderGeometry(0.2, 0.2, 2, 8),
new THREE.MeshPhongMaterial({ color: 0x8B4513 })
);
trunk.position.set(treeX, treeY + 1, treeZ);
const leaves = new THREE.Mesh(
new THREE.ConeGeometry(1, 2, 8),
new THREE.MeshPhongMaterial({ color: 0x228B22 })
);
leaves.position.set(treeX, treeY + 3, treeZ);
chunk.add(trunk, leaves);
}
return chunk;
}
function updateChunks() {
const playerChunkX = Math.floor(player.position.x / chunkSize);
const playerChunkZ = Math.floor(player.position.z / chunkSize);
for (let x = -renderDistance; x <= renderDistance; x++) {
for (let z = -renderDistance; z <= renderDistance; z++) {
const chunkX = playerChunkX + x;
const chunkZ = playerChunkZ + z;
const chunkKey = `${chunkX},${chunkZ}`;
if (!chunks.has(chunkKey)) {
const chunk = generateChunk(chunkX, chunkZ);
chunks.set(chunkKey, chunk);
scene.add(chunk);
}
}
}
// Remove far chunks
for (const [key, chunk] of chunks) {
const [x, z] = key.split(',').map(Number);
if (Math.abs(x - playerChunkX) > renderDistance || Math.abs(z - playerChunkZ) > renderDistance) {
scene.remove(chunk);
chunks.delete(key);
}
}
}
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// Improved movement controls
const moveSpeed = 0.1;
const movement = new THREE.Vector3();
const playerDirection = new THREE.Vector3();
function handleMovement() {
movement.set(0, 0, 0);
if (moveForward) movement.z -= 1;
if (moveBackward) movement.z += 1;
if (moveLeft) movement.x -= 1;
if (moveRight) movement.x += 1;
movement.normalize().multiplyScalar(moveSpeed);
player.getWorldDirection(playerDirection);
playerDirection.y = 0;
playerDirection.normalize();
const sideways = new THREE.Vector3(-playerDirection.z, 0, playerDirection.x);
player.position.addScaledVector(playerDirection, movement.z);
player.position.addScaledVector(sideways, movement.x);
// Adjust player height based on terrain
const terrainHeight = getTerrainHeight(player.position.x, player.position.z);
player.position.y = terrainHeight + 2; // Keep player 2 units above terrain
}
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
const onKeyDown = (event) => {
switch (event.code) {
case 'KeyW': moveForward = true; break;
case 'KeyS': moveBackward = true; break;
case 'KeyA': moveLeft = true; break;
case 'KeyD': moveRight = true; break;
}
};
const onKeyUp = (event) => {
switch (event.code) {
case 'KeyW': moveForward = false; break;
case 'KeyS': moveBackward = false; break;
case 'KeyA': moveLeft = false; break;
case 'KeyD': moveRight = false; break;
}
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
const gameContainer = document.getElementById('gameContainer');
let isLocked = false;
gameContainer.addEventListener('click', () => {
if (!isLocked) {
gameContainer.requestPointerLock();
}
});
document.addEventListener('pointerlockchange', () => {
isLocked = document.pointerLockElement === gameContainer;
});
document.addEventListener('mousemove', (event) => {
if (isLocked) {
player.rotation.y -= event.movementX * 0.002;
camera.rotation.x -= event.movementY * 0.002;
camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));
}
});
const animate = () => {
requestAnimationFrame(animate);
handleMovement();
updateChunks();
renderer.render(scene, camera);
};
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
if (isLocked) {
document.exitPointerLock();
} else {
gameContainer.requestPointerLock();
}
}
});
</script>
</body>
</html>