🎮ArcadeLab

Shahar Hayoti 3D

by DriftFlame10
199 lines6.2 KB🛠️ Three.js (3D graphics)
▶ Play
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Shahar Hayoti 3D</title>
<style>
  body { margin:0; overflow:hidden; background:#87CEEB; }
  #info { position:absolute; top:10px; left:10px; color:white;
          font-family:Arial; text-shadow:1px 1px 3px black; font-size:14px; }
</style>
</head>
<body>
<div id="info">WASD — yurish | Sichqoncha — qarash | E — mashinaga minish/chiqish</div>
<script type="importmap">
{ "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js" } }
</script>
<script type="module">
import * as THREE from 'three';

// --- Sahna ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB);
scene.fog = new THREE.Fog(0x87CEEB, 80, 250);

const camera = new THREE.PerspectiveCamera(60, innerWidth/innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

// --- Yorug'lik ---
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 1.2));
const sun = new THREE.DirectionalLight(0xffffff, 1.5);
sun.position.set(50, 100, 50);
sun.castShadow = true;
sun.shadow.camera.left = -100; sun.shadow.camera.right = 100;
sun.shadow.camera.top = 100; sun.shadow.camera.bottom = -100;
scene.add(sun);

// --- Yer ---
const ground = new THREE.Mesh(
  new THREE.PlaneGeometry(400, 400),
  new THREE.MeshLambertMaterial({color:0x3a7d44})
);
ground.rotation.x = -Math.PI/2;
ground.receiveShadow = true;
scene.add(ground);

// --- Yo'llar (to'r) ---
const roadMat = new THREE.MeshLambertMaterial({color:0x333333});
for (let i = -150; i <= 150; i += 50) {
  let r1 = new THREE.Mesh(new THREE.BoxGeometry(400, 0.1, 12), roadMat);
  r1.position.set(0, 0.05, i); scene.add(r1);
  let r2 = new THREE.Mesh(new THREE.BoxGeometry(12, 0.1, 400), roadMat);
  r2.position.set(i, 0.05, 0); scene.add(r2);
}

// --- Binolar ---
const buildingColors = [0x8d8d8d, 0xa67c52, 0x6b6b6b, 0xb0b0b0, 0x7a5c3e];
function makeBuilding(x, z) {
  const w = 8 + Math.random()*8;
  const d = 8 + Math.random()*8;
  const h = 10 + Math.random()*40;
  const mesh = new THREE.Mesh(
    new THREE.BoxGeometry(w, h, d),
    new THREE.MeshLambertMaterial({color: buildingColors[Math.floor(Math.random()*buildingColors.length)]})
  );
  mesh.position.set(x, h/2, z);
  mesh.castShadow = true; mesh.receiveShadow = true;
  scene.add(mesh);
}
for (let gx = -150; gx <= 150; gx += 50) {
  for (let gz = -150; gz <= 150; gz += 50) {
    // yo'l kesishmasidan chetga bino qo'yamiz
    if (Math.random() < 0.85) makeBuilding(gx + 20, gz + 20);
    if (Math.random() < 0.85) makeBuilding(gx - 20, gz - 20);
  }
}

// --- Personaj ---
const player = new THREE.Group();
const body = new THREE.Mesh(
  new THREE.CapsuleGeometry(0.5, 1, 4, 8),
  new THREE.MeshLambertMaterial({color:0x2b6cb0})
);
body.position.y = 1;
body.castShadow = true;
player.add(body);
player.position.set(0, 0, 0);
scene.add(player);

// --- Mashina ---
const car = new THREE.Group();
const carBody = new THREE.Mesh(
  new THREE.BoxGeometry(2, 1, 4),
  new THREE.MeshLambertMaterial({color:0xcc2222})
);
carBody.position.y = 0.8; carBody.castShadow = true;
car.add(carBody);
const roof = new THREE.Mesh(
  new THREE.BoxGeometry(1.8, 0.8, 2),
  new THREE.MeshLambertMaterial({color:0x222222})
);
roof.position.y = 1.6; roof.castShadow = true;
car.add(roof);
car.position.set(6, 0, 6);
scene.add(car);

// --- Boshqaruv ---
const keys = {};
addEventListener('keydown', e => keys[e.code] = true);
addEventListener('keyup', e => keys[e.code] = false);

let mouseYaw = 0, mousePitch = 0.3;
document.body.requestPointerLock = document.body.requestPointerLock || (()=>{});
renderer.domElement.addEventListener('click', () => renderer.domElement.requestPointerLock());
addEventListener('mousemove', e => {
  if (document.pointerLockElement) {
    mouseYaw -= e.movementX * 0.002;
    mousePitch -= e.movementY * 0.002;
    mousePitch = Math.max(0.05, Math.min(1.2, mousePitch));
  }
});

let inCar = false;
addEventListener('keydown', e => {
  if (e.code === 'KeyE') {
    if (inCar) {
      inCar = false;
      player.position.copy(car.position);
      player.position.x += 3;
    } else {
      const dist = player.position.distanceTo(car.position);
      if (dist < 4) inCar = true;
    }
  }
});

// --- Animatsiya ---
const clock = new THREE.Clock();
let speed = 0;

function animate() {
  requestAnimationFrame(animate);
  const dt = Math.min(clock.getDelta(), 0.05);

  if (inCar) {
    // mashina boshqaruvi
    if (keys['KeyW']) speed += 30 * dt;
    if (keys['KeyS']) speed -= 30 * dt;
    speed *= 0.98;
    car.rotation.y += (keys['KeyA']?1:0)*dt*1.5 - (keys['KeyD']?1:0)*dt*1.5;
    car.position.x += Math.sin(car.rotation.y) * speed * dt;
    car.position.z += Math.cos(car.rotation.y) * speed * dt;

    // kamera mashina orqasidan
    const camDist = 10;
    camera.position.x = car.position.x - Math.sin(car.rotation.y) * camDist;
    camera.position.z = car.position.z - Math.cos(car.rotation.y) * camDist;
    camera.position.y = 6;
    camera.lookAt(car.position.x, 2, car.position.z);
  } else {
    // personaj yurishi
    const dir = new THREE.Vector3();
    if (keys['KeyW']) dir.z -= 1;
    if (keys['KeyS']) dir.z += 1;
    if (keys['KeyA']) dir.x -= 1;
    if (keys['KeyD']) dir.x += 1;
    if (dir.length() > 0) {
      dir.normalize();
      // kamera yo'nalishiga moslashtirish
      const angle = mouseYaw;
      const dx = dir.x * Math.cos(angle) - dir.z * Math.sin(angle);
      const dz = dir.x * Math.sin(angle) + dir.z * Math.cos(angle);
      player.position.x += dx * 8 * dt;
      player.position.z += dz * 8 * dt;
      body.rotation.y = Math.atan2(dx, dz);
    }

    // kamera uchinchi shaxs
    const camDist = 8;
    camera.position.x = player.position.x + Math.sin(mouseYaw) * camDist * Math.cos(mousePitch);
    camera.position.z = player.position.z + Math.cos(mouseYaw) * camDist * Math.cos(mousePitch);
    camera.position.y = player.position.y + 3 + Math.sin(mousePitch) * camDist;
    camera.lookAt(player.position.x, 2, player.position.z);
  }

  renderer.render(scene, camera);
}
animate();

addEventListener('resize', () => {
  camera.aspect = innerWidth/innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>

Game Source: Shahar Hayoti 3D

Creator: DriftFlame10

Libraries: three

Complexity: moderate (199 lines, 6.2 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: shahar-hayoti-3d-driftflame10" to link back to the original. Then publish at arcadelab.ai/publish.