Meta Description" name="description" />
<!DOCTYPE html>
<html>
<head>
<title>Mini Battle Royale 3D</title>
<style>
body { margin:0; overflow:hidden; font-family:Arial; }
#hud {
position:absolute;
top:10px;
left:10px;
color:white;
background:rgba(0,0,0,0.5);
padding:10px;
}
</style>
</head>
<body>
<div id="hud">
Health: <span id="health">100</span><br>
Enemies: <span id="enemyCount">0</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.158/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.158/examples/js/controls/PointerLockControls.js"></script>
<script>
// --- setup ---
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87ceeb);
const camera = new THREE.PerspectiveCamera(75,innerWidth/innerHeight,0.1,1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth,innerHeight);
document.body.appendChild(renderer.domElement);
// lighting
scene.add(new THREE.HemisphereLight(0xffffff,0x444444,1));
// ground
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(400,400),
new THREE.MeshStandardMaterial({color:0x2e8b57})
);
ground.rotation.x = -Math.PI/2;
scene.add(ground);
// buildings
for(let i=0;i<20;i++){
const b = new THREE.Mesh(
new THREE.BoxGeometry(5,Math.random()*10+5,5),
new THREE.MeshStandardMaterial({color:0x888888})
);
b.position.set((Math.random()-0.5)*200,b.scale.y/2,(Math.random()-0.5)*200);
scene.add(b);
}
// controls
const controls = new THREE.PointerLockControls(camera,document.body);
document.body.addEventListener("click",()=>controls.lock());
scene.add(controls.getObject());
// input
let keys={};
addEventListener("keydown",e=>keys[e.code]=true);
addEventListener("keyup",e=>keys[e.code]=false);
// player
let playerHealth=100;
const healthUI=document.getElementById("health");
const enemyUI=document.getElementById("enemyCount");
// bullets
const bullets=[];
const enemyBullets=[];
// enemies
const enemies=[];
function spawnEnemy(){
const e = new THREE.Mesh(
new THREE.BoxGeometry(1,2,1),
new THREE.MeshStandardMaterial({color:0xff0000})
);
e.position.set((Math.random()-0.5)*150,1,(Math.random()-0.5)*150);
e.health=3;
e.cooldown=0;
scene.add(e);
enemies.push(e);
}
for(let i=0;i<8;i++) spawnEnemy();
// shooting
addEventListener("mousedown",()=>{
if(!controls.isLocked) return;
const bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.1),
new THREE.MeshBasicMaterial({color:0xffff00})
);
bullet.position.copy(camera.position);
const dir=new THREE.Vector3();
camera.getWorldDirection(dir);
bullet.velocity=dir.multiplyScalar(2);
scene.add(bullet);
bullets.push(bullet);
});
// enemy shooting
function enemyShoot(enemy){
const b = new THREE.Mesh(
new THREE.SphereGeometry(0.15),
new THREE.MeshBasicMaterial({color:0xffaa00})
);
b.position.copy(enemy.position);
const dir = camera.position.clone().sub(enemy.position).normalize();
b.velocity=dir.multiplyScalar(0.6);
scene.add(b);
enemyBullets.push(b);
}
// movement
const velocity=new THREE.Vector3();
// game loop
function animate(){
requestAnimationFrame(animate);
velocity.set(0,0,0);
if(keys["KeyW"]) velocity.z-=0.3;
if(keys["KeyS"]) velocity.z+=0.3;
if(keys["KeyA"]) velocity.x-=0.3;
if(keys["KeyD"]) velocity.x+=0.3;
controls.moveRight(velocity.x);
controls.moveForward(velocity.z);
// update bullets
for(let i=bullets.length-1;i>=0;i--){
const b=bullets[i];
b.position.add(b.velocity);
for(let j=enemies.length-1;j>=0;j--){
const e=enemies[j];
if(b.position.distanceTo(e.position)<1){
e.health--;
scene.remove(b);
bullets.splice(i,1);
if(e.health<=0){
scene.remove(e);
enemies.splice(j,1);
}
break;
}
}
}
// enemy AI
enemies.forEach(e=>{
const dir=camera.position.clone().sub(e.position).normalize();
e.position.add(dir.multiplyScalar(0.03));
e.cooldown--;
if(e.cooldown<=0){
enemyShoot(e);
e.cooldown=120;
}
});
// enemy bullets
for(let i=enemyBullets.length-1;i>=0;i--){
const b=enemyBullets[i];
b.position.add(b.velocity);
if(b.position.distanceTo(camera.position)<1){
playerHealth-=5;
healthUI.textContent=playerHealth;
scene.remove(b);
enemyBullets.splice(i,1);
if(playerHealth<=0){
alert("You died!");
location.reload();
}
}
}
// UI
enemyUI.textContent=enemies.length;
renderer.render(scene,camera);
}
animate();
</script>
</body>
</html>3
2
163KB
641KB
585.0ms
116.0ms
585.0ms