Skip to content

Commit

Permalink
Merge pull request #4565 from aamira0/main
Browse files Browse the repository at this point in the history
Pac-Man Game
  • Loading branch information
kunjgit authored Jul 1, 2024
2 parents 678820c + 79d8e44 commit cf973cd
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 0 deletions.
Binary file added Games/Pac_Man_Game/Img/Screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions Games/Pac_Man_Game/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Pac-Man

## Description 📃
This is a classic Pac-Man game built using HTML, CSS, and JavaScript. The objective of the game is to navigate Pac-Man through a maze, eat all the pac-dots, avoid the ghosts, and try to win the game!

## Functionalities 🎮
- **Pac-Man Movement**: Use arrow keys to move Pac-Man up, down, left, or right.
- **Pac-Dots**: Eat pac-dots to increase your score.
- **Ghosts**: Avoid ghosts that move around the maze. If a ghost touches Pac-Man, a life is lost.
- **Lives**: The player starts with 2 lives. The game ends when all lives are lost.
- **Winning Condition**: Collect all pac-dots to win the game.
- **Game Over**: The game ends when Pac-Man loses all lives and gets caught.

## How to Play? 🕹️
1. **Start the Game**: Open the game in your web browser. Pac-Man starts at the initial position in the maze.
2. **Move Pac-Man**: Use the arrow keys on your keyboard to move Pac-Man.
- **Arrow Up**: Move up
- **Arrow Down**: Move down
- **Arrow Left**: Move left
- **Arrow Right**: Move right
3. **Collect Pac-Dots**: Navigate through the maze and collect all the pac-dots to increase your score.
4. **Avoid Ghosts**: Avoid the ghosts moving around the maze. If a ghost touches Pac-Man, a life is lost.
5. **Game Over**: The game ends when Pac-Man loses all lives. A message will display "Game over! You lost!".
6. **Win the Game**: Collect all pac-dots to win the game. A message will display "Congratulations! You won!".

## Screenshots 📸
![Img/Screenshot.png](Img/Screenshot.png)
28 changes: 28 additions & 0 deletions Games/Pac_Man_Game/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pac-Man Game</title>
<!-- Link to the external stylesheet -->
<link rel="stylesheet" href="style.css">
</head>

<body>
<!-- Container for the game board -->
<div id="gameBoard"></div>

<!-- Display the current score -->
<div id="score">Score: <span id="scoreValue">0</span></div>
<!-- Display lives -->
<div id="livesContainer">
<span>Lives: </span>
<span id="life1" class="life"></span>
<span id="life2" class="life"></span>
</div>
<!-- Link to the JavaScript file -->
<script src="script.js"></script>
</body>

