Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chennai GTA V Mini Clone</title>
<style>
body { margin: 0; overflow: hidden; font-family: sans-serif; }
#ui {
position: absolute; top: 10px; left: 10px;
color: white; background: rgba(0,0,0,0.7);
padding: 15px; border-radius: 8px;
}
#controls { position: absolute; bottom: 10px; left: 10px; color: yellow; font-size: 14px; }
</style>
<!-- Three.js Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="ui">
<h2>π Chennai City Drive</h2>
<p>Location: Chennai Central Express Highway</p>
</div>
<div id="controls">
Controls: Use Arrow Keys or W, A, S, D to drive the car!
</div>
<script>
// --- 1. Scene Setup ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // Sky Blue
scene.fog = new THREE.FogExp2(0x87CEEB, 0.015);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- 2. Lighting ---
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xfffaed, 0.8);
dirLight.position.set(100, 100, 50);
scene.add(dirLight);
// --- 3. Environment (Chennai Roads & Buildings) ---
// Road
const roadGeo = new THREE.PlaneGeometry(40, 1000);
const roadMat = new THREE.MeshLambertMaterial({ color: 0x333333 });
const road = new THREE.Mesh(roadGeo, roadMat);
road.rotation.x = -Math.PI / 2;
scene.add(road);
// Chennai Buildings (Randomized blocks)
const buildings = [];
const colors = [0xffffff, 0xffd700, 0xfa8072, 0x40e0d0, 0x98fb98];
for (let i = 0; i < 50; i++) {
let h = 10 + Math.random() * 40;
let w = 10 + Math.random() * 15;
const bGeo = new THREE.BoxGeometry(w, h, w);
const bMat = new THREE.MeshLambertMaterial({ color: colors[Math.floor(Math.random() * colors.length)] });
const b = new THREE.Mesh(bGeo, bMat);
// Place along the sides of the road
b.position.x = (Math.random() > 0.5 ? 1 : -1) * (30 + Math.random() * 20);
b.position.z = -Math.random() * 800 + 100;
b.position.y = h / 2;
scene.add(b);
buildings.push(b);
}
// --- 4. The Player Car (Luxury Sports Car) ---
const carGroup = new THREE.Group();
// Car Body
const bodyGeo = new THREE.BoxGeometry(4, 1.5, 8);
const bodyMat = new THREE.MeshLambertMaterial({ color: 0xff0000 }); // Red Car
const carBody = new THREE.Mesh(bodyGeo, bodyMat);
carBody.position.y = 1;
carGroup.add(carBody);
// Car Cabin
const cabinGeo = new THREE.BoxGeometry(3.5, 1.2, 4);
const cabinMat = new THREE.MeshLambertMaterial({ color: 0x111111 });
const carCabin = new THREE.Mesh(cabinGeo, cabinMat);
carCabin.position.set(0, 2, -0.5);
carGroup.add(carCabin);
// Wheels
const wheelGeo = new THREE.CylinderGeometry(0.8, 0.8, 1, 16);
const wheelMat = new THREE.MeshLambertMaterial({ color: 0x000000 });
const wheelPositions = [
[-2.1, 0.5, -2.5], [2.1, 0.5, -2.5],
[-2.1, 0.5, 2.5], [2.1, 0.5, 2.5]
];
wheelPositions.forEach(pos => {
const wheel = new THREE.Mesh(wheelGeo, wheelMat);
wheel.rotation.z = Math.PI / 2;
wheel.position.set(pos[0], pos[1], pos[2]);
carGroup.add(wheel);
});
scene.add(carGroup);
carGroup.position.set(0, 0, 0);
// --- 5. Controls Logic ---
const keys = { w: false, a: false, s: false, d: false, ArrowUp: false, ArrowDown: false, ArrowLeft: false, ArrowRight: false };
let speed = 0;
const maxSpeed = 1.5;
const acceleration = 0.05;
const friction = 0.02;
window.addEventListener('keydown', (e) => { if(e.key in keys || ['w','a','s','d'].includes(e.key.toLowerCase())) keys[e.key.toLowerCase() || e.key] = true; });
window.addEventListener('keyup', (e) => { if(e.key in keys || ['w','a','s','d'].includes(e.key.toLowerCase())) keys[e.key.toLowerCase() || e.key] = false; });
// --- 6. Game Loop (Animation) ---
function animate() {
requestAnimationFrame(animate);
// Driving Logic
if (keys.w || keys.arrowup) {
if (speed > -maxSpeed) speed -= acceleration;
} else if (keys.s || keys.arrowdown) {
if (speed < maxSpeed) speed += acceleration;
} else {
// Apply friction to slow down naturally
if (speed > 0) speed -= friction;
if (speed < 0) speed += friction;
if (Math.abs(speed) < friction) speed = 0;
}
if (keys.a || keys.arrowleft) carGroup.position.x -= 0.3;
if (keys.d || keys.arrowright) carGroup.position.x += 0.3;
// Move Car Forward/Backward
carGroup.position.z += speed;
// Camera follows the car (GTA Third Person Style)
camera.position.set(carGroup.position.x, carGroup.position.y + 6, carGroup.position.z + 18);
camera.lookAt(carGroup.position.x, carGroup.position.y + 2, carGroup.position.z - 5);
// Endless World Loop
if(carGroup.position.z < -450) {
carGroup.position.z = 0; // Reset position for endless loop
}
renderer.render(scene, camera);
}
// Handle Window Resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
</script>
</body>
</html>2
2
125KB
596KB
1,072.0ms
884.0ms
1,072.0ms