awacke1's picture
Update index.html
c2de2b4 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Pac-Man Game</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: Arial, sans-serif;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 16px;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
}
#gameOverScreen {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
border-radius: 10px;
text-align: center;
display: none;
}
#gameOverScreen button {
margin-top: 20px;
padding: 10px 20px;
background-color: yellow;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}
#instructions {
position: absolute;
bottom: 10px;
left: 10px;
color: white;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="info">Score: <span id="score">0</span> | Dots Left: <span id="dotsLeft">0</span></div>
<div id="instructions">Controls: Arrow Keys to move, WASD to rotate camera, Q/E to raise/lower camera</div>
<div id="gameOverScreen">
<h2>Game Over</h2>
<p>Your final score: <span id="finalScore">0</span></p>
<button id="restartButton">Play Again</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Game variables
let scene, camera, renderer, player, maze = [];
let score = 0, dotsLeft = 0;
let gameOver = false;
let cameraOffset = { x: 0, y: 5, z: 10 };
let cameraRotation = { x: -0.5, y: 0, z: 0 };
// Maze layout (1: wall, 2: dot, 0: empty space)
const map = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1],
[1,2,1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,2,1],
[1,2,1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,2,1],
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
[1,2,1,1,2,1,2,1,1,1,1,1,2,1,2,1,1,2,1],
[1,2,2,2,2,1,2,2,2,1,2,2,2,1,2,2,2,2,1],
[1,1,1,1,2,1,1,1,0,1,0,1,1,1,2,1,1,1,1],
[0,0,0,1,2,1,0,0,0,0,0,0,0,1,2,1,0,0,0],
[1,1,1,1,2,1,0,1,1,0,1,1,0,1,2,1,1,1,1],
[0,0,0,0,2,0,0,1,0,0,0,1,0,0,2,0,0,0,0],
[1,1,1,1,2,1,0,1,1,1,1,1,0,1,2,1,1,1,1],
[0,0,0,1,2,1,0,0,0,0,0,0,0,1,2,1,0,0,0],
[1,1,1,1,2,1,0,1,1,1,1,1,0,1,2,1,1,1,1],
[1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1],
[1,2,1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,2,1],
[1,2,2,1,2,2,2,2,2,0,2,2,2,2,2,1,2,2,1],
[1,1,2,1,2,1,2,1,1,1,1,1,2,1,2,1,2,1,1],
[1,2,2,2,2,1,2,2,2,1,2,2,2,1,2,2,2,2,1],
[1,2,1,1,1,1,1,1,2,1,2,1,1,1,1,1,1,2,1],
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
// Initialize the game
function init() {
// Reset game variables
score = 0;
document.getElementById('score').textContent = score;
gameOver = false;
document.getElementById('gameOverScreen').style.display = 'none';
maze = [];
dotsLeft = 0;
// Create a scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
// Create a camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(cameraOffset.x, cameraOffset.y, cameraOffset.z);
camera.rotation.x = cameraRotation.x;
// Create a renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
if (document.querySelector('canvas')) {
document.body.removeChild(document.querySelector('canvas'));
}
document.body.appendChild(renderer.domElement);
// Add lights
const ambientLight = new THREE.AmbientLight(0x404040, 1);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(0, 20, 10);
scene.add(directionalLight);
// Create the maze
createMaze();
// Create player (Pac-Man)
createPlayer();
// Add event listeners
window.addEventListener('resize', onWindowResize);
window.addEventListener('keydown', onKeyDown);
document.getElementById('restartButton').addEventListener('click', init);
// Start animation loop
animate();
}
function createMaze() {
// Ground
const groundGeometry = new THREE.PlaneGeometry(map[0].length + 2, map.length + 2);
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x333333, side: THREE.DoubleSide });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = Math.PI / 2;
ground.position.set(map[0].length / 2 - 0.5, -0.5, map.length / 2 - 0.5);
scene.add(ground);
// Create maze elements
for (let z = 0; z < map.length; z++) {
maze[z] = [];
for (let x = 0; x < map[z].length; x++) {
if (map[z][x] === 1) {
// Create wall
const wallGeometry = new THREE.BoxGeometry(1, 1, 1);
const wallMaterial = new THREE.MeshLambertMaterial({ color: 0x0000ff });
const wall = new THREE.Mesh(wallGeometry, wallMaterial);
wall.position.set(x, 0, z);
scene.add(wall);
maze[z][x] = { type: 'wall', object: wall };
} else if (map[z][x] === 2) {
// Create dot
const dotGeometry = new THREE.SphereGeometry(0.1, 8, 8);
const dotMaterial = new THREE.MeshLambertMaterial({ color: 0xffff00 });
const dot = new THREE.Mesh(dotGeometry, dotMaterial);
dot.position.set(x, 0, z);
scene.add(dot);
maze[z][x] = { type: 'dot', object: dot, collected: false };
dotsLeft++;
} else {
maze[z][x] = { type: 'empty' };
}
}
}
document.getElementById('dotsLeft').textContent = dotsLeft;
}
function createPlayer() {
// Create Pac-Man body (sphere with mouth)
const playerGeometry = new THREE.SphereGeometry(0.4, 32, 32, 0, Math.PI * 1.8);
const playerMaterial = new THREE.MeshLambertMaterial({ color: 0xffff00 });
player = new THREE.Mesh(playerGeometry, playerMaterial);
// Set initial position (middle of the maze)
player.position.set(9, 0, 10);
player.rotation.y = Math.PI / 2; // Face right initially
scene.add(player);
// Player properties
player.userData = {
direction: { x: 0, z: 0 },
nextDirection: { x: 0, z: 0 },
speed: 0.05,
mouthOpen: true,
mouthSpeed: 0.05
};
}
function movePlayer() {
if (gameOver) return;
// Try to move in the next direction if requested
if (player.userData.nextDirection.x !== 0 || player.userData.nextDirection.z !== 0) {
const nextX = Math.floor(player.position.x + player.userData.nextDirection.x * player.userData.speed * 2);
const nextZ = Math.floor(player.position.z + player.userData.nextDirection.z * player.userData.speed * 2);
// Check if the next position is valid
if (nextX >= 0 && nextX < map[0].length &&
nextZ >= 0 && nextZ < map.length &&
map[nextZ][nextX] !== 1) {
player.userData.direction = {...player.userData.nextDirection};
// Rotate player to face the direction of movement
if (player.userData.direction.x === 1) player.rotation.y = Math.PI / 2;
else if (player.userData.direction.x === -1) player.rotation.y = -Math.PI / 2;
else if (player.userData.direction.z === 1) player.rotation.y = Math.PI;
else if (player.userData.direction.z === -1) player.rotation.y = 0;
}
}
// Move player in the current direction
if (player.userData.direction.x !== 0 || player.userData.direction.z !== 0) {
const newX = player.position.x + player.userData.direction.x * player.userData.speed;
const newZ = player.position.z + player.userData.direction.z * player.userData.speed;
// Check if we're about to hit a wall
const nextTileX = Math.floor(newX + player.userData.direction.x * 0.4);
const nextTileZ = Math.floor(newZ + player.userData.direction.z * 0.4);
if (nextTileX >= 0 && nextTileX < map[0].length &&
nextTileZ >= 0 && nextTileZ < map.length &&
map[nextTileZ][nextTileX] !== 1) {
player.position.x = newX;
player.position.z = newZ;
// Tunnel teleport (if you go off one side, appear on the other)
if (player.position.x < 0) player.position.x = map[0].length - 1;
if (player.position.x >= map[0].length) player.position.x = 0;
if (player.position.z < 0) player.position.z = map.length - 1;
if (player.position.z >= map.length) player.position.z = 0;
// Collect dots
collectDots();
}
}
// Animate Pac-Man's mouth
animateMouth();
// Update camera position
updateCamera();
}
function animateMouth() {
// Create the mouth animation effect
const playerGeometry = player.geometry;
if (player.userData.mouthOpen) {
playerGeometry.parameters.thetaLength -= player.userData.mouthSpeed;
if (playerGeometry.parameters.thetaLength <= Math.PI) {
player.userData.mouthOpen = false;
}
} else {
playerGeometry.parameters.thetaLength += player.userData.mouthSpeed;
if (playerGeometry.parameters.thetaLength >= Math.PI * 1.8) {
player.userData.mouthOpen = true;
}
}
player.geometry = new THREE.SphereGeometry(
0.4, 32, 32, 0, playerGeometry.parameters.thetaLength
);
player.material = new THREE.MeshLambertMaterial({ color: 0xffff00 });
}
function collectDots() {
const x = Math.round(player.position.x);
const z = Math.round(player.position.z);
// Check if there's a dot at the player's position
if (x >= 0 && x < map[0].length && z >= 0 && z < map.length) {
if (maze[z][x] && maze[z][x].type === 'dot' && !maze[z][x].collected) {
// Collect the dot
maze[z][x].collected = true;
scene.remove(maze[z][x].object);
// Update score
score += 10;
document.getElementById('score').textContent = score;
// Update dots left
dotsLeft--;
document.getElementById('dotsLeft').textContent = dotsLeft;
// Check if all dots are collected
if (dotsLeft === 0) {
// Player wins
gameOver = true;
document.getElementById('gameOverScreen').style.display = 'block';
document.getElementById('finalScore').textContent = score;
}
}
}
}
function updateCamera() {
// Camera follows player with offset
camera.position.x = player.position.x + cameraOffset.x;
camera.position.y = player.position.y + cameraOffset.y;
camera.position.z = player.position.z + cameraOffset.z;
// Look at player
camera.lookAt(player.position.x, player.position.y, player.position.z);
}
function onKeyDown(event) {
if (gameOver) return;
// Movement keys
switch (event.key) {
case 'ArrowUp':
player.userData.nextDirection = { x: 0, z: -1 };
break;
case 'ArrowDown':
player.userData.nextDirection = { x: 0, z: 1 };
break;
case 'ArrowLeft':
player.userData.nextDirection = { x: -1, z: 0 };
break;
case 'ArrowRight':
player.userData.nextDirection = { x: 1, z: 0 };
break;
// Camera controls
case 'w':
cameraOffset.y += 0.5;
break;
case 's':
cameraOffset.y -= 0.5;
break;
case 'a':
cameraOffset.x -= 0.5;
break;
case 'd':
cameraOffset.x += 0.5;
break;
case 'q':
cameraOffset.z -= 0.5;
break;
case 'e':
cameraOffset.z += 0.5;
break;
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
movePlayer();
renderer.render(scene, camera);
}
// Start the game
init();
</script>
</body>
</html>