Zombie Survival 3D
by LaserTiger28781 lines13.2 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zombie Survival 3D</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
overflow: hidden;
background: #000;
font-family: Arial, sans-serif;
}
#hud {
position: fixed;
top: 15px;
left: 15px;
color: white;
font-size: 20px;
z-index: 10;
text-shadow: 2px 2px 4px #000;
}
#menu {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(0,0,0,.8);
color: white;
z-index: 20;
text-align: center;
}
#menu h1 {
font-size: 50px;
margin-bottom: 10px;
}
button {
padding: 15px 30px;
font-size: 20px;
border: none;
border-radius: 10px;
cursor: pointer;
background: #2ecc71;
color: white;
}
#crosshair {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 25px;
z-index: 5;
pointer-events: none;
}
#message {
position: fixed;
bottom: 25px;
left: 50%;
transform: translateX(-50%);
color: white;
font-size: 18px;
z-index: 10;
text-align: center;
}
</style>
</head>
<body>
<div id="menu">
<h1>🧟 ZOMBIE SURVIVAL 3D</h1>
<p>Sobreviva o máximo que conseguir!</p>
<p>WASD = andar | Mouse = olhar</p>
<p>Corra dos zumbis e encontre os itens!</p>
<button onclick="startGame()">COMEÇAR</button>
</div>
<div id="hud">
❤️ Vida: <span id="health">100</span><br>
⭐ Pontos: <span id="score">0</span><br>
⏱️ Tempo: <span id="time">0</span><br>
🧟 Zumbis: <span id="zombies">0</span>
</div>
<div id="crosshair">+</div>
<div id="message">
Encontre os itens verdes para ganhar pontos!
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.161.0/three.min.js"></script>
<script>
let scene, camera, renderer;
let player;
let zombies = [];
let items = [];
let health = 100;
let score = 0;
let gameTime = 0;
let gameStarted = false;
let keys = {};
const clock = new THREE.Clock();
// ==========================
// INICIAR JOGO
// ==========================
function startGame() {
document.getElementById("menu").style.display = "none";
gameStarted = true;
health = 100;
score = 0;
gameTime = 0;
init();
document.body.requestPointerLock();
animate();
}
// ==========================
// CRIAR CENA
// ==========================
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x101820);
scene.fog = new THREE.Fog(
0x101820,
20,
180
);
// CÂMERA
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
500
);
camera.position.set(
0,
2,
10
);
// RENDERIZADOR
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(
window.innerWidth,
window.innerHeight
);
renderer.shadowMap.enabled = true;
document.body.appendChild(
renderer.domElement
);
// LUZ
const ambient = new THREE.AmbientLight(
0xffffff,
0.45
);
scene.add(ambient);
const moon = new THREE.DirectionalLight(
0xffffff,
1
);
moon.position.set(
30,
50,
20
);
moon.castShadow = true;
scene.add(moon);
// CHÃO
const floorGeometry =
new THREE.PlaneGeometry(
300,
300
);
const floorMaterial =
new THREE.MeshStandardMaterial({
color: 0x263238
});
const floor =
new THREE.Mesh(
floorGeometry,
floorMaterial
);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
// ESTRADA
const roadGeometry =
new THREE.PlaneGeometry(
18,
300
);
const roadMaterial =
new THREE.MeshStandardMaterial({
color: 0x151515
});
const road =
new THREE.Mesh(
roadGeometry,
roadMaterial
);
road.rotation.x = -Math.PI / 2;
road.position.y = 0.01;
scene.add(road);
// ÁRVORES
for (let i = 0; i < 100; i++) {
createTree();
}
// CASAS
for (let i = 0; i < 20; i++) {
createHouse();
}
// JOGADOR
const playerGeometry =
new THREE.BoxGeometry(
1,
2,
1
);
const playerMaterial =
new THREE.MeshStandardMaterial({
color: 0x3498db
});
player =
new THREE.Mesh(
playerGeometry,
playerMaterial
);
player.position.set(
0,
1,
10
);
player.castShadow = true;
scene.add(player);
// ITENS
for (let i = 0; i < 20; i++) {
createItem();
}
// ZUMBIS
for (let i = 0; i < 8; i++) {
createZombie();
}
// CONTROLES
document.addEventListener(
"keydown",
e => {
keys[e.key.toLowerCase()] = true;
}
);
document.addEventListener(
"keyup",
e => {
keys[e.key.toLowerCase()] = false;
}
);
document.addEventListener(
"mousemove",
mouseLook
);
window.addEventListener(
"resize",
resize
);
}
// ==========================
// ÁRVORE
// ==========================
function createTree() {
const trunk =
new THREE.Mesh(
new THREE.CylinderGeometry(
0.4,
0.6,
4
),
new THREE.MeshStandardMaterial({
color: 0x5d4037
})
);
const leaves =
new THREE.Mesh(
new THREE.SphereGeometry(
2.2,
8,
8
),
new THREE.MeshStandardMaterial({
color: 0x1b5e20
})
);
const x =
(Math.random() - .5) * 250;
const z =
(Math.random() - .5) * 250;
trunk.position.set(
x,
2,
z
);
leaves.position.set(
x,
5,
z
);
trunk.castShadow = true;
leaves.castShadow = true;
scene.add(trunk);
scene.add(leaves);
}
// ==========================
// CASA
// ==========================
function createHouse() {
const house =
new THREE.Mesh(
new THREE.BoxGeometry(
8,
5,
8
),
new THREE.MeshStandardMaterial({
color: 0x546e7a
})
);
house.position.set(
(Math.random() - .5) * 220,
2.5,
(Math.random() - .5) * 220
);
house.castShadow = true;
scene.add(house);
}
// ==========================
// ITEM
// ==========================
function createItem() {
const item =
new THREE.Mesh(
new THREE.BoxGeometry(
0.8,
0.8,
0.8
),
new THREE.MeshStandardMaterial({
color: 0x00ff66,
emissive: 0x003311
})
);
item.position.set(
(Math.random() - .5) * 180,
0.5,
(Math.random() - .5) * 180
);
scene.add(item);
items.push(item);
}
// ==========================
// ZUMBI
// ==========================
function createZombie() {
const zombie =
new THREE.Mesh(
new THREE.BoxGeometry(
1.2,
2.2,
1.2
),
new THREE.MeshStandardMaterial({
color: 0x7cb342
})
);
zombie.position.set(
(Math.random() - .5) * 180,
1.1,
(Math.random() - .5) * 180
);
zombie.speed =
0.015 + Math.random() * 0.02;
zombie.castShadow = true;
scene.add(zombie);
zombies.push(zombie);
}
// ==========================
// MOVIMENTO
// ==========================
function updatePlayer() {
if (!player) return;
let speed = 0.12;
if (keys["shift"]) {
speed = 0.2;
}
if (keys["w"] || keys["arrowup"]) {
player.position.z -= speed;
}
if (keys["s"] || keys["arrowdown"]) {
player.position.z += speed;
}
if (keys["a"] || keys["arrowleft"]) {
player.position.x -= speed;
}
if (keys["d"] || keys["arrowright"]) {
player.position.x += speed;
}
camera.position.x =
player.position.x;
camera.position.y =
player.position.y + 1;
camera.position.z =
player.position.z + 5;
}
// ==========================
// ZUMBIS SEGUEM O JOGADOR
// ==========================
function updateZombies() {
zombies.forEach(zombie => {
const direction =
new THREE.Vector3()
.subVectors(
player.position,
zombie.position
)
.normalize();
zombie.position.x +=
direction.x * zombie.speed;
zombie.position.z +=
direction.z * zombie.speed;
const distance =
zombie.position.distanceTo(
player.position
);
if (distance < 1.8) {
health -= 0.15;
if (health <= 0) {
gameOver();
}
}
});
}
// ==========================
// PEGAR ITENS
// ==========================
function updateItems() {
for (
let i = items.length - 1;
i >= 0;
i--
) {
const item = items[i];
const distance =
item.position.distanceTo(
player.position
);
if (distance < 2) {
score += 10;
scene.remove(item);
items.splice(i, 1);
createItem();
}
}
}
// ==========================
// MOUSE
// ==========================
let rotationY = 0;
function mouseLook(event) {
if (!gameStarted) return;
rotationY -=
event.movementX * 0.002;
camera.rotation.y =
rotationY;
}
// ==========================
// TEMPO
// ==========================
function updateGame() {
gameTime +=
clock.getDelta();
// A cada 15 segundos aparece um novo zumbi
if (
Math.floor(gameTime) % 15 === 0 &&
zombies.length < 40
) {
if (
Math.random() < 0.03
) {
createZombie();
}
}
document.getElementById(
"health"
).textContent =
Math.max(
0,
Math.floor(health)
);
document.getElementById(
"score"
).textContent =
score;
document.getElementById(
"time"
).textContent =
Math.floor(gameTime);
document.getElementById(
"zombies"
).textContent =
zombies.length;
}
// ==========================
// GAME OVER
// ==========================
function gameOver() {
gameStarted = false;
document.exitPointerLock();
document.getElementById(
"menu"
).style.display = "flex";
document.querySelector(
"#menu h1"
).textContent =
"GAME OVER";
document.querySelector(
"#menu p"
).textContent =
"Pontuação: " + score;
document.querySelector(
"#menu button"
).textContent =
"JOGAR NOVAMENTE";
}
// ==========================
// RESIZE
// ==========================
function resize() {
camera.aspect =
window.innerWidth /
window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(
window.innerWidth,
window.innerHeight
);
}
// ==========================
// LOOP
// ==========================
function animate() {
if (!gameStarted) return;
requestAnimationFrame(
animate
);
updatePlayer();
updateZombies();
updateItems();
updateGame();
renderer.render(
scene,
camera
);
}
</script>
</body>
</html>Game Source: Zombie Survival 3D
Creator: LaserTiger28
Libraries: three
Complexity: complex (781 lines, 13.2 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: zombie-survival-3d-lasertiger28" to link back to the original. Then publish at arcadelab.ai/publish.