Desi Open World 3D
by CosmicFlare41527 lines11.5 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Desi Open World 3D</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: Arial, sans-serif;
background: #87ceeb;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0,0,0,0.75);
padding: 12px;
border-radius: 10px;
line-height: 1.5;
}
#controls {
position: absolute;
bottom: 20px;
left: 10px;
color: white;
background: rgba(0,0,0,0.65);
padding: 10px;
border-radius: 10px;
}
</style>
</head>
<body>
<div id="info">
<b>DESI OPEN WORLD</b><br>
3D Indian Driving Game<br>
<span id="speed">Speed: 0 km/h</span><br>
WASD / Arrow keys = Drive<br>
C = Change Camera<br>
R = Reset Car
</div>
<div id="controls">
Explore the Indian countryside!
</div>
<script type="module">
import * as THREE from
'https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js';
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87ceeb);
scene.fog = new THREE.Fog(0x87ceeb, 150, 900);
const camera = new THREE.PerspectiveCamera(
70,
window.innerWidth / window.innerHeight,
0.1,
1500
);
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
document.body.appendChild(renderer.domElement);
// Lighting
scene.add(new THREE.HemisphereLight(0xffffff, 0x607044, 2));
const sunlight = new THREE.DirectionalLight(0xfff1d0, 3);
sunlight.position.set(-100, 150, 100);
sunlight.castShadow = true;
scene.add(sunlight);
// Materials
function material(color, roughness = 0.9) {
return new THREE.MeshStandardMaterial({
color,
roughness
});
}
// Ground
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(1400, 1400),
material(0x629447)
);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Mountains and hills
function makeHill(x, z, width, height, depth, color) {
const hill = new THREE.Mesh(
new THREE.SphereGeometry(1, 24, 16),
material(color)
);
hill.position.set(x, height * 0.25, z);
hill.scale.set(width, height, depth);
hill.castShadow = true;
scene.add(hill);
}
for (let i = 0; i < 28; i++) {
const angle = i / 28 * Math.PI * 2;
const radius = 420 + Math.random() * 100;
makeHill(
Math.cos(angle) * radius,
Math.sin(angle) * radius,
65 + Math.random() * 50,
35 + Math.random() * 35,
70 + Math.random() * 40,
0x748c55
);
}
for (let i = 0; i < 14; i++) {
const mountain = new THREE.Mesh(
new THREE.ConeGeometry(55 + Math.random() * 35, 150, 5),
material(0x82918b)
);
mountain.position.set(-500 + i * 75, 65, -480);
mountain.rotation.y = Math.random() * Math.PI;
scene.add(mountain);
}
// Roads
function makeRoad(x, z, width, length) {
const road = new THREE.Mesh(
new THREE.PlaneGeometry(width, length),
material(0x303337)
);
road.rotation.x = -Math.PI / 2;
road.position.set(x, 0.04, z);
road.receiveShadow = true;
scene.add(road);
}
makeRoad(0, 0, 24, 1100);
makeRoad(0, 0, 1100, 24);
// Road markings
for (let z = -530; z < 530; z += 22) {
const line = new THREE.Mesh(
new THREE.PlaneGeometry(0.4, 9),
material(0xffffff)
);
line.rotation.x = -Math.PI / 2;
line.position.set(0, 0.07, z);
scene.add(line);
}
for (let x = -530; x < 530; x += 22) {
const line = new THREE.Mesh(
new THREE.PlaneGeometry(9, 0.4),
material(0xffffff)
);
line.rotation.x = -Math.PI / 2;
line.position.set(x, 0.07, 0);
scene.add(line);
}
// Trees
function makeTree(x, z, scale = 1) {
const tree = new THREE.Group();
const trunk = new THREE.Mesh(
new THREE.CylinderGeometry(0.3, 0.5, 4, 8),
material(0x654321)
);
trunk.position.y = 2;
tree.add(trunk);
const leaves = new THREE.Mesh(
new THREE.SphereGeometry(2.5, 12, 10),
material(0x237a36)
);
leaves.position.y = 5;
leaves.castShadow = true;
tree.add(leaves);
const top = new THREE.Mesh(
new THREE.SphereGeometry(1.8, 12, 10),
material(0x368c42)
);
top.position.y = 6.3;
tree.add(top);
tree.position.set(x, 0, z);
tree.scale.setScalar(scale);
scene.add(tree);
}
for (let i = 0; i < 260; i++) {
const x = (Math.random() - 0.5) * 1100;
const z = (Math.random() - 0.5) * 1100;
if (Math.abs(x) < 18 || Math.abs(z) < 18) continue;
makeTree(x, z, 0.7 + Math.random() * 1.1);
}
// Village buildings
function makeHouse(x, z, color) {
const house = new THREE.Group();
const walls = new THREE.Mesh(
new THREE.BoxGeometry(10, 7, 9),
material(color)
);
walls.position.y = 3.5;
walls.castShadow = true;
house.add(walls);
const roof = new THREE.Mesh(
new THREE.ConeGeometry(7.5, 3, 4),
material(0x984d31)
);
roof.position.y = 8.5;
roof.rotation.y = Math.PI / 4;
house.add(roof);
const door = new THREE.Mesh(
new THREE.BoxGeometry(1.5, 3.4, 0.15),
material(0x49301e)
);
door.position.set(0, 1.7, 4.6);
house.add(door);
house.position.set(x, 0, z);
scene.add(house);
}
const houseColors = [
0xe8d1a5,
0xd5c8ad,
0xc4b69c,
0xe0d7c6
];
for (let i = 0; i < 30; i++) {
makeHouse(
140 + (i % 6) * 18,
120 + Math.floor(i / 6) * 20,
houseColors[i % houseColors.length]
);
}
// Pond
const pond = new THREE.Mesh(
new THREE.CircleGeometry(42, 40),
new THREE.MeshStandardMaterial({
color: 0x168fc0,
roughness: 0.25
})
);
pond.rotation.x = -Math.PI / 2;
pond.position.set(280, 0.08, -250);
scene.add(pond);
// Animals
function makeAnimal(x, z, color, size = 1) {
const animal = new THREE.Group();
const body = new THREE.Mesh(
new THREE.BoxGeometry(2.3, 1.1, 1),
material(color)
);
body.position.y = 1.2;
animal.add(body);
const head = new THREE.Mesh(
new THREE.BoxGeometry(0.65, 0.7, 0.65),
material(color)
);
head.position.set(1.2, 1.7, 0);
animal.add(head);
for (let i = 0; i < 4; i++) {
const leg = new THREE.Mesh(
new THREE.CylinderGeometry(0.1, 0.12, 0.8, 6),
material(0x51402f)
);
leg.position.set(
i < 2 ? -0.75 : 0.75,
0.4,
i % 2 ? -0.3 : 0.3
);
animal.add(leg);
}
animal.position.set(x, 0, z);
animal.scale.setScalar(size);
animal.rotation.y = Math.random() * Math.PI * 2;
scene.add(animal);
}
for (let i = 0; i < 12; i++) {
makeAnimal(
(Math.random() - 0.5) * 650,
(Math.random() - 0.5) * 650,
i % 2 ? 0xeee6d4 : 0x99724f,
0.8 + Math.random() * 0.4
);
}
// Indian-style vehicles
function makeVehicle(color, type = "car") {
const vehicle = new THREE.Group();
const body = new THREE.Mesh(
new THREE.BoxGeometry(
type === "jeep" ? 3.1 : 2.6,
0.85,
type === "auto" ? 3.1 : 4.2
),
material(color, 0.4)
);
body.position.y = 1;
body.castShadow = true;
vehicle.add(body);
if (type !== "auto") {
const cabin = new THREE.Mesh(
new THREE.BoxGeometry(2, 0.9, 2.1),
material(0x274455, 0.25)
);
cabin.position.set(0, 1.7, -0.15);
vehicle.add(cabin);
const roof = new THREE.Mesh(
new THREE.BoxGeometry(2.1, 0.15, 2.2),
material(color)
);
roof.position.set(0, 2.2, -0.15);
vehicle.add(roof);
} else {
const roof = new THREE.Mesh(
new THREE.BoxGeometry(1.8, 0.2, 1.8),
material(0x252525)
);
roof.position.y = 2;
vehicle.add(roof);
}
const wheels = [];
for (const x of [-1.25, 1.25]) {
for (const z of [-1.35, 1.35]) {
const wheel = new THREE.Mesh(
new THREE.CylinderGeometry(0.42, 0.42, 0.28, 16),
material(0x151515)
);
wheel.rotation.z = Math.PI / 2;
wheel.position.set(x, 0.45, z);
wheel.castShadow = true;
vehicle.add(wheel);
wheels.push(wheel);
}
}
return { vehicle, wheels };
}
// Player car
const playerData = makeVehicle(0xd62828);
const car = playerData.vehicle;
scene.add(car);
// Parked vehicles
const suv = makeVehicle(0xe9e9e9, "jeep");
suv.vehicle.position.set(15, 0, 4);
scene.add(suv.vehicle);
const auto = makeVehicle(0x1da36c, "auto");
auto.vehicle.position.set(22, 0, -5);
scene.add(auto.vehicle);
const blueCar = makeVehicle(0x2469d8);
blueCar.vehicle.position.set(-12, 0, 5);
scene.add(blueCar.vehicle);
// Driving
const keys = {};
let speed = 0;
let heading = 0;
let cameraMode = 0;
window.addEventListener("keydown", event => {
keys[event.key.toLowerCase()] = true;
if (event.key.toLowerCase() === "c") {
cameraMode = (cameraMode + 1) % 2;
}
if (event.key.toLowerCase() === "r") {
car.position.set(0, 0, 0);
speed = 0;
heading = 0;
}
});
window.addEventListener("keyup", event => {
keys[event.key.toLowerCase()] = false;
});
function animate() {
requestAnimationFrame(animate);
if (keys["w"] || keys["arrowup"]) {
speed = Math.min(speed + 0.015, 0.7);
} else if (keys["s"] || keys["arrowdown"]) {
speed = Math.max(speed - 0.02, -0.3);
} else {
speed *= 0.985;
}
if (keys[" "]) speed *= 0.92;
if (Math.abs(speed) > 0.005) {
if (keys["a"] || keys["arrowleft"]) {
heading += 0.035 * Math.sign(speed);
}
if (keys["d"] || keys["arrowright"]) {
heading -= 0.035 * Math.sign(speed);
}
}
car.rotation.y = heading;
car.position.x += Math.sin(heading) * speed;
car.position.z += Math.cos(heading) * speed;
car.position.x = THREE.MathUtils.clamp(car.position.x, -650, 650);
car.position.z = THREE.MathUtils.clamp(car.position.z, -650, 650);
playerData.wheels.forEach(wheel => {
wheel.rotation.x += speed * 1.5;
});
const forward = new THREE.Vector3(
Math.sin(heading), 0, Math.cos(heading)
);
if (cameraMode === 0) {
const desired = car.position.clone()
.addScaledVector(forward, -10)
.add(new THREE.Vector3(0, 5, 0));
camera.position.lerp(desired, 0.1);
camera.lookAt(
car.position.clone().add(new THREE.Vector3(0, 1.5, 0))
);
} else {
camera.position.copy(car.position)
.add(new THREE.Vector3(0, 2.4, 0))
.addScaledVector(forward, 1.1);
camera.lookAt(
car.position.clone()
.addScaledVector(forward, 20)
.add(new THREE.Vector3(0, 1.5, 0))
);
}
document.getElementById("speed").textContent =
"Speed: " + Math.round(Math.abs(speed) * 180) + " km/h";
renderer.render(scene, camera);
}
animate();
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>Game Source: Desi Open World 3D
Creator: CosmicFlare41
Libraries: three
Complexity: complex (527 lines, 11.5 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: desi-open-world-3d-cosmicflare41" to link back to the original. Then publish at arcadelab.ai/publish.