For the bordii.

This commit is contained in:
retoor 2025-07-23 23:43:19 +02:00
parent 6378c397a0
commit 35272c710d

269
bordii1.html Normal file
View File

@ -0,0 +1,269 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js City Walker</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: Arial, sans-serif;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0,0,0,0.7);
padding: 10px;
border-radius: 5px;
font-size: 14px;
}
</style>
</head>
<body>
<div id="info">
Use WASD or Arrow Keys to move<br>
Mouse to look around<br>
Click to lock pointer
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // Sky blue
scene.fog = new THREE.Fog(0x87CEEB, 10, 500);
// Camera
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1.6, 10); // Eye height
// Renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(50, 100, 50);
directionalLight.castShadow = true;
directionalLight.shadow.camera.left = -100;
directionalLight.shadow.camera.right = 100;
directionalLight.shadow.camera.top = 100;
directionalLight.shadow.camera.bottom = -100;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 200;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);
// Ground
const groundGeometry = new THREE.PlaneGeometry(200, 200);
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x3a3a3a });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Create buildings
const buildings = [];
const buildingColors = [0x8B4513, 0x696969, 0x778899, 0x2F4F4F, 0x483D8B];
function createBuilding(x, z, width, height, depth, color) {
const geometry = new THREE.BoxGeometry(width, height, depth);
const material = new THREE.MeshLambertMaterial({ color: color });
const building = new THREE.Mesh(geometry, material);
building.position.set(x, height / 2, z);
building.castShadow = true;
building.receiveShadow = true;
scene.add(building);
buildings.push(building);
// Add windows (simple emissive rectangles)
const windowMaterial = new THREE.MeshBasicMaterial({ color: 0xffff99, emissive: 0xffff99 });
const windowSize = 0.8;
const windowSpacing = 2;
for (let floor = 1; floor < height / 3; floor++) {
for (let i = 0; i < width / windowSpacing - 1; i++) {
const windowGeometry = new THREE.PlaneGeometry(windowSize, windowSize);
const window1 = new THREE.Mesh(windowGeometry, windowMaterial);
window1.position.set(x - width/2 + (i + 1) * windowSpacing, floor * 3, z + depth/2 + 0.01);
scene.add(window1);
const window2 = new THREE.Mesh(windowGeometry, windowMaterial);
window2.position.set(x - width/2 + (i + 1) * windowSpacing, floor * 3, z - depth/2 - 0.01);
window2.rotation.y = Math.PI;
scene.add(window2);
}
}
}
// Create city layout
createBuilding(-20, -20, 10, 25, 10, buildingColors[0]);
createBuilding(20, -20, 8, 30, 8, buildingColors[1]);
createBuilding(-20, 20, 12, 20, 12, buildingColors[2]);
createBuilding(20, 20, 15, 35, 15, buildingColors[3]);
createBuilding(0, 0, 10, 40, 10, buildingColors[4]);
createBuilding(-40, 0, 8, 15, 8, buildingColors[0]);
createBuilding(40, 0, 10, 25, 10, buildingColors[1]);
createBuilding(0, -40, 12, 18, 12, buildingColors[2]);
createBuilding(0, 40, 8, 22, 8, buildingColors[3]);
createBuilding(-40, -40, 10, 28, 10, buildingColors[4]);
createBuilding(40, -40, 8, 20, 8, buildingColors[0]);
createBuilding(-40, 40, 15, 32, 15, buildingColors[1]);
createBuilding(40, 40, 10, 25, 10, buildingColors[2]);
// Add some street lights
function createStreetLight(x, z) {
const poleGeometry = new THREE.CylinderGeometry(0.1, 0.1, 4);
const poleMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 });
const pole = new THREE.Mesh(poleGeometry, poleMaterial);
pole.position.set(x, 2, z);
pole.castShadow = true;
scene.add(pole);
const lightGeometry = new THREE.SphereGeometry(0.3);
const lightMaterial = new THREE.MeshBasicMaterial({ color: 0xffffaa, emissive: 0xffffaa });
const lightBulb = new THREE.Mesh(lightGeometry, lightMaterial);
lightBulb.position.set(x, 4, z);
scene.add(lightBulb);
const pointLight = new THREE.PointLight(0xffffaa, 0.5, 10);
pointLight.position.set(x, 4, z);
scene.add(pointLight);
}
createStreetLight(-30, 0);
createStreetLight(30, 0);
createStreetLight(0, -30);
createStreetLight(0, 30);
// Movement controls
const moveSpeed = 0.1;
const lookSpeed = 0.002;
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
const velocity = new THREE.Vector3();
const direction = new THREE.Vector3();
// Pointer lock controls
let isPointerLocked = false;
const euler = new THREE.Euler(0, 0, 0, 'YXZ');
renderer.domElement.addEventListener('click', () => {
renderer.domElement.requestPointerLock();
});
document.addEventListener('pointerlockchange', () => {
isPointerLocked = document.pointerLockElement === renderer.domElement;
});
document.addEventListener('mousemove', (event) => {
if (!isPointerLocked) return;
euler.setFromQuaternion(camera.quaternion);
euler.y -= event.movementX * lookSpeed;
euler.x -= event.movementY * lookSpeed;
euler.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, euler.x));
camera.quaternion.setFromEuler(euler);
});
// Keyboard controls
document.addEventListener('keydown', (event) => {
switch (event.code) {
case 'KeyW':
case 'ArrowUp':
moveForward = true;
break;
case 'KeyS':
case 'ArrowDown':
moveBackward = true;
break;
case 'KeyA':
case 'ArrowLeft':
moveLeft = true;
break;
case 'KeyD':
case 'ArrowRight':
moveRight = true;
break;
}
});
document.addEventListener('keyup', (event) => {
switch (event.code) {
case 'KeyW':
case 'ArrowUp':
moveForward = false;
break;
case 'KeyS':
case 'ArrowDown':
moveBackward = false;
break;
case 'KeyA':
case 'ArrowLeft':
moveLeft = false;
break;
case 'KeyD':
case 'ArrowRight':
moveRight = false;
break;
}
});
// Window resize handler
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update movement
direction.z = Number(moveForward) - Number(moveBackward);
direction.x = Number(moveRight) - Number(moveLeft);
direction.normalize();
if (moveForward || moveBackward) {
velocity.z -= direction.z * moveSpeed;
}
if (moveLeft || moveRight) {
velocity.x -= direction.x * moveSpeed;
}
// Apply movement with friction
velocity.x *= 0.9;
velocity.z *= 0.9;
// Move camera
const moveVector = new THREE.Vector3();
moveVector.x = -velocity.x;
moveVector.z = -velocity.z;
moveVector.applyQuaternion(camera.quaternion);
camera.position.add(moveVector);
// Keep camera at eye height
camera.position.y = 1.6;
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>