</html>
316 changes: 316 additions & 0 deletions Games/Pac_Man_Game/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
document.addEventListener('DOMContentLoaded', () => {
// Get the game board element
const gameBoard = document.getElementById('gameBoard');

// Initialize variables
const grid = []; // Array to hold the grid cells
const rows = 20; // Number of rows in the grid
const cols = 20; // Number of columns in the grid
let score = 0; // Player's score
let lives = 3; // Player's lives
let totalPacDots = 0; // Total number of pac-dots in the game
let gameOver = false; // Flag to track game over state
let gameLoop; // Variable to hold game loop interval

// Level layout (0 = empty, 1 = wall, 2 = pac-dot)
const layout = [
1,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,2,2,2,2,2,2,2,2,2,2,1,
1,2,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1,1,2,1,
1,2,2,2,2,2,2,2,1,2,2,2,1,2,1,2,2,2,2,1,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,
1,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,
1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
1,2,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,2,1,
1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
1,2,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,
1,2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,1,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,2,2,2,1,
1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,1,1,
1,2,2,2,2,2,2,2,1,2,2,2,1,2,2,2,2,2,2,1,
1,2,1,1,1,1,1,2,1,2,1,2,1,2,1,1,1,1,2,1,
1,2,2,2,2,2,2,2,2,2,1,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,1
];

// Create the gameboard
layout.forEach((cell, index) => {
const div = document.createElement('div'); // Create a new div element for each cell
div.classList.add('cell'); // Add the 'cell' class to the div

// Add wall class if the cell is a wall, pac-dot class if the cell contains a pac-dot
if (cell === 1) {
div.classList.add('wall'); // Add the 'wall' class to the div if the cell represents a wall
} else if (cell === 2) {
div.classList.add('pac-dot'); // Add the 'pac-dot' class to the div if the cell contains a pac-dot
totalPacDots++; // Increment totalPacDots for each pac-dot found
}

gameBoard.appendChild(div); // Add the div to the game board element in the HTML
grid.push(div); // Add the div element to the grid array for tracking
});

// Place Pac-Man
let pacmanCurrentIndex = 21; // Set Pac-Man's initial position to index 21
grid[pacmanCurrentIndex].classList.add('pacman'); // Add 'pacman' class to the cell at Pac-Man's initial position

// Remove pac-dot at initial position if present
if (grid[pacmanCurrentIndex].classList.contains('pac-dot')) {
grid[pacmanCurrentIndex].classList.remove('pac-dot'); // Remove 'pac-dot' class if present at Pac-Man's initial position
score += 10; // Increase the score by 10 points
document.getElementById('scoreValue').textContent = score; // Update the score display
}

// Function to move Pac-Man
const movePacman = () => {
if (!gameOver && direction !== null) {
let newIndex = pacmanCurrentIndex; // Initialize newIndex with the current Pac-Man index

// Move Pac-Man based on the current direction
switch (direction) {
case 'ArrowUp': // Move Pac-Man up if the direction is 'ArrowUp'
// Check if moving up is possible and there is no wall in the way
if (pacmanCurrentIndex - cols >= 0 && !grid[pacmanCurrentIndex - cols].classList.contains('wall')) {
newIndex -= cols; // Move Pac-Man up by one row
}
break;
case 'ArrowDown': // Move Pac-Man down if the direction is 'ArrowDown'
// Check if moving down is possible and there is no wall in the way
if (pacmanCurrentIndex + cols < cols * rows && !grid[pacmanCurrentIndex + cols].classList.contains('wall')) {
newIndex += cols; // Move Pac-Man down by one row
}
break;
case 'ArrowLeft': // Move Pac-Man left if the direction is 'ArrowLeft'
// Check if moving left is possible and there is no wall in the way
if (pacmanCurrentIndex % cols !== 0 && !grid[pacmanCurrentIndex - 1].classList.contains('wall')) {
newIndex -= 1; // Move Pac-Man left by one column
}
break;
case 'ArrowRight': // Move Pac-Man right if the direction is 'ArrowRight'
// Check if moving right is possible and there is no wall in the way
if (pacmanCurrentIndex % cols < cols - 1 && !grid[pacmanCurrentIndex + 1].classList.contains('wall')) {
newIndex += 1; // Move Pac-Man right by one column
}
break;
}

// Check if Pac-Man's position has changed
if (newIndex !== pacmanCurrentIndex) {
// Remove Pac-Man from the current position
grid[pacmanCurrentIndex].classList.remove('pacman');
pacmanCurrentIndex = newIndex; // Update Pac-Man's current index
grid[pacmanCurrentIndex].classList.add('pacman'); // Add Pac-Man to the new position

// Check if Pac-Man has eaten a pac-dot
if (grid[pacmanCurrentIndex].classList.contains('pac-dot')) {
grid[pacmanCurrentIndex].classList.remove('pac-dot'); // Remove the pac-dot
score += 10; // Increase the score
document.getElementById('scoreValue').textContent = score; // Update the score display
console.log('Score:', score);

// Call checkForWin function after updating score
checkForWin();
}

// Check for collision with ghosts after Pac-Man moves
checkCollision(); // Check collision after each move
}

// Check if Pac-Man's position after movement ends the game
if (lives === 0) {
gameOver = true;
endGame(); // Game over
}
}
};

// Function to check for win condition
const checkForWin = () => {
if (score === 2030) { // Total score won
gameOver = true; // Set game over flag
clearInterval(gameLoop); // Stop the game loop

// Stop ghost movements
ghost1.stop();
ghost2.stop();

// Display win message after a short delay
setTimeout(() => {
alert("Congratulations! You won!");
}, 500);

}
};

// Check for keydown events to set Pac-Man's direction
let direction = null; // Initialize direction as null
document.addEventListener('keydown', (event) => {
const key = event.key;
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
direction = key; // Set Pac-Man's direction based on the pressed key
}
});

// Initialize lives using a for loop
for (let lives = 3; lives > 0; lives--) {
}

// Function to end the game
const endGame = () => {
clearInterval(gameLoop); // Stop the game loop

// Stop ghost movements
ghost1.stop();
ghost2.stop();

// Display game over message after a short delay
setTimeout(() => {
alert("Game over! You lost!");
}, 500);
};

// Game loop
gameLoop = setInterval(movePacman, 200); // Move Pac-Man every 200ms

// Ghost
class Ghost {
constructor(startIndex, color) {
// Initialize Ghost
this.currentIndex = startIndex; // Set the current index of the ghost
this.color = color; // Set the color of the ghost
this.timerId = null; // Timer ID for ghost movement interval
}

moveGhost() {
const directions = [-1, +1, -cols, +cols]; // Possible directions for the ghost

// Function to calculate distance between two indices on the grid
const distanceToPacman = (ghostIndex, pacmanIndex) => {
const ghostRow = Math.floor(ghostIndex / cols);
const ghostCol = ghostIndex % cols;
const pacmanRow = Math.floor(pacmanIndex / cols);
const pacmanCol = pacmanIndex % cols;
return Math.abs(ghostRow - pacmanRow) + Math.abs(ghostCol - pacmanCol);
};

// Function to choose the best direction towards Pac-Man
const chooseDirection = () => {
// Get Pac-Man's current index
const pacmanIndex = grid.findIndex(cell => cell.classList.contains('pacman'));

// Calculate distances for each direction and filter out invalid moves
const validDirections = directions.filter(direction => {
const nextMove = this.currentIndex + direction;
return !grid[nextMove].classList.contains('wall') && !grid[nextMove].classList.contains('ghost');
});

// Sort directions by distance to Pac-Man
validDirections.sort((dir1, dir2) => {
const nextMove1 = this.currentIndex + dir1;
const nextMove2 = this.currentIndex + dir2;
return distanceToPacman(nextMove1, pacmanIndex) - distanceToPacman(nextMove2, pacmanIndex);
});

// Return the closest direction if available
return validDirections.length > 0 ? validDirections[0] : null;
};

let direction = chooseDirection(); // Initial direction

// Move the ghost at regular intervals
this.timerId = setInterval(() => {
// Logic for ghost movement
if (!gameOver && direction !== null) {
const nextMove = this.currentIndex + direction; // Calculate the next potential position for the ghost

// Check if next move isn't a wall or another ghost
if (!grid[nextMove].classList.contains('wall') && !grid[nextMove].classList.contains('ghost')) {
// Remove ghost from the current position
grid[this.currentIndex].classList.remove('ghost', this.color);
// Move the ghost to the next position
this.currentIndex = nextMove;
// Place the ghost on the new position
grid[this.currentIndex].classList.add('ghost', this.color);
} else {
// Choose a new direction if the ghost can't move
direction = chooseDirection();
}

// Check if the ghost touched Pac-Man
if (this.currentIndex === pacmanCurrentIndex) {
lives--; // Decrease lives
document.getElementById('livesValue').textContent = lives; // Update lives display

if (lives === 0) {
gameOver = true;
endGame(); // Game over
} else {
// Reset Pac-Man's position
grid[pacmanCurrentIndex].classList.remove('pacman');
pacmanCurrentIndex = 21;
grid[pacmanCurrentIndex].classList.add('pacman');
}
}
}
}, 200); // Move Ghost every 200ms
}

stop() {
clearInterval(this.timerId); // Stop the ghost movement
}
}

// Create ghosts
const ghost1 = new Ghost(209, 'red'); // Place the first ghost
const ghost2 = new Ghost(229, 'blue'); // Place the second ghost

// Start ghost movement
ghost1.moveGhost();
ghost2.moveGhost();

// Define the lifeIcons array globally
const lifeIcons = [
document.getElementById('life1'),
document.getElementById('life2'),
];

const updateLivesDisplay = () => {
console.log('Updating lives display. Current lives:', lives);
for (let i = 0; i < lifeIcons.length; i++) {
if (i < lives) {
lifeIcons[i].style.display = 'inline-block'; // Display the life icon
} else {
lifeIcons[i].style.display = 'none'; // Hide the life icon
}
console.log(`Life icon ${i + 1}: display is ${lifeIcons[i].style.display}`);
}
};

const checkCollision = () => {
if (grid[pacmanCurrentIndex].classList.contains('ghost')) {
lives--; // Decrease lives
updateLivesDisplay(); // Update visual display of lives

// Reset Pac-Man's position
grid[pacmanCurrentIndex].classList.remove('pacman');
pacmanCurrentIndex = 21;
grid[pacmanCurrentIndex].classList.add('pacman');

// Update lives count in the HTML element
document.getElementById('livesValue').textContent = lives;

// Check if there are no lives left
if (lives === 0) {
gameOver = true;
endGame(); // Game over
}
}
};

// Check for collision on Pac-Man movement
setInterval(checkCollision, 100); // Check collision every 100ms
});

Loading

0 comments on commit cf973cd

Please sign in to comment.