<!DOCTYPE html>
<html lang="hi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>3D Battle Royale - Realistic Human</title>
<style>
body { margin: 0; overflow: hidden; background: #111; font-family: 'Segoe UI', Arial, sans-serif; user-select: none; }
/* टॉप HUD */
#hud-top {
position: absolute; top: 10px; left: 10px; right: 10px;
display: flex; justify-content: space-between; align-items: flex-start;
z-index: 10; pointer-events: none;
}
.panel {
background: rgba(0, 0, 0, 0.65); color: white; padding: 8px 14px;
border-radius: 6px; border-left: 4px solid #ff9800; font-weight: bold; font-size: 14px;
}
#hp-bar-wrap { width: 140px; height: 10px; background: #333; margin-top: 4px; border-radius: 5px; overflow: hidden; }
#hp-bar { width: 100%; height: 100%; background: #4caf50; transition: 0.2s; }
#zone-alert {
position: absolute; top: 65px; left: 50%; transform: translateX(-50%);
background: rgba(33, 150, 243, 0.85); color: white; padding: 5px 15px;
border-radius: 20px; font-size: 13px; font-weight: bold; display: none; z-index: 12;
}
/* निशाना */
#crosshair {
position: absolute; top: 45%; left: 50%; width: 26px; height: 26px;
transform: translate(-50%, -50%); pointer-events: none; z-index: 10;
border: 2px solid rgba(255,255,255,0.75); border-radius: 50%;
}
#crosshair::after {
content: ''; position: absolute; top: 11px; left: 11px; width: 4px; height: 4px;
background: red; border-radius: 50%;
}
#scope-overlay {
display: none; position: fixed; inset: 0; pointer-events: none; z-index: 9;
background: radial-gradient(circle, transparent 28%, rgba(0,0,0,0.88) 32%);
}
/* जॉयस्टिक */
#joystick-zone {
position: absolute; bottom: 25px; left: 25px; width: 115px; height: 115px;
background: rgba(255, 255, 255, 0.15); border: 2px solid rgba(255,255,255,0.4);
border-radius: 50%; z-index: 15; touch-action: none;
}
#joystick-knob {
position: absolute; top: 32px; left: 32px; width: 50px; height: 50px;
background: rgba(255, 152, 0, 0.85); border-radius: 50%; pointer-events: none;
}
/* कैमरा रोटेशन */
#look-zone { position: absolute; top: 0; right: 0; width: 55%; height: 100%; z-index: 5; touch-action: none; }
/* एक्शन बटन्स */
.btn {
position: absolute; border-radius: 50%; border: 2px solid rgba(255,255,255,0.85);
color: white; font-weight: bold; z-index: 15; touch-action: manipulation;
display: flex; flex-direction: column; align-items: center; justify-content: center;
box-shadow: 0 4px 8px rgba(0,0,0,0.5); font-size: 11px;
}
#fireBtn { bottom: 35px; right: 25px; width: 80px; height: 80px; background: radial-gradient(circle, #ff5722, #bf360c); font-size: 16px; }
#fireBtn:active { transform: scale(0.92); }
#jumpBtn { bottom: 130px; right: 25px; width: 52px; height: 52px; background: rgba(0,0,0,0.65); }
#scopeBtn { bottom: 130px; right: 90px; width: 52px; height: 52px; background: rgba(0,0,0,0.65); }
#glooBtn { bottom: 35px; right: 120px; width: 56px; height: 56px; background: rgba(0, 188, 212, 0.85); }
#medkitBtn { bottom: 35px; right: 185px; width: 52px; height: 52px; background: rgba(76, 175, 80, 0.85); }
#sprintBtn { bottom: 155px; left: 55px; width: 50px; height: 50px; background: rgba(255, 152, 0, 0.7); }
/* स्टार्ट और एंड स्क्रीन */
#overlayScreen {
position: fixed; inset: 0; background: rgba(10, 15, 25, 0.92);
color: white; display: flex; flex-direction: column; align-items: center; justify-content: center;
z-index: 30; text-align: center; padding: 20px;
}
.main-btn {
background: linear-gradient(45deg, #ff9800, #ff5722); color: white; border: none;
padding: 14px 35px; font-size: 20px; font-weight: bold; border-radius: 8px;
margin-top: 20px; cursor: pointer; box-shadow: 0 4px 15px rgba(255,87,34,0.5);
}
</style>
</head>
<body>
<div id="hud-top">
<div class="panel">
HP: <span id="hp-val">200</span>/200
<div id="hp-bar-wrap"><div id="hp-bar"></div></div>
</div>
<div class="panel" style="border-left-color: #00bcd4;">
ZONE: <span id="zone-rad">140</span>m
</div>
<div class="panel" style="border-left-color: #f44336;">
KILLS: <span id="kills-val">0</span> | ALIVE: <span id="alive-val">12</span>
</div>
</div>
<div id="zone-alert">⚠️ आप सेफ ज़ोन से बाहर हैं! अंदर जाएं!</div>
<div id="scope-overlay"></div>
<div id="crosshair"></div>
<div id="look-zone"></div>
<div id="joystick-zone"><div id="joystick-knob"></div></div>
<button class="btn" id="sprintBtn">RUN</button>
<button class="btn" id="fireBtn">FIRE</button>
<button class="btn" id="jumpBtn">JUMP</button>
<button class="btn" id="scopeBtn">2X</button>
<button class="btn" id="glooBtn">WALL<br>(<span id="gloo-val">4</span>)</button>
<button class="btn" id="medkitBtn">+HP<br>(<span id="med-val">3</span>)</button>
<div id="overlayScreen">
<h1 id="screenTitle" style="color:#ff9800; font-size:32px; margin-bottom:10px;">3D BATTLE ROYALE</h1>
<p id="screenSub" style="font-size:16px; color:#ccc; max-width:400px;">
असली ह्यूमन कैरेक्टर एनीमेशन, पैराशूट लैंडिंग, Gloo Wall और बैटल रॉयल एक्शन!
</p>
<button class="main-btn" id="startBtn">START MATCH</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// साउंड जनरेटर
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playGunSound() {
if (audioCtx.state === 'suspended') audioCtx.resume();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(190, audioCtx.currentTime);
osc.frequency.exponentialRampToValueAtTime(45, audioCtx.currentTime + 0.11);
gain.gain.setValueAtTime(0.25, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.11);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + 0.11);
}
// 1. सीन और लाइटिंग
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB);
scene.fog = new THREE.Fog(0x87CEEB, 40, 180);
const camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 600);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 0.9));
const sun = new THREE.DirectionalLight(0xffffff, 0.9);
sun.position.set(50, 80, 40);
sun.castShadow = true;
scene.add(sun);
// 2. मैप और सेफ ज़ोन
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(360, 360),
new THREE.MeshStandardMaterial({ color: 0x38761d, roughness: 0.9 })
);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
let zoneRadius = 140;
const safeZoneMesh = new THREE.Mesh(
new THREE.CylinderGeometry(zoneRadius, zoneRadius, 25, 48, 1, true),
new THREE.MeshBasicMaterial({ color: 0x00b0ff, transparent: true, opacity: 0.25, side: THREE.DoubleSide })
);
safeZoneMesh.position.y = 12.5;
scene.add(safeZoneMesh);
const glooWalls = [];
function buildMap() {
const houseMat = new THREE.MeshStandardMaterial({ color: 0xd7ccc8 });
const roofMat = new THREE.MeshStandardMaterial({ color: 0x8d6e63 });
const treeWood = new THREE.MeshStandardMaterial({ color: 0x5d4037 });
const treeLeaf = new THREE.MeshStandardMaterial({ color: 0x1b5e20 });
for (let i = 0; i < 45; i++) {
const x = (Math.random() - 0.5) * 240;
const z = (Math.random() - 0.5) * 240;
if (Math.abs(x) < 12 && Math.abs(z) < 12) continue;
if (i % 3 === 0) {
const house = new THREE.Mesh(new THREE.BoxGeometry(7, 4.5, 7), houseMat);
house.position.set(x, 2.25, z);
const roof = new THREE.Mesh(new THREE.ConeGeometry(5.5, 2.5, 4), roofMat);
roof.position.set(x, 5.7, z);
roof.rotation.y = Math.PI / 4;
scene.add(house, roof);
} else {
const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.4, 0.6, 4.5), treeWood);
trunk.position.set(x, 2.25, z);
const leaves = new THREE.Mesh(new THREE.ConeGeometry(2.8, 6, 8), treeLeaf);
leaves.position.set(x, 6.5, z);
scene.add(trunk, leaves);
}
}
}
buildMap();
// ==========================================
// 3. असली इंसान (Realistic Articulated Human) बनाने का फंक्शन
// ==========================================
function createHumanCharacter(shirtColor, pantsColor, hasParachute = false) {
const human = new THREE.Group();
const skinMat = new THREE.MeshStandardMaterial({ color: 0xf1c27d, roughness: 0.6 });
const hairMat = new THREE.MeshStandardMaterial({ color: 0x1a1a1a, roughness: 0.8 });
const shirtMat = new THREE.MeshStandardMaterial({ color: shirtColor, roughness: 0.7 });
const vestMat = new THREE.MeshStandardMaterial({ color: 0x263238, roughness: 0.5 }); // टैक्टिकल जैकेट
const pantsMat = new THREE.MeshStandardMaterial({ color: pantsColor, roughness: 0.8 });
const shoeMat = new THREE.MeshStandardMaterial({ color: 0x111111 });
// 1. सिर (गोल चेहरा + बाल + आँखें)
const headGroup = new THREE.Group();
headGroup.position.y = 2.35;
const headMesh = new THREE.Mesh(new THREE.SphereGeometry(0.26, 16, 16), skinMat);
headGroup.add(headMesh);
// बाल (Hair Cap)
const hairMesh = new THREE.Mesh(
new THREE.SphereGeometry(0.275, 16, 16, 0, Math.PI * 2, 0, Math.PI * 0.55),
hairMat
);
hairMesh.rotation.x = -0.2;
headGroup.add(hairMesh);
// आँखें (सामने की तरफ -Z दिशा में)
const eyeGeo = new THREE.SphereGeometry(0.035, 8, 8);
const eyeMat = new THREE.MeshBasicMaterial({ color: 0x000000 });
const leftEye = new THREE.Mesh(eyeGeo, eyeMat);
leftEye.position.set(-0.09, 0.02, -0.24);
const rightEye = new THREE.Mesh(eyeGeo, eyeMat);
rightEye.position.set(0.09, 0.02, -0.24);
headGroup.add(leftEye, rightEye);
human.add(headGroup);
// 2. गर्दन (Neck)
const neck = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.11, 0.18, 12), skinMat);
neck.position.y = 2.05;
human.add(neck);
// 3. धड़ / छाती (Torso + Tactical Vest)
const torso = new THREE.Mesh(new THREE.CylinderGeometry(0.28, 0.23, 0.85, 14), shirtMat);
torso.scale.set(1.1, 1, 0.7);
torso.position.y = 1.55;
human.add(torso);
// बुलेटप्रूफ जैकेट (Vest)
const vest = new THREE.Mesh(new THREE.CylinderGeometry(0.295, 0.25, 0.65, 14), vestMat);
vest.scale.set(1.12, 1, 0.74);
vest.position.y = 1.6;
human.add(vest);
// 4. बायाँ हाथ (Left Arm - कंधे से जुड़ा हुआ ताकि दौड़ते समय हिले)
const leftArmPivot = new THREE.Group();
leftArmPivot.position.set(-0.38, 1.9, 0);
const lShoulder = new THREE.Mesh(new THREE.SphereGeometry(0.11, 10, 10), shirtMat);
const lUpperArm = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.075, 0.45, 10), skinMat);
lUpperArm.position.y = -0.22;
const lHand = new THREE.Mesh(new THREE.SphereGeometry(0.08, 10, 10), skinMat);
lHand.position.y = -0.46;
leftArmPivot.add(lShoulder, lUpperArm, lHand);
human.add(leftArmPivot);
// 5. दायाँ हाथ + बंदूक (Right Arm holding Gun)
const rightArmPivot = new THREE.Group();
rightArmPivot.position.set(0.38, 1.9, 0);
const rShoulder = new THREE.Mesh(new THREE.SphereGeometry(0.11, 10, 10), shirtMat);
const rArm = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.075, 0.5, 10), skinMat);
rArm.rotation.x = Math.PI / 2.3; // आगे बंदूक पकड़े हुए
rArm.position.set(0, -0.1, -0.22);
// डिटेल्ड बंदूक (Rifle)
const gunGroup = new THREE.Group();
const gunBody = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.14, 0.85), new THREE.MeshStandardMaterial({ color: 0x1c1c1c, metalness: 0.7 }));
const gunBarrel = new THREE.Mesh(new THREE.CylinderGeometry(0.02, 0.02, 0.4), new THREE.MeshStandardMaterial({ color: 0x444444 }));
gunBarrel.rotation.x = Math.PI / 2;
gunBarrel.position.set(0, 0.03, -0.55);
const gunMag = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.22, 0.1), new THREE.MeshStandardMaterial({ color: 0x8d6e63 }));
gunMag.position.set(0, -0.12, -0.15);
gunMag.rotation.x = 0.25;
gunGroup.add(gunBody, gunBarrel, gunMag);
gunGroup.position.set(0, -0.15, -0.55);
rightArmPivot.add(rShoulder, rArm, gunGroup);
human.add(rightArmPivot);
// 6. बायाँ पैर (Left Leg + Shoe)
const leftLegPivot = new THREE.Group();
leftLegPivot.position.set(-0.16, 1.12, 0);
const lLeg = new THREE.Mesh(new THREE.CylinderGeometry(0.115, 0.085, 0.98, 12), pantsMat);
lLeg.position.y = -0.49;
const lShoe = new THREE.Mesh(new THREE.BoxGeometry(0.18, 0.14, 0.34), shoeMat);
lShoe.position.set(0, -1.02, -0.06);
leftLegPivot.add(lLeg, lShoe);
human.add(leftLegPivot);
// 7. दायाँ पैर (Right Leg + Shoe)
const rightLegPivot = new THREE.Group();
rightLegPivot.position.set(0.16, 1.12, 0);
const rLeg = new THREE.Mesh(new THREE.CylinderGeometry(0.115, 0.085, 0.98, 12), pantsMat);
rLeg.position.y = -0.49;
const rShoe = new THREE.Mesh(new THREE.BoxGeometry(0.18, 0.14, 0.34), shoeMat);
rShoe.position.set(0, -1.02, -0.06);
rightLegPivot.add(rLeg, rShoe);
human.add(rightLegPivot);
// पैराशूट (अगर प्लेयर है)
let parachute = null;
if (hasParachute) {
parachute = new THREE.Mesh(
new THREE.SphereGeometry(2.5, 14, 10, 0, Math.PI * 2, 0, Math.PI / 2),
new THREE.MeshStandardMaterial({ color: 0xff9800, side: THREE.DoubleSide })
);
parachute.position.y = 4.3;
human.add(parachute);
}
// एनीमेशन के लिए अंगों के रेफरेंस सेव करना
human.userData.limbs = {
leftArm: leftArmPivot,
rightArm: rightArmPivot,
leftLeg: leftLegPivot,
rightLeg: rightLegPivot,
parachute: parachute,
animTime: Math.random() * 10
};
return human;
}
// ह्यूमन चलने/दौड़ने का एनीमेशन अपडेट करना
function animateHumanLimbs(human, isMoving, speedMultiplier = 1) {
const limbs = human.userData.limbs;
if (isMoving) {
limbs.animTime += 0.16 * speedMultiplier;
const swing = Math.sin(limbs.animTime) * 0.65;
limbs.leftLeg.rotation.x = swing;
limbs.rightLeg.rotation.x = -swing;
limbs.leftArm.rotation.x = -swing * 0.8;
// दायाँ हाथ बंदूक ताने रहेगा, हल्का सा हिलेगा
limbs.rightArm.rotation.x = Math.sin(limbs.animTime * 2) * 0.04;
} else {
// खड़े होने पर सामान्य मुद्रा (Idle Breathing)
limbs.leftLeg.rotation.x *= 0.8;
limbs.rightLeg.rotation.x *= 0.8;
limbs.leftArm.rotation.x *= 0.8;
limbs.rightArm.rotation.x = 0;
}
}
// प्लेयर बनाना (नीली टी-शर्ट और काली पैंट)
const player = createHumanCharacter(0x1976D2, 0x212121, true);
player.position.set(0, 45, 0);
scene.add(player);
// गेम स्टेट वेरिएबल्स
let gameStarted = false, isGameOver = false;
let hp = 200, kills = 0, alive = 12, glooCount = 4, medCount = 3;
let yaw = 0, pitch = 0.15;
let velY = 0, isGrounded = false, isParachuting = true;
let isScoped = false, isSprinting = false;
const bullets = [], enemyBullets = [], enemies = [];
// 4. दुश्मन (Enemy Humans) बनाना
function createEnemies() {
const shirtColors = [0xc62828, 0x6a1b9a, 0x2e7d32, 0xef6c00];
for (let i = 0; i < 11; i++) {
const color = shirtColors[i % shirtColors.length];
const en = createHumanCharacter(color, 0x37474f, false);
en.position.set((Math.random() - 0.5) * 180, 0, (Math.random() - 0.5) * 180);
en.userData.hp = 100;
en.userData.lastShot = 0;
scene.add(en);
enemies.push(en);
}
}
createEnemies();
// 5. फायरिंग फंक्शन
function fireWeapon() {
if (!gameStarted || isGameOver || isParachuting) return;
playGunSound();
const bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.11, 6, 6),
new THREE.MeshBasicMaterial({ color: 0xffeb3b })
);
bullet.position.copy(player.position);
bullet.position.y += 1.75;
const dir = new THREE.Vector3(0, 0, -1);
dir.applyEuler(new THREE.Euler(-pitch * 0.45, yaw, 0, 'YXZ'));
bullet.userData.vel = dir.multiplyScalar(2.6);
scene.add(bullet);
bullets.push(bullet);
}
// 6. Gloo Wall लगाना
function deployGlooWall() {
if (!gameStarted || isGameOver || isParachuting || glooCount <= 0) return;
glooCount--;
updateHUD();
const wall = new THREE.Mesh(
new THREE.BoxGeometry(3.8, 2.6, 0.4),
new THREE.MeshStandardMaterial({ color: 0x00e5ff, transparent: true, opacity: 0.85 })
);
const forward = new THREE.Vector3(-Math.sin(yaw), 0, -Math.cos(yaw));
wall.position.copy(player.position).addScaledVector(forward, 3.2);
wall.position.y = 1.3;
wall.rotation.y = yaw;
wall.userData = { hp: 150 };
scene.add(wall);
glooWalls.push(wall);
}
// 7. कंट्रोल्स
let joyX = 0, joyY = 0;
const joyZone = document.getElementById('joystick-zone');
const joyKnob = document.getElementById('joystick-knob');
joyZone.addEventListener('touchmove', (e) => {
e.preventDefault();
const t = e.touches[0];
const r = joyZone.getBoundingClientRect();
const dx = t.clientX - (r.left + r.width / 2);
const dy = t.clientY - (r.top + r.height / 2);
const dist = Math.min(Math.hypot(dx, dy), 38);
const ang = Math.atan2(dy, dx);
joyX = Math.cos(ang) * (dist / 38);
joyY = Math.sin(ang) * (dist / 38);
joyKnob.style.transform = `translate(${Math.cos(angle) * dist}px, ${Math.sin(angle) * dist}px)`;
});
joyZone.addEventListener('touchend', () => {
joyX = 0; joyY = 0;
joyKnob.style.transform = `translate(0,0)`;
});
let lastX = 0, lastY = 0;
const lookZone = document.getElementById('look-zone');
lookZone.addEventListener('touchstart', (e) => { lastX = e.touches[0].clientX; lastY = e.touches[0].clientY; });
lookZone.addEventListener('touchmove', (e) => {
const sens = isScoped ? 0.003 : 0.007;
yaw -= (e.touches[0].clientX - lastX) * sens;
pitch = Math.max(-0.25, Math.min(0.6, pitch + (e.touches[0].clientY - lastY) * sens));
lastX = e.touches[0].clientX;
lastY = e.touches[0].clientY;
});
document.getElementById('fireBtn').addEventListener('touchstart', (e) => { e.preventDefault(); fireWeapon(); });
document.getElementById('fireBtn').addEventListener('click', fireWeapon);
document.getElementById('jumpBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
if (isGrounded) { velY = 0.36; isGrounded = false; }
});
document.getElementById('glooBtn').addEventListener('touchstart', (e) => { e.preventDefault(); deployGlooWall(); });
document.getElementById('medkitBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
if (medCount > 0 && hp < 200) {
medCount--;
hp = Math.min(200, hp + 80);
updateHUD();
}
});
document.getElementById('scopeBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
isScoped = !isScoped;
camera.fov = isScoped ? 32 : 65;
camera.updateProjectionMatrix();
document.getElementById('scope-overlay').style.display = isScoped ? 'block' : 'none';
});
document.getElementById('sprintBtn').addEventListener('touchstart', (e) => {
e.preventDefault();
isSprinting = !isSprinting;
document.getElementById('sprintBtn').style.background = isSprinting ? '#ff5722' : 'rgba(255, 152, 0, 0.7)';
});
const keys = {};
window.addEventListener('keydown', (e) => {
keys[e.key.toLowerCase()] = true;
if (e.key === ' ' && isGrounded) { velY = 0.36; isGrounded = false; }
if (e.key === 'f' || e.key === 'Enter') fireWeapon();
if (e.key === 'g') deployGlooWall();
});
window.addEventListener('keyup', (e) => keys[e.key.toLowerCase()] = false);
document.getElementById('startBtn').addEventListener('click', () => {
if (isGameOver) { location.reload(); return; }
document.getElementById('overlayScreen').style.display = 'none';
gameStarted = true;
});
function updateHUD() {
document.getElementById('hp-val').innerText = Math.max(0, Math.round(hp));
document.getElementById('hp-bar').style.width = (Math.max(0, hp) / 200 * 100) + '%';
document.getElementById('kills-val').innerText = kills;
document.getElementById('alive-val').innerText = alive;
document.getElementById('gloo-val').innerText = glooCount;
document.getElementById('med-val').innerText = medCount;
}
function finishGame(isBooyah) {
isGameOver = true;
document.getElementById('screenTitle').innerText = isBooyah ? "🏆 BOOYAH! #1" : "ELIMINATED!";
document.getElementById('screenSub').innerText = `कुल किल्स (Kills): ${kills}`;
document.getElementById('startBtn').innerText = "PLAY AGAIN";
document.getElementById('overlayScreen').style.display = 'flex';
}
// 8. मेन गेम लूप
let lastZoneDamageTime = 0;
function animate(time) {
requestAnimationFrame(animate);
if (!gameStarted || isGameOver) {
renderer.render(scene, camera);
return;
}
if (isParachuting) {
player.position.y -= 0.25;
if (player.position.y <= 0) {
player.position.y = 0;
isParachuting = false;
isGrounded = true;
if (player.userData.limbs.parachute) player.userData.limbs.parachute.visible = false;
}
} else {
player.position.y += velY;
if (player.position.y > 0) velY -= 0.02;
else { player.position.y = 0; velY = 0; isGrounded = true; }
}
let mx = joyX, mz = joyY;
if (keys['w']) mz = -1;
if (keys['s']) mz = 1;
if (keys['a']) mx = -1;
if (keys['d']) mx = 1;
if (keys['q']) yaw += 0.04;
if (keys['e']) yaw -= 0.04;
player.rotation.y = yaw;
const moveSpeed = isSprinting ? 0.38 : 0.24;
const forward = new THREE.Vector3(-Math.sin(yaw), 0, -Math.cos(yaw));
const right = new THREE.Vector3(Math.cos(yaw), 0, -Math.sin(yaw));
player.position.addScaledVector(forward, -mz * moveSpeed);
player.position.addScaledVector(right, mx * moveSpeed);
// प्लेयर के हाथ-पैर का एनीमेशन
const isPlayerMoving = Math.hypot(mx, mz) > 0.05 && !isParachuting;
animateHumanLimbs(player, isPlayerMoving, isSprinting ? 1.5 : 1.0);
const camOffset = isScoped ? new THREE.Vector3(0.45, 2.35, 1.2) : new THREE.Vector3(0.85, 3.1 + pitch * 3, 5.4);
camOffset.applyAxisAngle(new THREE.Vector3(0, 1, 0), yaw);
camera.position.copy(player.position).add(camOffset);
camera.lookAt(player.position.x, player.position.y + 1.85, player.position.z);
// सेफ ज़ोन
if (zoneRadius > 20) {
zoneRadius -= 0.012;
safeZoneMesh.scale.set(zoneRadius / 140, 1, zoneRadius / 140);
document.getElementById('zone-rad').innerText = Math.round(zoneRadius);
}
const distFromCenter = Math.hypot(player.position.x, player.position.z);
if (distFromCenter > zoneRadius) {
document.getElementById('zone-alert').style.display = 'block';
if (time - lastZoneDamageTime > 1000) {
lastZoneDamageTime = time;
hp -= 8;
updateHUD();
if (hp <= 0) finishGame(false);
}
} else {
document.getElementById('zone-alert').style.display = 'none';
}
// प्लेयर की गोलियाँ
for (let i = bullets.length - 1; i >= 0; i--) {
const b = bullets[i];
b.position.add(b.userData.vel);
if (b.position.distanceTo(player.position) > 150) {
scene.remove(b); bullets.splice(i, 1); continue;
}
for (let j = enemies.length - 1; j >= 0; j--) {
const en = enemies[j];
if (Math.hypot(b.position.x - en.position.x, b.position.z - en.position.z) < 0.85 && b.position.y < 2.7) {
const isHeadshot = b.position.y > 2.05;
en.userData.hp -= isHeadshot ? 100 : 35;
scene.remove(b); bullets.splice(i, 1);
if (en.userData.hp <= 0) {
scene.remove(en); enemies.splice(j, 1);
kills++; alive--;
updateHUD();
if (alive <= 1) finishGame(true);
}
break;
}
}
}
// दुश्मनों का AI और एनीमेशन
enemies.forEach(en => {
en.lookAt(player.position.x, 0, player.position.z);
const dist = en.position.distanceTo(player.position);
let enemyMoving = false;
if (dist > 14 && dist < 95 && !isParachuting) {
en.translateZ(0.09);
enemyMoving = true;
}
animateHumanLimbs(en, enemyMoving, 0.9);
if (dist < 60 && !isParachuting && time - en.userData.lastShot > 2000) {
en.userData.lastShot = time;
const eb = new THREE.Mesh(new THREE.SphereGeometry(0.14), new THREE.MeshBasicMaterial({ color: 0xff1744 }));
eb.position.copy(en.position);
eb.position.y += 1.65;
eb.userData.vel = new THREE.Vector3().subVectors(player.position, en.position).normalize().multiplyScalar(1.0);
scene.add(eb);
enemyBullets.push(eb);
}
});
// दुश्मन की गोलियाँ
for (let i = enemyBullets.length - 1; i >= 0; i--) {
const eb = enemyBullets[i];
eb.position.add(eb.userData.vel);
let hitWall = false;
for (let w = glooWalls.length - 1; w >= 0; w--) {
if (eb.position.distanceTo(glooWalls[w].position) < 2.1) {
glooWalls[w].userData.hp -= 25;
if (glooWalls[w].userData.hp <= 0) {
scene.remove(glooWalls[w]); glooWalls.splice(w, 1);
}
hitWall = true; break;
}
}
if (hitWall) { scene.remove(eb); enemyBullets.splice(i, 1); continue; }
if (eb.position.distanceTo(player.position) < 1.2) {
hp -= 14;
updateHUD();
scene.remove(eb); enemyBullets.splice(i, 1);
if (hp <= 0) finishGame(false);
} else if (eb.position.distanceTo(player.position) > 120) {
scene.remove(eb); enemyBullets.splice(i, 1);
}
}
renderer.render(scene, camera);
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate(0);
</script>
</body>
</html>
2
2
149KB
620KB
1,219.0ms
200.0ms
1,219.0ms