maze-runner-mayhem / script.js
Xnix677's picture
Problema:
8d4ed97 verified
Raw
History Blame Contribute Delete
13.6 kB
// Main game script
document.addEventListener('DOMContentLoaded', () => {
// Game variables
let scene, camera, renderer, controls;
let player, enemies = [], mazeWalls = [], exit;
let moveDirection = { forward: 0, backward: 0, left: 0, right: 0 };
let isGameOver = false;
let gameStarted = false;
let playerSpeed = 0.1;
let enemySpeed = 0.08;
let mazeSize = 15;
let cellSize = 3;
let wallHeight = 2;
// Initialize game
init();
createMaze();
createPlayer();
createEnemies(3);
createExit();
setupControls();
animate();
// Event listeners
document.getElementById('restart-btn').addEventListener('click', restartGame);
document.getElementById('next-level-btn').addEventListener('click', nextLevel);
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 10, 15);
camera.lookAt(0, 0, 0);
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.getElementById('game-container').appendChild(renderer.domElement);
// Add lights
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1);
directionalLight.castShadow = true;
scene.add(directionalLight);
// Add fog
scene.fog = new THREE.FogExp2(0x111111, 0.05);
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
}
function createMaze() {
// Simple maze generation - in a real game you'd implement a proper maze algorithm
const wallGeometry = new THREE.BoxGeometry(cellSize, wallHeight, 0.2);
const wallMaterial = new THREE.MeshStandardMaterial({ color: 0x880000 });
// Create outer walls
const outerWalls = [];
const outerSize = mazeSize * cellSize;
// Floor
const floorGeometry = new THREE.PlaneGeometry(outerSize, outerSize);
const floorMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
const floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
// Ceiling
const ceiling = new THREE.Mesh(floorGeometry, floorMaterial);
ceiling.rotation.x = Math.PI / 2;
ceiling.position.y = wallHeight;
scene.add(ceiling);
// Inner maze walls (simplified)
for (let i = 0; i < mazeSize - 1; i++) {
for (let j = 0; j < mazeSize - 1; j++) {
if (Math.random() > 0.7) {
const wall = new THREE.Mesh(wallGeometry, wallMaterial);
wall.position.set(
(i - mazeSize/2) * cellSize + cellSize/2,
wallHeight/2,
(j - mazeSize/2) * cellSize + cellSize/2
);
wall.castShadow = true;
wall.receiveShadow = true;
scene.add(wall);
mazeWalls.push(wall);
// Randomly rotate some walls
if (Math.random() > 0.5) {
wall.rotation.y = Math.PI / 2;
}
}
}
}
}
function createPlayer() {
const geometry = new THREE.CylinderGeometry(0.5, 0.5, 1.8, 16);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
player = new THREE.Mesh(geometry, material);
player.position.set(0, 1, 0);
player.castShadow = true;
player.receiveShadow = true;
scene.add(player);
// Add a small directional light to the player to make them stand out
const playerLight = new THREE.PointLight(0x00ff00, 1, 5);
player.add(playerLight);
}
function createEnemies(count) {
const geometry = new THREE.CylinderGeometry(0.5, 0.5, 1.8, 16);
const material = new THREE.MeshStandardMaterial({ color: 0xff0000 });
for (let i = 0; i < count; i++) {
const enemy = new THREE.Mesh(geometry, material);
// Position enemies at random locations in the maze
enemy.position.set(
(Math.random() - 0.5) * mazeSize * cellSize * 0.8,
1,
(Math.random() - 0.5) * mazeSize * cellSize * 0.8
);
enemy.castShadow = true;
enemy.receiveShadow = true;
// Add red glow
const enemyLight = new THREE.PointLight(0xff0000, 1, 5);
enemy.add(enemyLight);
scene.add(enemy);
enemies.push(enemy);
}
}
function createExit() {
const exitGeometry = new THREE.BoxGeometry(cellSize, 0.1, cellSize);
const exitMaterial = new THREE.MeshStandardMaterial({ color: 0xffff00 });
exit = new THREE.Mesh(exitGeometry, exitMaterial);
// Position exit at a random edge of the maze
const side = Math.floor(Math.random() * 4);
let x, z;
switch(side) {
case 0: // top
x = (Math.random() - 0.5) * mazeSize * cellSize * 0.8;
z = -mazeSize * cellSize / 2;
break;
case 1: // right
x = mazeSize * cellSize / 2;
z = (Math.random() - 0.5) * mazeSize * cellSize * 0.8;
break;
case 2: // bottom
x = (Math.random() - 0.5) * mazeSize * cellSize * 0.8;
z = mazeSize * cellSize / 2;
break;
case 3: // left
x = -mazeSize * cellSize / 2;
z = (Math.random() - 0.5) * mazeSize * cellSize * 0.8;
break;
}
exit.position.set(x, 0.05, z);
scene.add(exit);
}
function setupControls() {
const forwardBtn = document.getElementById('forward-btn');
const backwardBtn = document.getElementById('backward-btn');
const leftBtn = document.getElementById('left-btn');
const rightBtn = document.getElementById('right-btn');
// Touch start events
forwardBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
moveDirection.forward = 1;
gameStarted = true;
});
backwardBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
moveDirection.backward = 1;
gameStarted = true;
});
leftBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
moveDirection.left = 1;
gameStarted = true;
});
rightBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
moveDirection.right = 1;
gameStarted = true;
});
// Touch end events
forwardBtn.addEventListener('touchend', (e) => {
e.preventDefault();
moveDirection.forward = 0;
});
backwardBtn.addEventListener('touchend', (e) => {
e.preventDefault();
moveDirection.backward = 0;
});
leftBtn.addEventListener('touchend', (e) => {
e.preventDefault();
moveDirection.left = 0;
});
rightBtn.addEventListener('touchend', (e) => {
e.preventDefault();
moveDirection.right = 0;
});
}
function update() {
if (!gameStarted || isGameOver) return;
// Player movement
const moveForward = moveDirection.forward - moveDirection.backward;
const moveSideways = moveDirection.right - moveDirection.left;
// Apply movement
const speed = playerSpeed;
player.position.x -= Math.sin(player.rotation.y) * moveForward * speed;
player.position.z -= Math.cos(player.rotation.y) * moveForward * speed;
// Apply rotation
player.rotation.y -= moveSideways * speed * 0.5;
// Simple collision detection with walls
const playerRadius = 0.5;
for (const wall of mazeWalls) {
const wallBox = new THREE.Box3().setFromObject(wall);
const playerBox = new THREE.Box3(
new THREE.Vector3(player.position.x - playerRadius, 0, player.position.z - playerRadius),
new THREE.Vector3(player.position.x + playerRadius, 2, player.position.z + playerRadius)
);
if (wallBox.intersectsBox(playerBox)) {
// Push player back
player.position.x -= moveDirection.x * speed * 2;
player.position.z -= moveDirection.z * speed * 2;
break;
}
}
// Enemy movement
for (const enemy of enemies) {
// Simple AI: move toward player
const direction = new THREE.Vector3(
player.position.x - enemy.position.x,
0,
player.position.z - enemy.position.z
).normalize();
enemy.position.x += direction.x * enemySpeed;
enemy.position.z += direction.z * enemySpeed;
// Simple collision detection between enemies and walls
const enemyRadius = 0.5;
for (const wall of mazeWalls) {
const wallBox = new THREE.Box3().setFromObject(wall);
const enemyBox = new THREE.Box3(
new THREE.Vector3(enemy.position.x - enemyRadius, 0, enemy.position.z - enemyRadius),
new THREE.Vector3(enemy.position.x + enemyRadius, 2, enemy.position.z + enemyRadius)
);
if (wallBox.intersectsBox(enemyBox)) {
// Push enemy back
enemy.position.x -= direction.x * enemySpeed * 2;
enemy.position.z -= direction.z * enemySpeed * 2;
break;
}
}
// Check for collision with player
const distanceToPlayer = Math.sqrt(
Math.pow(player.position.x - enemy.position.x, 2) +
Math.pow(player.position.z - enemy.position.z, 2)
);
if (distanceToPlayer < 1) {
gameOver();
}
}
// Check if player reached exit
const exitBox = new THREE.Box3().setFromObject(exit);
const playerBox = new THREE.Box3(
new THREE.Vector3(player.position.x - 0.5, 0, player.position.z - 0.5),
new THREE.Vector3(player.position.x + 0.5, 2, player.position.z + 0.5)
);
if (exitBox.intersectsBox(playerBox)) {
winGame();
}
// Update camera position to follow player
camera.position.x = player.position.x;
camera.position.z = player.position.z + 5;
camera.lookAt(player.position.x, player.position.y, player.position.z);
}
function gameOver() {
isGameOver = true;
document.getElementById('game-over').classList.remove('hidden');
}
function winGame() {
isGameOver = true;
document.getElementById('win-screen').classList.remove('hidden');
}
function restartGame() {
// Reset player and enemies
player.position.set(0, 1, 0);
enemies.forEach(enemy => {
enemy.position.set(
(Math.random() - 0.5) * mazeSize * cellSize * 0.8,
1,
(Math.random() - 0.5) * mazeSize * cellSize * 0.8
);
});
// Reset UI
document.getElementById('game-over').classList.add('hidden');
document.getElementById('win-screen').classList.add('hidden');
isGameOver = false;
gameStarted = false;
}
function nextLevel() {
// Clear current maze and enemies
mazeWalls.forEach(wall => scene.remove(wall));
mazeWalls = [];
enemies.forEach(enemy => scene.remove(enemy));
enemies = [];
scene.remove(exit);
// Increase difficulty
mazeSize += 2;
enemySpeed += 0.01;
// Create new level
createMaze();
createEnemies(3 + Math.floor(mazeSize / 5));
createExit();
// Reset player
player.position.set(0, 1, 0);
// Reset UI
document.getElementById('win-screen').classList.add('hidden');
isGameOver = false;
gameStarted = false;
}
function animate() {
requestAnimationFrame(animate);
update();
renderer.render(scene, camera);
}
});