| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>Pac-Man Clone</title> |
| | <script src="https://cdn.tailwindcss.com"></script> |
| | <style> |
| | @keyframes pacman-animation { |
| | 0% { transform: rotate(0deg); } |
| | 50% { transform: rotate(-45deg); } |
| | 100% { transform: rotate(0deg); } |
| | } |
| | |
| | @keyframes ghost-animation { |
| | 0%, 100% { transform: translateY(0); } |
| | 50% { transform: translateY(-5px); } |
| | } |
| | |
| | .pacman { |
| | animation: pacman-animation 0.5s infinite; |
| | transform-origin: center; |
| | } |
| | |
| | .ghost { |
| | animation: ghost-animation 1s infinite ease-in-out; |
| | } |
| | |
| | .blinky { background-color: #FF0000; } |
| | .pinky { background-color: #FFB8FF; } |
| | .inky { background-color: #00FFFF; } |
| | .clyde { background-color: #FFB852; } |
| | |
| | .eye { |
| | background-color: white; |
| | border-radius: 50%; |
| | position: absolute; |
| | width: 10px; |
| | height: 10px; |
| | } |
| | |
| | .pupil { |
| | background-color: #0000AA; |
| | border-radius: 50%; |
| | position: absolute; |
| | width: 5px; |
| | height: 5px; |
| | } |
| | |
| | .dot { |
| | width: 8px; |
| | height: 8px; |
| | background-color: #FFF; |
| | border-radius: 50%; |
| | position: absolute; |
| | } |
| | |
| | .power-pellet { |
| | width: 16px; |
| | height: 16px; |
| | background-color: #FFF; |
| | border-radius: 50%; |
| | position: absolute; |
| | box-shadow: 0 0 10px 5px rgba(255, 255, 255, 0.7); |
| | } |
| | |
| | .wall { |
| | background-color: #2121FF; |
| | position: absolute; |
| | } |
| | |
| | #game-container { |
| | position: relative; |
| | width: 600px; |
| | height: 600px; |
| | background-color: #000; |
| | margin: 0 auto; |
| | overflow: hidden; |
| | } |
| | |
| | #score-display { |
| | position: absolute; |
| | top: 10px; |
| | left: 10px; |
| | color: white; |
| | font-family: 'Courier New', monospace; |
| | font-size: 20px; |
| | z-index: 100; |
| | } |
| | |
| | #lives-display { |
| | position: absolute; |
| | top: 10px; |
| | right: 10px; |
| | color: white; |
| | font-family: 'Courier New', monospace; |
| | font-size: 20px; |
| | z-index: 100; |
| | } |
| | |
| | #game-over { |
| | position: absolute; |
| | top: 50%; |
| | left: 50%; |
| | transform: translate(-50%, -50%); |
| | color: white; |
| | font-family: 'Courier New', monospace; |
| | font-size: 48px; |
| | text-align: center; |
| | display: none; |
| | z-index: 100; |
| | } |
| | |
| | #start-screen { |
| | position: absolute; |
| | top: 0; |
| | left: 0; |
| | width: 100%; |
| | height: 100%; |
| | background-color: rgba(0, 0, 0, 0.8); |
| | display: flex; |
| | flex-direction: column; |
| | justify-content: center; |
| | align-items: center; |
| | z-index: 200; |
| | } |
| | |
| | #start-screen h1 { |
| | color: #FF0; |
| | font-family: 'Courier New', monospace; |
| | font-size: 48px; |
| | margin-bottom: 30px; |
| | text-shadow: 0 0 10px #FF0; |
| | } |
| | |
| | #start-button { |
| | background-color: #FF0; |
| | color: #000; |
| | border: none; |
| | padding: 15px 30px; |
| | font-family: 'Courier New', monospace; |
| | font-size: 24px; |
| | cursor: pointer; |
| | border-radius: 10px; |
| | transition: all 0.3s; |
| | } |
| | |
| | #start-button:hover { |
| | background-color: #FFF; |
| | transform: scale(1.1); |
| | } |
| | |
| | .vulnerable-ghost { |
| | background-color: #0000FF !important; |
| | opacity: 0.7 !important; |
| | } |
| | </style> |
| | </head> |
| | <body class="bg-gray-900 flex flex-col items-center justify-center min-h-screen"> |
| | <h1 class="text-yellow-400 text-4xl font-bold mb-8">Pac-Man Clone</h1> |
| | |
| | <div id="game-container"> |
| | <div id="score-display">Score: 0</div> |
| | <div id="lives-display">Lives: 3</div> |
| | <div id="game-over">GAME OVER<br><button id="restart-button" class="mt-4 bg-yellow-400 text-black px-4 py-2 rounded">Play Again</button></div> |
| | <div id="start-screen"> |
| | <h1>PAC-MAN CLONE</h1> |
| | <button id="start-button">START GAME</button> |
| | <div class="mt-8 text-white text-center"> |
| | <p class="mb-2">Use arrow keys to move</p> |
| | <p class="mb-2">Eat all dots to win</p> |
| | <p>Avoid ghosts (except when powered up)</p> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <script> |
| | document.addEventListener('DOMContentLoaded', () => { |
| | const gameContainer = document.getElementById('game-container'); |
| | const scoreDisplay = document.getElementById('score-display'); |
| | const livesDisplay = document.getElementById('lives-display'); |
| | const gameOverDisplay = document.getElementById('game-over'); |
| | const startScreen = document.getElementById('start-screen'); |
| | const startButton = document.getElementById('start-button'); |
| | const restartButton = document.getElementById('restart-button'); |
| | |
| | const containerWidth = 600; |
| | const containerHeight = 600; |
| | const gridSize = 20; |
| | const cellSize = containerWidth / gridSize; |
| | |
| | let score = 0; |
| | let lives = 3; |
| | let gameRunning = false; |
| | let dotsRemaining = 0; |
| | let powerPelletActive = false; |
| | let powerPelletTimeout; |
| | let gameLoop; |
| | |
| | |
| | let pacman = { |
| | x: 9, |
| | y: 15, |
| | element: null, |
| | direction: 'right', |
| | nextDirection: 'right' |
| | }; |
| | |
| | const ghosts = [ |
| | { name: 'blinky', x: 9, y: 7, element: null, direction: 'left', color: 'red' }, |
| | { name: 'pinky', x: 9, y: 9, element: null, direction: 'up', color: 'pink' }, |
| | { name: 'inky', x: 8, y: 9, element: null, direction: 'right', color: 'cyan' }, |
| | { name: 'clyde', x: 10, y: 9, element: null, direction: 'down', color: 'orange' } |
| | ]; |
| | |
| | |
| | const maze = [ |
| | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], |
| | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], |
| | [1,0,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1], |
| | [1,0,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1], |
| | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], |
| | [1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1], |
| | [1,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,1], |
| | [1,1,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,1,1,1], |
| | [0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0], |
| | [1,1,1,1,0,1,0,1,1,2,2,1,1,1,0,1,1,1,1,1], |
| | [0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0], |
| | [1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1], |
| | [1,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,1], |
| | [1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1], |
| | [1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1], |
| | [1,1,0,1,0,1,0,1,1,1,1,1,1,0,1,0,1,0,1,1], |
| | [1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1], |
| | [1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,1], |
| | [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], |
| | [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] |
| | ]; |
| | |
| | |
| | function initGame() { |
| | |
| | gameContainer.querySelectorAll('.pacman, .ghost, .dot, .power-pellet, .wall').forEach(el => el.remove()); |
| | |
| | |
| | score = 0; |
| | lives = 3; |
| | dotsRemaining = 0; |
| | powerPelletActive = false; |
| | clearTimeout(powerPelletTimeout); |
| | clearInterval(gameLoop); |
| | |
| | |
| | pacman.x = 9; |
| | pacman.y = 15; |
| | pacman.direction = 'right'; |
| | pacman.nextDirection = 'right'; |
| | |
| | |
| | ghosts[0].x = 9; ghosts[0].y = 7; ghosts[0].direction = 'left'; |
| | ghosts[1].x = 9; ghosts[1].y = 9; ghosts[1].direction = 'up'; |
| | ghosts[2].x = 8; ghosts[2].y = 9; ghosts[2].direction = 'right'; |
| | ghosts[3].x = 10; ghosts[3].y = 9; ghosts[3].direction = 'down'; |
| | |
| | |
| | createMaze(); |
| | |
| | |
| | createDots(); |
| | |
| | |
| | createPacman(); |
| | |
| | |
| | ghosts.forEach(ghost => createGhost(ghost)); |
| | |
| | |
| | updateScore(); |
| | updateLives(); |
| | |
| | |
| | gameOverDisplay.style.display = 'none'; |
| | } |
| | |
| | function createMaze() { |
| | for (let y = 0; y < maze.length; y++) { |
| | for (let x = 0; x < maze[y].length; x++) { |
| | if (maze[y][x] === 1) { |
| | const wall = document.createElement('div'); |
| | wall.className = 'wall'; |
| | wall.style.width = `${cellSize}px`; |
| | wall.style.height = `${cellSize}px`; |
| | wall.style.left = `${x * cellSize}px`; |
| | wall.style.top = `${y * cellSize}px`; |
| | gameContainer.appendChild(wall); |
| | } |
| | } |
| | } |
| | } |
| | |
| | function createDots() { |
| | dotsRemaining = 0; |
| | |
| | for (let y = 0; y < maze.length; y++) { |
| | for (let x = 0; x < maze[y].length; x++) { |
| | if (maze[y][x] === 0) { |
| | const dot = document.createElement('div'); |
| | dot.className = 'dot'; |
| | dot.style.left = `${x * cellSize + cellSize / 2 - 4}px`; |
| | dot.style.top = `${y * cellSize + cellSize / 2 - 4}px`; |
| | gameContainer.appendChild(dot); |
| | dotsRemaining++; |
| | } else if (maze[y][x] === 2) { |
| | const powerPellet = document.createElement('div'); |
| | powerPellet.className = 'power-pellet'; |
| | powerPellet.style.left = `${x * cellSize + cellSize / 2 - 8}px`; |
| | powerPellet.style.top = `${y * cellSize + cellSize / 2 - 8}px`; |
| | gameContainer.appendChild(powerPellet); |
| | } |
| | } |
| | } |
| | } |
| | |
| | function createPacman() { |
| | if (pacman.element) { |
| | gameContainer.removeChild(pacman.element); |
| | } |
| | |
| | pacman.element = document.createElement('div'); |
| | pacman.element.className = 'pacman absolute'; |
| | pacman.element.style.width = `${cellSize}px`; |
| | pacman.element.style.height = `${cellSize}px`; |
| | pacman.element.style.left = `${pacman.x * cellSize}px`; |
| | pacman.element.style.top = `${pacman.y * cellSize}px`; |
| | pacman.element.style.backgroundColor = '#FF0'; |
| | pacman.element.style.borderRadius = '50%'; |
| | pacman.element.style.zIndex = '10'; |
| | |
| | |
| | const mouth = document.createElement('div'); |
| | mouth.style.position = 'absolute'; |
| | mouth.style.width = `${cellSize}px`; |
| | mouth.style.height = `${cellSize}px`; |
| | mouth.style.backgroundColor = '#000'; |
| | mouth.style.clipPath = 'polygon(50% 50%, 100% 0%, 100% 100%)'; |
| | pacman.element.appendChild(mouth); |
| | |
| | gameContainer.appendChild(pacman.element); |
| | } |
| | |
| | function createGhost(ghost) { |
| | if (ghost.element) { |
| | gameContainer.removeChild(ghost.element); |
| | } |
| | |
| | ghost.element = document.createElement('div'); |
| | ghost.element.className = `ghost absolute ${ghost.name}`; |
| | ghost.element.style.width = `${cellSize}px`; |
| | ghost.element.style.height = `${cellSize}px`; |
| | ghost.element.style.left = `${ghost.x * cellSize}px`; |
| | ghost.element.style.top = `${ghost.y * cellSize}px`; |
| | ghost.element.style.borderRadius = '50% 50% 0 0'; |
| | ghost.element.style.zIndex = '5'; |
| | |
| | |
| | const body = document.createElement('div'); |
| | body.style.position = 'absolute'; |
| | body.style.width = '100%'; |
| | body.style.height = '100%'; |
| | body.style.borderRadius = '50% 50% 0 0'; |
| | ghost.element.appendChild(body); |
| | |
| | |
| | const leftEye = document.createElement('div'); |
| | leftEye.className = 'eye'; |
| | leftEye.style.left = '25%'; |
| | leftEye.style.top = '25%'; |
| | ghost.element.appendChild(leftEye); |
| | |
| | const rightEye = document.createElement('div'); |
| | rightEye.className = 'eye'; |
| | rightEye.style.right = '25%'; |
| | rightEye.style.top = '25%'; |
| | ghost.element.appendChild(rightEye); |
| | |
| | |
| | const leftPupil = document.createElement('div'); |
| | leftPupil.className = 'pupil'; |
| | leftPupil.style.left = '2px'; |
| | leftPupil.style.top = '2px'; |
| | leftEye.appendChild(leftPupil); |
| | |
| | const rightPupil = document.createElement('div'); |
| | rightPupil.className = 'pupil'; |
| | rightPupil.style.right = '2px'; |
| | rightPupil.style.top = '2px'; |
| | rightEye.appendChild(rightPupil); |
| | |
| | |
| | const feetContainer = document.createElement('div'); |
| | feetContainer.style.position = 'absolute'; |
| | feetContainer.style.bottom = '0'; |
| | feetContainer.style.width = '100%'; |
| | feetContainer.style.height = '10px'; |
| | feetContainer.style.display = 'flex'; |
| | feetContainer.style.justifyContent = 'space-between'; |
| | ghost.element.appendChild(feetContainer); |
| | |
| | for (let i = 0; i < 3; i++) { |
| | const foot = document.createElement('div'); |
| | foot.style.width = '10px'; |
| | foot.style.height = '10px'; |
| | foot.style.backgroundColor = 'inherit'; |
| | foot.style.borderRadius = '0 0 5px 5px'; |
| | feetContainer.appendChild(foot); |
| | } |
| | |
| | gameContainer.appendChild(ghost.element); |
| | } |
| | |
| | function updateScore() { |
| | scoreDisplay.textContent = `Score: ${score}`; |
| | } |
| | |
| | function updateLives() { |
| | livesDisplay.textContent = `Lives: ${lives}`; |
| | } |
| | |
| | function movePacman() { |
| | let newX = pacman.x; |
| | let newY = pacman.y; |
| | |
| | |
| | if (pacman.nextDirection !== pacman.direction) { |
| | switch (pacman.nextDirection) { |
| | case 'up': |
| | if (isValidMove(pacman.x, pacman.y - 1)) { |
| | pacman.direction = pacman.nextDirection; |
| | } |
| | break; |
| | case 'down': |
| | if (isValidMove(pacman.x, pacman.y + 1)) { |
| | pacman.direction = pacman.nextDirection; |
| | } |
| | break; |
| | case 'left': |
| | if (isValidMove(pacman.x - 1, pacman.y)) { |
| | pacman.direction = pacman.nextDirection; |
| | } |
| | break; |
| | case 'right': |
| | if (isValidMove(pacman.x + 1, pacman.y)) { |
| | pacman.direction = pacman.nextDirection; |
| | } |
| | break; |
| | } |
| | } |
| | |
| | |
| | switch (pacman.direction) { |
| | case 'up': |
| | if (isValidMove(pacman.x, pacman.y - 1)) { |
| | newY--; |
| | } |
| | break; |
| | case 'down': |
| | if (isValidMove(pacman.x, pacman.y + 1)) { |
| | newY++; |
| | } |
| | break; |
| | case 'left': |
| | if (isValidMove(pacman.x - 1, pacman.y)) { |
| | newX--; |
| | } |
| | break; |
| | case 'right': |
| | if (isValidMove(pacman.x + 1, pacman.y)) { |
| | newX++; |
| | } |
| | break; |
| | } |
| | |
| | |
| | if (newX < 0) newX = gridSize - 1; |
| | if (newX >= gridSize) newX = 0; |
| | |
| | |
| | if (isValidMove(newX, newY) || (newX !== pacman.x || newY !== pacman.y)) { |
| | pacman.x = newX; |
| | pacman.y = newY; |
| | } |
| | |
| | |
| | pacman.element.style.left = `${pacman.x * cellSize}px`; |
| | pacman.element.style.top = `${pacman.y * cellSize}px`; |
| | |
| | |
| | switch (pacman.direction) { |
| | case 'up': |
| | pacman.element.style.transform = 'rotate(-90deg)'; |
| | break; |
| | case 'down': |
| | pacman.element.style.transform = 'rotate(90deg)'; |
| | break; |
| | case 'left': |
| | pacman.element.style.transform = 'rotate(180deg)'; |
| | break; |
| | case 'right': |
| | pacman.element.style.transform = 'rotate(0deg)'; |
| | break; |
| | } |
| | |
| | |
| | checkCollisions(); |
| | } |
| | |
| | function isValidMove(x, y) { |
| | |
| | if (x < 0 || x >= gridSize || y < 0 || y >= gridSize) { |
| | return true; |
| | } |
| | |
| | |
| | return maze[y][x] !== 1; |
| | } |
| | |
| | function checkCollisions() { |
| | |
| | const dots = document.querySelectorAll('.dot'); |
| | dots.forEach(dot => { |
| | const dotX = parseInt(dot.style.left) / cellSize; |
| | const dotY = parseInt(dot.style.top) / cellSize; |
| | |
| | if (Math.abs(pacman.x - dotX) < 0.5 && Math.abs(pacman.y - dotY) < 0.5) { |
| | dot.remove(); |
| | score += 10; |
| | dotsRemaining--; |
| | updateScore(); |
| | } |
| | }); |
| | |
| | |
| | const powerPellets = document.querySelectorAll('.power-pellet'); |
| | powerPellets.forEach(pellet => { |
| | const pelletX = parseInt(pellet.style.left) / cellSize; |
| | const pelletY = parseInt(pellet.style.top) / cellSize; |
| | |
| | if (Math.abs(pacman.x - pelletX) < 0.5 && Math.abs(pacman.y - pelletY) < 0.5) { |
| | pellet.remove(); |
| | score += 50; |
| | updateScore(); |
| | activatePowerPellet(); |
| | } |
| | }); |
| | |
| | |
| | ghosts.forEach(ghost => { |
| | if (Math.abs(pacman.x - ghost.x) < 0.8 && Math.abs(pacman.y - ghost.y) < 0.8) { |
| | if (powerPelletActive) { |
| | |
| | ghost.element.classList.add('vulnerable-ghost'); |
| | setTimeout(() => { |
| | |
| | ghost.x = 9; |
| | ghost.y = 9; |
| | ghost.element.style.left = `${ghost.x * cellSize}px`; |
| | ghost.element.style.top = `${ghost.y * cellSize}px`; |
| | ghost.element.classList.remove('vulnerable-ghost'); |
| | ghost.element.className = `ghost absolute ${ghost.name}`; |
| | }, 1000); |
| | |
| | score += 200; |
| | updateScore(); |
| | } else { |
| | |
| | lives--; |
| | updateLives(); |
| | |
| | if (lives <= 0) { |
| | gameOver(); |
| | } else { |
| | |
| | pacman.x = 9; |
| | pacman.y = 15; |
| | pacman.direction = 'right'; |
| | pacman.nextDirection = 'right'; |
| | pacman.element.style.left = `${pacman.x * cellSize}px`; |
| | pacman.element.style.top = `${pacman.y * cellSize}px`; |
| | pacman.element.style.transform = 'rotate(0deg)'; |
| | |
| | ghosts.forEach(g => { |
| | g.x = [9, 9, 8, 10][ghosts.indexOf(g)]; |
| | g.y = [7, 9, 9, 9][ghosts.indexOf(g)]; |
| | g.direction = ['left', 'up', 'right', 'down'][ghosts.indexOf(g)]; |
| | g.element.style.left = `${g.x * cellSize}px`; |
| | g.element.style.top = `${g.y * cellSize}px`; |
| | }); |
| | } |
| | } |
| | } |
| | }); |
| | |
| | |
| | if (dotsRemaining <= 0) { |
| | setTimeout(() => { |
| | alert('Congratulations! You won!'); |
| | initGame(); |
| | }, 500); |
| | } |
| | } |
| | |
| | function activatePowerPellet() { |
| | powerPelletActive = true; |
| | clearTimeout(powerPelletTimeout); |
| | |
| | |
| | ghosts.forEach(ghost => { |
| | ghost.element.classList.add('vulnerable-ghost'); |
| | }); |
| | |
| | |
| | powerPelletTimeout = setTimeout(() => { |
| | powerPelletActive = false; |
| | ghosts.forEach(ghost => { |
| | ghost.element.classList.remove('vulnerable-ghost'); |
| | ghost.element.className = `ghost absolute ${ghost.name}`; |
| | }); |
| | }, 10000); |
| | } |
| | |
| | function moveGhosts() { |
| | ghosts.forEach(ghost => { |
| | |
| | const directions = ['up', 'down', 'left', 'right']; |
| | const oppositeDirections = { |
| | 'up': 'down', |
| | 'down': 'up', |
| | 'left': 'right', |
| | 'right': 'left' |
| | }; |
| | |
| | |
| | let possibleDirections = directions.filter(dir => dir !== oppositeDirections[ghost.direction]); |
| | |
| | |
| | let newDirection = ghost.direction; |
| | let newX = ghost.x; |
| | let newY = ghost.y; |
| | |
| | |
| | let moved = false; |
| | |
| | switch (ghost.direction) { |
| | case 'up': |
| | if (isValidMove(ghost.x, ghost.y - 1)) { |
| | newY--; |
| | moved = true; |
| | } |
| | break; |
| | case 'down': |
| | if (isValidMove(ghost.x, ghost.y + 1)) { |
| | newY++; |
| | moved = true; |
| | } |
| | break; |
| | case 'left': |
| | if (isValidMove(ghost.x - 1, ghost.y)) { |
| | newX--; |
| | moved = true; |
| | } |
| | break; |
| | case 'right': |
| | if (isValidMove(ghost.x + 1, ghost.y)) { |
| | newX++; |
| | moved = true; |
| | } |
| | break; |
| | } |
| | |
| | |
| | if (!moved) { |
| | |
| | possibleDirections = possibleDirections.sort(() => Math.random() - 0.5); |
| | |
| | for (const dir of possibleDirections) { |
| | switch (dir) { |
| | case 'up': |
| | if (isValidMove(ghost.x, ghost.y - 1)) { |
| | newDirection = 'up'; |
| | newY--; |
| | moved = true; |
| | break; |
| | } |
| | case 'down': |
| | if (isValidMove(ghost.x, ghost.y + 1)) { |
| | newDirection = 'down'; |
| | newY++; |
| | moved = true; |
| | break; |
| | } |
| | case 'left': |
| | if (isValidMove(ghost.x - 1, ghost.y)) { |
| | newDirection = 'left'; |
| | newX--; |
| | moved = true; |
| | break; |
| | } |
| | case 'right': |
| | if (isValidMove(ghost.x + 1, ghost.y)) { |
| | newDirection = 'right'; |
| | newX++; |
| | moved = true; |
| | break; |
| | } |
| | } |
| | if (moved) break; |
| | } |
| | } |
| | |
| | |
| | if (newX < 0) newX = gridSize - 1; |
| | if (newX >= gridSize) newX = 0; |
| | |
| | |
| | ghost.x = newX; |
| | ghost.y = newY; |
| | ghost.direction = newDirection; |
| | |
| | |
| | ghost.element.style.left = `${ghost.x * cellSize}px`; |
| | ghost.element.style.top = `${ghost.y * cellSize}px`; |
| | |
| | |
| | const leftPupil = ghost.element.querySelector('.eye:first-child .pupil'); |
| | const rightPupil = ghost.element.querySelector('.eye:last-child .pupil'); |
| | |
| | leftPupil.style.left = ''; |
| | leftPupil.style.right = ''; |
| | leftPupil.style.top = ''; |
| | leftPupil.style.bottom = ''; |
| | rightPupil.style.left = ''; |
| | rightPupil.style.right = ''; |
| | rightPupil.style.top = ''; |
| | rightPupil.style.bottom = ''; |
| | |
| | switch (ghost.direction) { |
| | case 'up': |
| | leftPupil.style.left = '2px'; |
| | leftPupil.style.top = '0'; |
| | rightPupil.style.right = '2px'; |
| | rightPupil.style.top = '0'; |
| | break; |
| | case 'down': |
| | leftPupil.style.left = '2px'; |
| | leftPupil.style.bottom = '0'; |
| | rightPupil.style.right = '2px'; |
| | rightPupil.style.bottom = '0'; |
| | break; |
| | case 'left': |
| | leftPupil.style.left = '0'; |
| | leftPupil.style.top = '2px'; |
| | rightPupil.style.right = '4px'; |
| | rightPupil.style.top = '2px'; |
| | break; |
| | case 'right': |
| | leftPupil.style.left = '4px'; |
| | leftPupil.style.top = '2px'; |
| | rightPupil.style.right = '0'; |
| | rightPupil.style.top = '2px'; |
| | break; |
| | } |
| | }); |
| | } |
| | |
| | function gameOver() { |
| | gameRunning = false; |
| | gameOverDisplay.style.display = 'block'; |
| | } |
| | |
| | |
| | document.addEventListener('keydown', (e) => { |
| | switch (e.key) { |
| | case 'ArrowUp': |
| | pacman.nextDirection = 'up'; |
| | break; |
| | case 'ArrowDown': |
| | pacman.nextDirection = 'down'; |
| | break; |
| | case 'ArrowLeft': |
| | pacman.nextDirection = 'left'; |
| | break; |
| | case 'ArrowRight': |
| | pacman.nextDirection = 'right'; |
| | break; |
| | } |
| | }); |
| | |
| | startButton.addEventListener('click', () => { |
| | startScreen.style.display = 'none'; |
| | initGame(); |
| | startGame(); |
| | }); |
| | |
| | restartButton.addEventListener('click', () => { |
| | gameOverDisplay.style.display = 'none'; |
| | initGame(); |
| | startGame(); |
| | }); |
| | |
| | function startGame() { |
| | gameRunning = true; |
| | |
| | |
| | gameLoop = setInterval(() => { |
| | if (!gameRunning) { |
| | clearInterval(gameLoop); |
| | return; |
| | } |
| | |
| | movePacman(); |
| | moveGhosts(); |
| | }, 150); |
| | } |
| | }); |
| | </script> |
| | <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=Andosky/andosky-game" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body> |
| | </html> |