3D FPS Zombie Game
by PlasmaHero19200 lines4.6 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3D FPS Zombie Game</title>
<style>
body { margin:0; overflow:hidden; font-family:Arial; }
#hud {
position:absolute; top:10px; left:10px;
color:white; z-index:10;
}
#hpBar {
width:200px; height:20px;
background:red;
}
#hp {
height:100%; width:100%;
background:lime;
}
#msg {
position:absolute;
top:50%; left:50%;
transform:translate(-50%,-50%);
color:white;
font-size:24px;
}
</style>
</head>
<body>
<div id="hud">
❤️ HP
<div id="hpBar"><div id="hp"></div></div>
🔫 Ammo: <span id="ammo">12</span>/12
</div>
<div id="msg">Click to Play</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.y = 2;
let move = {forward:false,back:false,left:false,right:false};
let velocity = new THREE.Vector3();
let hp = 100;
let ammo = 12;
let reloading = false;
let zombies = [];
let bullets = [];
function createCity(){
for(let i=0;i<50;i++){
let box = new THREE.Mesh(
new THREE.BoxGeometry(2,Math.random()*10+2,2),
new THREE.MeshBasicMaterial({color:0x555555})
);
box.position.set(
(Math.random()-0.5)*100,
box.geometry.parameters.height/2,
(Math.random()-0.5)*100
);
scene.add(box);
}
}
function createZombie(x,z){
let zmb = new THREE.Mesh(
new THREE.BoxGeometry(1,2,1),
new THREE.MeshBasicMaterial({color:0x00ff00})
);
zmb.position.set(x,1,z);
scene.add(zmb);
zombies.push(zmb);
}
for(let i=0;i<5;i++){
createZombie((Math.random()-0.5)*50, (Math.random()-0.5)*50);
}
createCity();
let pointerLocked = false;
document.body.onclick = () => {
document.body.requestPointerLock();
document.getElementById("msg").style.display="none";
};
document.addEventListener("mousemove", (e)=>{
if(document.pointerLockElement === document.body){
camera.rotation.y -= e.movementX * 0.002;
camera.rotation.x -= e.movementY * 0.002;
}
});
document.addEventListener("keydown", (e)=>{
if(e.key=="w") move.forward=true;
if(e.key=="s") move.back=true;
if(e.key=="a") move.left=true;
if(e.key=="d") move.right=true;
});
document.addEventListener("keyup", (e)=>{
if(e.key=="w") move.forward=false;
if(e.key=="s") move.back=false;
if(e.key=="a") move.left=false;
if(e.key=="d") move.right=false;
});
function shoot(){
if(reloading) return;
if(ammo<=0) return;
ammo--;
document.getElementById("ammo").innerText = ammo;
let ray = new THREE.Raycaster();
ray.setFromCamera({x:0,y:0}, camera);
let hit = ray.intersectObjects(zombies);
if(hit.length>0){
let z = hit[0].object;
scene.remove(z);
zombies = zombies.filter(x=>x!==z);
// spawn 2 zombies after 1 min
setTimeout(()=>{
createZombie(Math.random()*50-25, Math.random()*50-25);
createZombie(Math.random()*50-25, Math.random()*50-25);
},60000);
}
if(ammo==0){
reloading = true;
setTimeout(()=>{
ammo = 12;
document.getElementById("ammo").innerText = ammo;
reloading = false;
},2000);
}
}
document.addEventListener("click", shoot);
function damagePlayer(){
hp -= 0.1;
document.getElementById("hp").style.width = hp+"%";
if(hp<=0){
alert("Game Over");
location.reload();
}
}
function animate(){
requestAnimationFrame(animate);
let speed = 0.2;
if(move.forward) camera.position.z -= Math.cos(camera.rotation.y)*speed;
if(move.forward) camera.position.x -= Math.sin(camera.rotation.y)*speed;
if(move.back) camera.position.z += Math.cos(camera.rotation.y)*speed;
if(move.back) camera.position.x += Math.sin(camera.rotation.y)*speed;
if(move.left) camera.position.x -= Math.cos(camera.rotation.y)*speed;
if(move.right) camera.position.x += Math.cos(camera.rotation.y)*speed;
zombies.forEach(z=>{
z.position.lerp(camera.position, 0.005);
let dist = z.position.distanceTo(camera.position);
if(dist<2){
damagePlayer();
}
});
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: 3D FPS Zombie Game
Creator: PlasmaHero19
Libraries: three
Complexity: complex (200 lines, 4.6 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: 3d-fps-zombie-game-plasmahero19" to link back to the original. Then publish at arcadelab.ai/publish.