diff --git a/Games/Pac_Man_Game/CodeStandards.md b/Games/Pac_Man_Game/CodeStandards.md new file mode 100644 index 0000000000..b228671bab --- /dev/null +++ b/Games/Pac_Man_Game/CodeStandards.md @@ -0,0 +1,63 @@ +# Code Standards + +## 1. File Structure +- Keep HTML, CSS, and JavaScript in separate files. +- Use clear and descriptive names for files and folders. + +## 2. HTML +- Use meaningful HTML tags. +- Link CSS and JavaScript files in the `` or at the end of the ``. +- Use meaningful `id` and `class` names. + +## 3. CSS +- Use consistent class names (e.g., `kebab-case`). +- Group related styles together. +- Use comments to separate sections. +- Use relative units (e.g., `em`, `rem`) for sizes. +- Use `z-index` sparingly. +- Use CSS animations for effects. + +## 4. JavaScript +- Use `const` and `let` instead of `var`. +- Use `const` for variables that don't change. +- Use `let` for variables that can change. +- Use clear names for variables and functions. +- Use camelCase for variables and functions. +- Use PascalCase for class names. +- Group related functions together. +- Add comments above and/or next to code to explain it. +- Use template literals for strings. +- Use event listeners for user interactions. +- Use `setInterval` and `setTimeout` for timed actions. +- Use `querySelector` and `querySelectorAll` to select elements. +- Use `classList` to add, remove, and toggle classes. +- Use `appendChild` and `removeChild` for DOM changes. +- Use `addEventListener` for events. + +### Example + +```javascript +// Use const for variables that do not change +const gameBoard = document.getElementById('gameBoard'); + +// Use let for variables that may change +let score = 0; + +// Use descriptive names for functions +const initializeGame = () => { + // Function logic here +}; + +// Use event listeners to handle user interactions +document.addEventListener('DOMContentLoaded', initializeGame); + +// Use template literals for string concatenation +const updateScore = (points) => { + score += points; + document.getElementById('scoreValue').textContent = `Score: ${score}`; +}; + +// Use arrow functions for anonymous functions +document.getElementById('startGameButton').addEventListener('click', () => { + // Start game logic here +}); \ No newline at end of file diff --git a/Games/Pac_Man_Game/Img/Screenshot.png b/Games/Pac_Man_Game/Img/Screenshot.png index 2fb1a59e20..e2a5d12e26 100644 Binary files a/Games/Pac_Man_Game/Img/Screenshot.png and b/Games/Pac_Man_Game/Img/Screenshot.png differ diff --git a/Games/Pac_Man_Game/README.md b/Games/Pac_Man_Game/README.md index 9a50d70455..5c4734bbcc 100644 --- a/Games/Pac_Man_Game/README.md +++ b/Games/Pac_Man_Game/README.md @@ -6,8 +6,10 @@ This is a classic Pac-Man game built using HTML, CSS, and JavaScript. The object ## 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. +- **Power Pellets**: Eat power pellets to temporarily turn ghosts blue and make them vulnerable. - **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. +- **Fruits**: Occasionally, fruits appear in the maze. Eat them to gain extra points. +- **Lives**: The player starts with 3 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. @@ -19,9 +21,11 @@ This is a classic Pac-Man game built using HTML, CSS, and JavaScript. The object - **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!". +4. **Eat Power Pellets**: Eat power pellets to turn ghosts blue and make them vulnerable. You can eat blue ghosts for extra points. +5. **Collect Fruits**: Occasionally, fruits appear in the maze. Eat them to gain extra points. +6. **Avoid Ghosts**: Avoid the ghosts moving around the maze. If a ghost touches Pac-Man, a life is lost. +7. **Game Over**: The game ends when Pac-Man loses all lives. A message will display "Game over! You lost!". +8. **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) diff --git a/Games/Pac_Man_Game/index.html b/Games/Pac_Man_Game/index.html index c435db18b0..fbcaa99a25 100644 --- a/Games/Pac_Man_Game/index.html +++ b/Games/Pac_Man_Game/index.html @@ -5,24 +5,54 @@ Pac-Man Game - - + + - +
- +
Score: 0
-
+
Lives: + +
+ + +
+ Start Game
+ + +
+

Use the ⬅️ ⬆️ ➡️ ⬇️ arrow keys to move Pac-Man!

+
+ + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/Games/Pac_Man_Game/pixels/PacMan-title.png b/Games/Pac_Man_Game/pixels/PacMan-title.png new file mode 100644 index 0000000000..98630fc5be Binary files /dev/null and b/Games/Pac_Man_Game/pixels/PacMan-title.png differ diff --git a/Games/Pac_Man_Game/pixels/fruit-apple.png b/Games/Pac_Man_Game/pixels/fruit-apple.png new file mode 100644 index 0000000000..4ddebc4ba4 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/fruit-apple.png differ diff --git a/Games/Pac_Man_Game/pixels/fruit-cherry.png b/Games/Pac_Man_Game/pixels/fruit-cherry.png new file mode 100644 index 0000000000..5271b07433 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/fruit-cherry.png differ diff --git a/Games/Pac_Man_Game/pixels/fruit-orange.png b/Games/Pac_Man_Game/pixels/fruit-orange.png new file mode 100644 index 0000000000..284af5e49b Binary files /dev/null and b/Games/Pac_Man_Game/pixels/fruit-orange.png differ diff --git a/Games/Pac_Man_Game/pixels/fruit-strawberry.png b/Games/Pac_Man_Game/pixels/fruit-strawberry.png new file mode 100644 index 0000000000..4719d06659 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/fruit-strawberry.png differ diff --git a/Games/Pac_Man_Game/pixels/ghost-blue.png b/Games/Pac_Man_Game/pixels/ghost-blue.png new file mode 100644 index 0000000000..f1d2be581b Binary files /dev/null and b/Games/Pac_Man_Game/pixels/ghost-blue.png differ diff --git a/Games/Pac_Man_Game/pixels/ghost-pink.png b/Games/Pac_Man_Game/pixels/ghost-pink.png new file mode 100644 index 0000000000..542f8b773f Binary files /dev/null and b/Games/Pac_Man_Game/pixels/ghost-pink.png differ diff --git a/Games/Pac_Man_Game/pixels/ghost-red.png b/Games/Pac_Man_Game/pixels/ghost-red.png new file mode 100644 index 0000000000..78dadf80e5 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/ghost-red.png differ diff --git a/Games/Pac_Man_Game/pixels/ghosts-slow.gif b/Games/Pac_Man_Game/pixels/ghosts-slow.gif new file mode 100644 index 0000000000..cca916bb85 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/ghosts-slow.gif differ diff --git a/Games/Pac_Man_Game/pixels/pacman.gif b/Games/Pac_Man_Game/pixels/pacman.gif new file mode 100644 index 0000000000..6437292fc0 Binary files /dev/null and b/Games/Pac_Man_Game/pixels/pacman.gif differ diff --git a/Games/Pac_Man_Game/script.js b/Games/Pac_Man_Game/script.js index 25d4184bde..67f85f3fcc 100644 --- a/Games/Pac_Man_Game/script.js +++ b/Games/Pac_Man_Game/script.js @@ -1,316 +1,573 @@ document.addEventListener('DOMContentLoaded', () => { // Get the game board element - const gameBoard = document.getElementById('gameBoard'); + const gameBoard = document.getElementById('gameBoard'); // Game board element + const startSound = document.getElementById('startSound'); // Start screen audio element + const eatSound = document.getElementById('eatSound'); // Eat sound element + const eatFruitSound = document.getElementById('eatFruitSound'); // Eat fruit sound element + const powerUpSound = document.getElementById('powerUpSound'); // Power-up sound element + const ghostEatenSound = document.getElementById('ghostEatenSound'); // Ghost eaten sound element + const gameOverSound = document.getElementById('gameOverSound'); // Game over sound element // Initialize variables const grid = []; // Array to hold the grid cells - const rows = 20; // Number of rows in the grid + const rows = 24; // Updated 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 totalPowerPellets = 0; // Total number of power-pellets in the game let gameOver = false; // Flag to track game over state let gameLoop; // Variable to hold game loop interval + let powerPelletActive = false; // Flag to track power pellet state + let powerPelletTimer; // Timer for power pellet effect + let powerPelletSpawnTimer; // Timer for spawning power pellets + + // Start game after startscreen + const initializeGame = () => { // 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,1,2,1,1,1,1,2,1,1,2,1,1,1,1,2,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,1,1,1,1,2,1,1,1,2,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,1,2,1,1,1,1,1,2,1,1,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,2,1, - 1,2,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,2,1, + 0,2,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,2,0, 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,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,2,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,2,1,1,2,1,1,1,2,1,1,1,2,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,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 + // Create the grid + layout.forEach((cell, index) => { // Loop through each cell in the layout + const div = document.createElement('div'); // Create a new div element + 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 + if (cell === 1) { // If the cell is a wall + div.classList.add('wall'); // Add the wall class to the div + } else if (cell === 2) { // If the cell is a pac-dot + div.classList.add('pac-dot'); // Add the pac-dot class to the div + totalPacDots++; // Add to the total number of pac-dots } - - 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 + gameBoard.appendChild(div); // Append the div to the game board + grid.push(div); // Add the div to the grid array }); - // 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 + let pacmanCurrentIndex = 21; // Starting position + grid[pacmanCurrentIndex].classList.add('pacman'); // Add the pacman class to the starting 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 + // Kept this here so that the firs pac-dot is eaten and the backgriund of the pacman doesn't turn white + if (grid[pacmanCurrentIndex].classList.contains('pac-dot')) { // If the pacman is on a pac-dot + grid[pacmanCurrentIndex].classList.remove('pac-dot'); // Remove the pac-dot class + score += 10; // Add 10 to the score + totalPacDots--; // Subtract 1 from the total number of pac-dots document.getElementById('scoreValue').textContent = score; // Update the score display + grid[pacmanCurrentIndex].style.backgroundColor = '#000'; // Set the background color to match the game board } + // Function to spawn fruit + const spawnFruit = () => { + const fruitTypes = ['apple', 'orange', 'cherry', 'strawberry']; // Array of fruit types + + // Choose a random fruit type (math.floor rounds down to the nearest integer and math.random generates a random number between 0 and 1) + // Math.random() * fruitTypes.length generates a random number between 0 and 3 + const randomFruit = fruitTypes[Math.floor(Math.random() * fruitTypes.length)]; // Choose a random fruit type + + // Choose a random cell that does not contain a wall + const availableCells = grid.filter(cell => + !cell.classList.contains('wall') && // Filter out walls + !cell.classList.contains('pacman') && // Filter out pacman + !cell.classList.contains('ghost') // Filter out ghosts + ); + + if (availableCells.length > 0) { // If there are available cells + // Choose a random cell (math.floor rounds down to the nearest integer and math.random generates a random number between 0 and 1) + // Math.random() * availableCells.length generates a random number between 0 and the number of available cells + const randomCell = availableCells[Math.floor(Math.random() * availableCells.length)]; // Choose a random cell + + // Add fruit to the cell + const fruitElement = document.createElement('div'); // Create a new div element + fruitElement.classList.add('fruit', randomFruit); // Add the fruit and fruit type classes to the div + randomCell.appendChild(fruitElement); // Append the div to the random cell + + // Remove the fruit after 10 seconds if it is not eaten + setTimeout(() => { + if (randomCell.contains(fruitElement)) { // If the random cell contains the fruit element + randomCell.removeChild(fruitElement); // Remove the fruit element + } + }, 10000); // 10 seconds + } + }; + + // Start an interval to spawn fruit every 20 seconds + setInterval(spawnFruit, 20000); + // Function to move Pac-Man const movePacman = () => { - if (!gameOver && direction !== null) { - let newIndex = pacmanCurrentIndex; // Initialize newIndex with the current Pac-Man index + if (!gameOver && direction !== null) { // If the game is not over and there is a direction + let newIndex = pacmanCurrentIndex; // Set the new index to the current index + let rotation = 0; // Set the rotation to 0 so that the pacman faces right at the start - // 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 + switch (direction) { // Switch statement to handle the direction + case 'ArrowUp': // If the direction is up + if (pacmanCurrentIndex - cols >= 0 && !grid[pacmanCurrentIndex - cols].classList.contains('wall')) { // If the new index is within the grid and does not contain a wall + newIndex -= cols; // Subtract the number of columns from the new index so that it moves up + rotation = -90; // Rotate up } - 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 + break; // Break out of the switch statement so that the pacman does not move in multiple directions + case 'ArrowDown': // If the direction is down if (pacmanCurrentIndex + cols < cols * rows && !grid[pacmanCurrentIndex + cols].classList.contains('wall')) { - newIndex += cols; // Move Pac-Man down by one row + newIndex += cols; // Add the number of columns to the new index so that it moves down + rotation = 90; // Rotate down } 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 + case 'ArrowLeft': // If the direction is left if (pacmanCurrentIndex % cols !== 0 && !grid[pacmanCurrentIndex - 1].classList.contains('wall')) { - newIndex -= 1; // Move Pac-Man left by one column + newIndex -= 1; // Subtract 1 from the new index so that it moves left + rotation = 180; // Rotate left + } else if (pacmanCurrentIndex % cols === 0) { // If the pacman is at the left portal + newIndex += cols - 1; // Move to the right portal + rotation = 180; // Rotate left } 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 + case 'ArrowRight': // If the direction is right if (pacmanCurrentIndex % cols < cols - 1 && !grid[pacmanCurrentIndex + 1].classList.contains('wall')) { - newIndex += 1; // Move Pac-Man right by one column + newIndex += 1; // Add 1 to the new index so that it moves right + rotation = 0; // Rotate right + } else if (pacmanCurrentIndex % cols === cols - 1) { + newIndex -= cols - 1; // Move to the left portal + rotation = 0; // Rotate right } 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 + if (grid[pacmanCurrentIndex].querySelector('.fruit')) { // If the current cell contains a fruit + const fruit = grid[pacmanCurrentIndex].querySelector('.fruit'); // Get the fruit element + let fruitScore = 0; // Initialize the fruit score so that it can be updated later + + // Decide the number of points based on the fruit type + if (fruit.classList.contains('apple')) fruitScore = 100; + else if (fruit.classList.contains('orange')) fruitScore = 150; + else if (fruit.classList.contains('cherry')) fruitScore = 200; + else if (fruit.classList.contains('strawberry')) fruitScore = 250; + + score += fruitScore; // Add the fruit score to the total score + document.getElementById('scoreValue').textContent = score; // Update the score display + + // Show score indicator at the fruit position + showScoreIndicator(`+${fruitScore}`, pacmanCurrentIndex); - // 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 + // Play the eat fruit sound + eatFruitSound.play(); + + // Delete fruit from grid + fruit.remove(); + } + + if (newIndex !== pacmanCurrentIndex) { // If the new index is different from the current index + grid[pacmanCurrentIndex].classList.remove('pacman'); // Remove the pacman class from the current cell + pacmanCurrentIndex = newIndex; // Update the current index to the new index + grid[pacmanCurrentIndex].classList.add('pacman'); // Add the pacman class to the new cell + grid[pacmanCurrentIndex].style.transform = `rotate(${rotation}deg)`; // Apply rotation when moving + + if (grid[pacmanCurrentIndex].classList.contains('pac-dot')) { // If the new cell contains a pac-dot + grid[pacmanCurrentIndex].classList.remove('pac-dot'); // Remove the pac-dot class + score += 10; // Add 10 to the score + totalPacDots--; // Subtract 1 from the total number of pac-dots document.getElementById('scoreValue').textContent = score; // Update the score display + eatSound.play(); // Play the eat sound console.log('Score:', score); - - // Call checkForWin function after updating score - checkForWin(); + + checkForWin(); // Check for win condition + } else if (grid[pacmanCurrentIndex].classList.contains('power-pellet')) { // If the new cell contains a power-pellet + grid[pacmanCurrentIndex].classList.remove('power-pellet'); // Remove the power-pellet class + score += 50; // Add 50 to the score + totalPowerPellets--; // Subtract 1 from the total number of power-pellets + document.getElementById('scoreValue').textContent = score; // Update the score display + eatSound.play(); // Play the eat sound + powerUpSound.play(); // Play the power-up sound + console.log('Score:', score); + + activatePowerPelletEffect(); // Activate the power-pellet effect } - // Check for collision with ghosts after Pac-Man moves - checkCollision(); // Check collision after each move + checkCollision(); // Check for collision } - // Check if Pac-Man's position after movement ends the game - if (lives === 0) { - gameOver = true; - endGame(); // Game over + if (lives === 0) { // If the player has no lives left + gameOver = true; // Set the game over flag to true + endGame(); // End the game } } }; - // 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 + const addRestartButtonListener = () => { // Function to add an event listener to the restart button + // Event listener to the restart button + document.getElementById('restartGameButton').addEventListener('click', () => { // When the restart button is clicked + console.log('Restart button clicked'); + window.location.reload(); // Reload the page to restart the game + }); + }; + + const checkForWin = () => { // Function to check for the win condition + if (totalPacDots === 0 && totalPowerPellets === 0) { // If there are no pac-dots and power-pellets left + gameOver = true; // Set the game over flag to true + clearInterval(gameLoop); // Clear the game loop - // Stop ghost movements - ghost1.stop(); - ghost2.stop(); + ghosts.forEach(ghost => ghost.stop()); // Stop the ghosts - // Display win message after a short delay - setTimeout(() => { - alert("Congratulations! You won!"); - }, 500); - + // Delete existing overlay + const existingOverlay = document.getElementById('gameOverOverlay'); // Get the existing overlay + if (existingOverlay) { // If the overlay exists + existingOverlay.remove(); // Remove the overlay + } + + // Create new overlay + const gameOverOverlay = document.createElement('div'); // Create a new div element + gameOverOverlay.id = 'gameOverOverlay'; // Set the id of the div + // Add the game over message to the div + gameOverOverlay.innerHTML = ` +
+

Congratulations! You Won!

+ +
+ `; + document.body.appendChild(gameOverOverlay); // Append the div to the body + + addRestartButtonListener(); // Add an event listener to the restart button } }; - // 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 - } - }); + const endGame = () => { // Function to end the game + clearInterval(gameLoop); // Clear the game loop + + ghosts.forEach(ghost => ghost.stop()); // Stop the ghosts + + // Delete existing overlay + const existingOverlay = document.getElementById('gameOverOverlay'); // Get the existing overlay + if (existingOverlay) { // If the overlay exists + existingOverlay.remove(); // Remove the overlay + } + + // Create new overlay + const gameOverOverlay = document.createElement('div'); // Create a new div element + gameOverOverlay.id = 'gameOverOverlay'; // Set the id of the div + // Add the game over message to the div + gameOverOverlay.innerHTML = ` +
+

Game Over!

+ +
+ `; + document.body.appendChild(gameOverOverlay); // Append the div to the body - // Initialize lives using a for loop - for (let lives = 3; lives > 0; lives--) { - } + gameOverSound.play(); // Play the game over sound - // 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); - }; + addRestartButtonListener(); // Add an event listener to the restart button + }; + + let direction = null; // Direction variable to store the current direction + document.addEventListener('keydown', (event) => { + const key = event.key; + if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) { + direction = key; + } + }); + + // Start the game when the start button is clicked (startscreen) + document.getElementById('startGameButton').addEventListener('click', () => { // When the start button is clicked + document.getElementById('startGameOverlay').style.display = 'none'; // Hide the start overlay + initializeGame(); // Initialize the game + }); + + class Ghost { + constructor(startIndex, color) { // Constructor to initialize the ghost + this.startIndex = startIndex; // Set the start index + this.currentIndex = startIndex; // Set the current index + this.color = color; + this.timerId = null; // Timer ID + this.originalSpeed = 200; // Original speed + this.currentSpeed = this.originalSpeed; // Current speed + this.scared = false; // Initial scared state + this.ghostElement = document.createElement('div'); // Create a new div element + this.ghostElement.classList.add('ghost', this.color); // Add the ghost and color classes + this.ghostElement.style.width = '20px'; // Set the width + this.ghostElement.style.height = '20px'; // Set the height + this.ghostElement.style.transform = 'rotate(0deg)'; // Prevent rotation + grid[this.currentIndex].appendChild(this.ghostElement); // Append the div to the grid + this.draw(); // Draw the ghost on the grid + } + + draw() { // Function to draw the ghost on the grid + grid[this.currentIndex].appendChild(this.ghostElement); + } + + scare() { // Function to scare the ghost + this.scared = true; // Set the scared state to true + this.currentSpeed = 400; // Slow down the ghost + this.ghostElement.classList.add('scared'); // Add scared class + this.restartMovement(); // Restart the movement + } + + unscare() { // Function to unscare the ghost + this.scared = false; // Set the scared state to false + this.currentSpeed = this.originalSpeed; // Reset the speed + this.ghostElement.classList.remove('scared'); // Remove scared class + this.restartMovement(); // Restart the movement + } + + restartMovement() { // Function to restart the movement + clearInterval(this.timerId); // Stop the current movement + this.moveGhost(); // Restart the movement with the new speed + } - // 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 + resetPosition() { // Function to reset the ghost position + this.ghostElement.classList.remove('ghost', this.color); // Remove the ghost and color classes + this.currentIndex = this.startIndex; // Reset the current index + grid[this.currentIndex].appendChild(this.ghostElement); // Append the ghost element to the grid + this.ghostElement.classList.add('ghost', this.color); // Add the ghost and color classes + if (this.scared) { // If the ghost is scared + this.ghostElement.classList.add('scared'); // Retain scared class if ghost is scared } + } - 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(); - } + moveGhost() { // Function to move the ghost + const directions = [-1, +1, -cols, +cols]; // Array of directions + const distanceToPacman = (ghostIndex, pacmanIndex) => { // Function to calculate the distance + const ghostRow = Math.floor(ghostIndex / cols); // Calculate the row (ghost position divided by number of columns) + const ghostCol = ghostIndex % cols; // Calculate the column by getting the remainder of the ghost position divided by number of columns + const pacmanRow = Math.floor(pacmanIndex / cols); // Calculate the row (pacman position divided by number of columns) + const pacmanCol = pacmanIndex % cols; // Calculate the column by getting the remainder of the pacman position divided by number of columns + return Math.abs(ghostRow - pacmanRow) + Math.abs(ghostCol - pacmanCol); // Return the absolute difference between the rows and columns + }; + + const chooseDirection = () => { // Function to choose the direction + const pacmanIndex = grid.findIndex(cell => cell.classList.contains('pacman')); // Find the index of the pacman + const validDirections = directions.filter(direction => { // Filter the directions + const nextMove = this.currentIndex + direction; // Calculate the next move by adding the direction to the current index + return !grid[nextMove].classList.contains('wall') && !grid[nextMove].classList.contains('ghost'); // Return true if the next move is not a wall or ghost + }); - // 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'); + validDirections.sort((dir1, dir2) => { // Sort the valid directions + const nextMove1 = this.currentIndex + dir1; // Calculate the next move for direction 1 + const nextMove2 = this.currentIndex + dir2; // Calculate the next move for direction 2 + return distanceToPacman(nextMove1, pacmanIndex) - distanceToPacman(nextMove2, pacmanIndex); // Return the difference in distance + }); + + return validDirections.length > 0 ? validDirections[0] : null; // Return the first valid direction or null + }; + + let direction = chooseDirection(); // Choose the direction + + this.timerId = setInterval(() => { // Set an interval to move the ghost + if (!gameOver && direction !== null) { // If the game is not over and there is a direction + const nextMove = this.currentIndex + direction; // Calculate the next move by adding the direction to the current index + + if (!grid[nextMove].classList.contains('wall') && !grid[nextMove].classList.contains('ghost')) { // If the next move is not a wall or ghost + grid[this.currentIndex].removeChild(this.ghostElement); // Remove the ghost element from the grid + this.currentIndex = nextMove; // Update the current index to the next move + grid[this.currentIndex].appendChild(this.ghostElement); // Append the ghost element to the grid + } else { // If the next move is a wall or ghost + direction = chooseDirection(); // Choose a new direction + } + if (this.currentIndex === pacmanCurrentIndex) { // If the ghost reaches the pacman + if (powerPelletActive) { // If the power-pellet is active + // Pac-Man eats the ghost + this.resetPosition(); // Reset ghost position + score += 200; // Increase score for eating a ghost + document.getElementById('scoreValue').textContent = score; // Update the score display + showScoreIndicator('+200', pacmanCurrentIndex); // Show score indicator + const ghostEatenSoundInstance = ghostEatenSound.cloneNode(); // Clone the sound element + ghostEatenSoundInstance.play(); // Play the cloned sound + } else { // If the power-pellet is not active + lives--; // Decrease the number of lives by 1 + updateLivesDisplay(); // Update the lives display + + if (lives === 0) { // If the player has no lives left + gameOver = true; // Set the game over flag to true + endGame(); // End the game + } else { // if the player has lives left + grid[pacmanCurrentIndex].classList.remove('pacman'); // Remove the pacman class + pacmanCurrentIndex = 21; // Reset the pacman position + grid[pacmanCurrentIndex].classList.add('pacman'); // Add the pacman class } } } - }, 200); // Move Ghost every 200ms - } - stop() { - clearInterval(this.timerId); // Stop the ghost movement - } + // Handle portal logic for ghosts + if (this.currentIndex % cols === 0) { // If the ghost is at the left portal + this.currentIndex += cols - 1; // Move to the right portal + } else if (this.currentIndex % cols === cols - 1) { // If the ghost is at the right portal + this.currentIndex -= cols - 1; // Move to the left portal + } + } + }, this.currentSpeed); // Use the current speed } - // Create ghosts - const ghost1 = new Ghost(209, 'red'); // Place the first ghost - const ghost2 = new Ghost(229, 'blue'); // Place the second ghost + stop() { + clearInterval(this.timerId); // Stop the ghost movement when the game is over + } + } + + // Function to show score indicator + const showScoreIndicator = (text, index) => { // Function to show the score indicator + const indicator = document.createElement('div'); // Create a new div element + indicator.classList.add('score-indicator'); // Add the score indicator class + indicator.textContent = text; // Set the text content of the indicator + indicator.style.transform = 'rotate(0deg)'; // Prevent rotation + grid[index].appendChild(indicator); // Append the indicator to the grid - // Start ghost movement + setTimeout(() => { // Set a timeout to remove the indicator + indicator.remove(); + }, 1000); // Remove the indicator after 1 second + }; + + // Create the ghosts + const ghost1 = new Ghost(209, 'red'); // Set the start index and color for the ghost + const ghost2 = new Ghost(229, 'blue'); + const ghost3 = new Ghost(249, 'pink'); + const ghosts = [ghost1, ghost2, ghost3]; // Add all ghosts to an array + + setTimeout(() => { ghost1.moveGhost(); + }, 5000); // Start moving after 5 seconds + + setTimeout(() => { ghost2.moveGhost(); + }, 15000); // Start moving after 15 seconds - // 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}`); + setTimeout(() => { + ghost3.moveGhost(); + }, 30000); // Start moving after 30 seconds + + const lifeIcons = [ // Array of life icons + document.getElementById('life1'), + document.getElementById('life2'), + document.getElementById('life3') + ]; + + const updateLivesDisplay = () => { // Function to update the lives display + console.log('Updating lives display. Current lives:', lives); + for (let i = 0; i < lifeIcons.length; i++) { // Loop through each life icon + if (i < lives) { // If the index is less than the number of lives + lifeIcons[i].style.display = 'inline-block'; // Display the life icon + } else { // If the index is greater than or equal to the number of lives + 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 + const checkCollision = () => { // Function to check for collision + ghosts.forEach(ghost => { // Loop through each ghost + if (ghost.currentIndex === pacmanCurrentIndex) { // If the ghost index is the same as the pacman index + if (powerPelletActive) { // If the power-pellet is active + // Pac-Man eats the ghost + ghost.resetPosition(); // Reset ghost position + score += 200; // Increase score for eating a ghost + document.getElementById('scoreValue').textContent = score; + showScoreIndicator('+200', pacmanCurrentIndex); // Show score indicator + } else { // If the power-pellet is not active + lives--; // Decrease the number of lives by 1 + updateLivesDisplay(); // Update the lives display + + if (lives === 0) { // If the player has no lives left + gameOver = true; // Set the game over flag to true + endGame(); // End the game + } else { // If the player has lives left + grid[pacmanCurrentIndex].classList.remove('pacman'); // Remove the pacman class + pacmanCurrentIndex = 21; // Reset the pacman position + grid[pacmanCurrentIndex].classList.add('pacman'); // Add the pacman class + } } } - }; - - // Check for collision on Pac-Man movement - setInterval(checkCollision, 100); // Check collision every 100ms + }); + }; + + // Check for collision on Pac-Man movement + setInterval(checkCollision, 100); // Check collision every 100ms + + // Function to randomly turn a pac-dot into a power-pellet + const turnPacDotIntoPowerPellet = () => { + // Check if there is already a power-pellet on the grid + const existingPowerPellet = grid.some(cell => cell.classList.contains('power-pellet')); + if (existingPowerPellet) return; // Exit if there is already a power-pellet + + const pacDotIndices = grid // Get the indices (positions) of all pac-dots + .map((cell, index) => cell.classList.contains('pac-dot') ? index : -1) // Map the indices to -1 if they are not pac-dots + .filter(index => index !== -1); // Filter out the -1 values + + if (pacDotIndices.length > 0) { // If there are pac-dots + const randomIndex = pacDotIndices[Math.floor(Math.random() * pacDotIndices.length)]; // Choose a random pac-dot index + grid[randomIndex].classList.remove('pac-dot'); // Delete pac-dot class + grid[randomIndex].classList.add('power-pellet'); // Add new power-pellet class + totalPacDots--; // Subtract 1 from the total number of pac-dots + totalPowerPellets++; // Add 1 to the total number of power-pellets + } + }; + + // Turn a random pac-dot into a power-pellet every 30 seconds + powerPelletSpawnTimer = setInterval(turnPacDotIntoPowerPellet, 30000); + + // Function to make ghosts dark blue and slow + const activatePowerPelletEffect = () => { // Function to activate the power-pellet effect + powerPelletActive = true; // Set the power-pellet flag to true + clearTimeout(powerPelletTimer); // Stop the previous power-pellet timer + clearInterval(powerPelletSpawnTimer); // Stop spawning power-pellets + + // Scare the ghosts + ghosts.forEach(ghost => ghost.scare()); + + // Loop the power-up sound + powerUpSound.loop = true + powerUpSound.play(); + + // After 10 seconds, deactivate the power-pellet effect + powerPelletTimer = setTimeout(() => { // Set a timeout to deactivate the power-pellet effect + powerPelletActive = false; // Set the power-pellet flag to false + ghosts.forEach(ghost => ghost.unscare()); // Go through each ghost and unscare them + + // Restart the power-pellet spawn timer after 30 seconds + powerPelletSpawnTimer = setInterval(turnPacDotIntoPowerPellet, 30000); + + // Stop the power-up sound + powerUpSound.pause(); + powerUpSound.currentTime = 0; // Reset the sound to the beginning + }, 10000); // Power pellet effect lasts for 10 seconds + }; + + + // Event listener for Pac-Man eating a power-pellet + grid.forEach(cell => { // Loop through each cell in the grid + cell.addEventListener('pacmanEatPowerPellet', () => { // When Pac-Man eats a power-pellet + activatePowerPelletEffect(); // Activate the power-pellet effect function + }); }); + // Start the game loop interval + gameLoop = setInterval(movePacman, 200); // Move Pac-Man every 200ms +}; + +// Start the game when the start button is clicked +document.getElementById('startGameButton').addEventListener('click', () => { // When the start button is clicked + document.getElementById('startGameOverlay').style.display = 'none'; // Hide the start overlay + initializeGame(); // Initialize the game +}); + // Play the start sound when the start overlay is displayed + startSound.play(); +}); diff --git a/Games/Pac_Man_Game/sounds/eat_fruit.wav b/Games/Pac_Man_Game/sounds/eat_fruit.wav new file mode 100644 index 0000000000..420c02b7a0 Binary files /dev/null and b/Games/Pac_Man_Game/sounds/eat_fruit.wav differ diff --git a/Games/Pac_Man_Game/sounds/game_over.wav b/Games/Pac_Man_Game/sounds/game_over.wav new file mode 100644 index 0000000000..47f21ac751 Binary files /dev/null and b/Games/Pac_Man_Game/sounds/game_over.wav differ diff --git a/Games/Pac_Man_Game/sounds/game_start.wav b/Games/Pac_Man_Game/sounds/game_start.wav new file mode 100644 index 0000000000..5a44df0076 Binary files /dev/null and b/Games/Pac_Man_Game/sounds/game_start.wav differ diff --git a/Games/Pac_Man_Game/sounds/ghost_eaten.wav b/Games/Pac_Man_Game/sounds/ghost_eaten.wav new file mode 100644 index 0000000000..30ae4a363c Binary files /dev/null and b/Games/Pac_Man_Game/sounds/ghost_eaten.wav differ diff --git a/Games/Pac_Man_Game/sounds/pacman_eat.wav b/Games/Pac_Man_Game/sounds/pacman_eat.wav new file mode 100644 index 0000000000..d3a800953f Binary files /dev/null and b/Games/Pac_Man_Game/sounds/pacman_eat.wav differ diff --git a/Games/Pac_Man_Game/sounds/power_up.wav b/Games/Pac_Man_Game/sounds/power_up.wav new file mode 100644 index 0000000000..bed8e582d7 Binary files /dev/null and b/Games/Pac_Man_Game/sounds/power_up.wav differ diff --git a/Games/Pac_Man_Game/style.css b/Games/Pac_Man_Game/style.css index 6e562ce6c1..0e432558f1 100644 --- a/Games/Pac_Man_Game/style.css +++ b/Games/Pac_Man_Game/style.css @@ -1,114 +1,191 @@ body { /* Center align the content vertically and horizontally */ display: flex; + flex-direction: column; + align-items: center; justify-content: center; align-items: center; /* Set the height of the body to 100% of the viewport height */ height: 100vh; /* Remove margin to prevent unwanted spacing */ margin: 0; - /* Set background color to black */ - background-color: #000; + background-color: black; + color: white; + font-family: Arial, sans-serif; +} + +#gameBoard { /* Adjust the size of the game board as needed */ + display: grid; /* Use CSS Grid for layout */ + grid-template-columns: repeat(20, 20px); /* Create a grid with 20 columns */ + grid-template-rows: repeat(24, 20px); /* Create a grid with 24 rows */ + background-color: black; +} + +#startGameOverlay { /* Overlay to display the start game button */ + position: fixed; /* Fixed position to cover the entire viewport */ + top: 0; /* Position from the top */ + left: 0; /* Position from the left */ + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.8); /* Semi-transparent background */ + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; /* Ensure it is on top of other elements */ } -#gameBoard { - /* Create a grid layout for the game board */ - display: grid; - /* Define 20 columns each with a width of 30px */ - grid-template-columns: repeat(20, 30px); - /* Define 20 rows each with a height of 30px */ - grid-template-rows: repeat(20, 30px); - /* Set the gap between grid items */ - gap: 2px; +#startGameButton { /* Start game button styling */ + cursor: pointer; /* Change cursor to pointer on hover */ + width: 400px; + height: auto; } -.cell { - width: 30px; - height: 30px; +.game-over-message { /* Styling for the game over message */ + color: white; + text-align: center; } -.wall { - background-color: blue; +#restartGameButton { /* Restart game button styling */ + padding: 10px 20px; + font-size: 16px; + background-color: #ffcc00; + border: none; + cursor: pointer; /* Change cursor to pointer on hover */ + border-radius: 5px; } -/*Space for the pac dots*/ -.pac-dot { - background-color: black; - /* Center align content vertically and horizontally */ +#restartGameButton:hover { /* Hover effect for the restart game button */ + background-color: #ff9900; +} + +.cell { /* Styling for each cell in the game board */ + width: 20px; + height: 20px; display: flex; - justify-content: center; align-items: center; + justify-content: center; + background-color: black; /* Set the background color of the cell */ } -/*Pac dots themselves*/ -.pac-dot::after { - /*Create circle*/ - content: ''; - width: 10px; - height: 10px; +.wall { /* Styling for the walls */ + background-color: black; + border: 2px solid blue; + box-sizing: border-box; /* Include border in the width and height of the cell */ +} + +.pac-dot { /* Styling for the pac-dots */ + width: 5px; + height: 5px; background-color: white; - /*Create a rounded shape*/ - border-radius: 50%; + border-radius: 50%; /* Create a circular shape */ + margin: auto; /* Center the dot within the cell */ } -/*Pac-Man*/ -.pacman { +.power-pellet { /* Styling for the power pellets */ + width: 10px; + height: 10px; background-color: yellow; - /*Create a round shape*/ - border-radius: 50%; + border-radius: 50%; /* Create a circular shape */ + margin: auto; /* Center the pellet within the cell */ } -/*Score display*/ -#score { - font-size: 24px; - font-weight: bold; - color: white; - background-color: black; - padding: 10px; +/* General styling for the fruits*/ +.fruit { + width: 20px; + height: 20px; + position: absolute; + background-size: contain; + background-repeat: no-repeat; + z-index: 10; } -/*Score value*/ -#scoreValue { - color: yellow; +/* Specific styling for each fruit */ +.fruit.apple { + background-image: url('./pixels/fruit-apple.png'); +} + +.fruit.orange { + background-image: url('./pixels/fruit-orange.png'); +} + +.fruit.cherry { + background-image: url('./pixels/fruit-cherry.png'); +} + +.fruit.strawberry { + background-image: url('./pixels/fruit-strawberry.png'); } +.pacman { /* Styling for the pacman */ + width: 20px; + height: 20px; + background-image: url('./pixels/pacman.gif'); + background-size: cover; /* Ensure the image covers the entire cell */ +} -/*Ghosts*/ .ghost { - /*Set background color dynamically*/ - background-color: var(--ghost-color); + width: 20px; + height: 20px; + background-size: cover; /* Ensure the image covers the entire cell */ + position: absolute; /* Position the ghost absolutely within the cell so it can move freely */ + transform: rotate(0deg); /* Prevent rotation of the score indicator */ + transform-origin: center; /* Set the rotation origin to the center of the ghost */ } -/*Red ghost*/ -.red { - --ghost-color: red; +.ghost.red { + background-image: url('./pixels/ghost-red.png'); + transform: rotate(0deg); /* Prevent rotation of the score indicator */ } -/*Blue ghost*/ -.blue { - --ghost-color: green; +.ghost.blue { + background-image: url('./pixels/ghost-blue.png'); + transform: rotate(0deg); /* Prevent rotation of the score indicator */ } -/*Lives*/ -#livesContainer { - margin-top: 20px; - font-size: 20px; +.ghost.pink { + background-image: url('./pixels/ghost-pink.png'); + transform: rotate(0deg); /* Prevent rotation of the score indicator */ + transform-origin: center; +} + +.ghost.scared { + background-image: url('./pixels/ghosts-slow.gif'); + transform: rotate(0deg); /* Prevent rotation of the score indicator */ + transform-origin: center; +} + +#score { + margin-top: 20px; /* Add margin to separate the score from the game board */ +} + +.score-indicator { /* Styling for the score indicator */ + color: yellow; + font-size: 16px; font-weight: bold; - color: white; + animation: fadeOut 1s forwards; } -.life { - display: inline-block; - width: 30px; - height: 30px; - background-color: yellow; - border: 2px solid white; - border-radius: 50%; - margin-right: 10px; +@keyframes fadeOut { /* Animation to fade out the score indicator */ + 0% { + opacity: 1; /* Start with full opacity */ + transform: translateY(0); /* Start at the original position */ + } + 100% { /* End with zero opacity and move up */ + opacity: 0; /* End with zero opacity */ + transform: translateY(-20px); /* Move up by 20px */ + } } -/*Hide life*/ -.life.hidden { - display: none; +#livesContainer { + margin-top: 10px; /* Add margin to separate the lives from the score */ } + +.life { /* Styling for each life indicator */ + display: inline-block; /* Display the lives horizontally */ + width: 20px; + height: 20px; + background-color: yellow; + border-radius: 50%; + margin-left: 5px; +} \ No newline at end of file diff --git a/README.md b/README.md index 7c75d9bc0b..fcf173f6ac 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ This repository also provides one such platforms where contributers come over an | Game | Game | Game | Game | Game | +<<<<<<< HEAD | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | --- | @@ -115,6 +116,10 @@ This repository also provides one such platforms where contributers come over an | [Bulls_And_Cows_New](https://github.com/kunjgit/GameZone/tree/main/Games/Bulls_And_Cows_New) | [Find The Number](https://github.com/kunjgit/GameZone/tree/main/Games/Find_the_Number) | [Guess_That_Pokemon](https://github.com/kunjgit/GameZone/tree/main/Games/Guess_That_Pokemon) +======= +| ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | [Pac_Man]() +| [Master Typing](https://github.com/kunjgit/GameZone/tree/main/Games/Master_Typing) | [Treasure Hunt](https://github.com/Antiquely3059/GameZone/tree/main/Games/Treasure%20Hunt) | [Virtual Pet](https://github.com/Antiquely3059/GameZone/tree/main/Games/Virtual_Pet) | [MazeRunner](https://github.com/kunjgit/GameZone/tree/main/Games/MazeRunner) | [Ping_Pong_Singleplayer](https://github.com/kunjgit/GameZone/tree/main/Games/Ping_Pong_Singleplayer) | | +>>>>>>> parent of 772df1c4 (Added link) | [Tilting Maze](https://github.com/kunjgit/GameZone/tree/main/Games/Tilting_Maze) | [Simon Game Challenge](https://github.com/kunjgit/GameZone/tree/main/Games/Simon_Game_Challenge) | [Snake Game](https://github.com/kunjgit/GameZone/tree/main/Games/Snake_Game) | [Dino Runner Game](https://github.com/kunjgit/GameZone/tree/main/Games/Dino_Runner_Game) | | [Whack a Mole](https://github.com/kunjgit/GameZone/tree/main/Games/Whack_a_Mole) | [Doraemon Jump](https://github.com/kunjgit/GameZone/tree/main/Games/Doraemon_Jump) | [Black Jack](https://github.com/kunjgit/GameZone/tree/main/Games/Black_Jack) | [Memory Game](https://github.com/kunjgit/GameZone/tree/main/Games/Memory_Game) | [Word Guessing Game](https://github.com/kunjgit/GameZone/tree/main/Games/Word_Guessing_Game) | [Ludo Game](https://github.com/kunjgit/GameZone/tree/main/Games/Ludo_Game) | [Piano Game](https://github.com/kunjgit/GameZone/tree/main/Games/Piano) | [Atari Breakout](https://github.com/kunjgit/GameZone/tree/main/Games/Atari_Breakout) | [Dinosaur Game](https://github.com/kunjgit/GameZone/tree/main/Games/Chrome_Dinosaur_Game) | [Guess The Colour by RGB Game](https://github.com/kunjgit/GameZone/tree/main/Games/Colour_Guessing_Game) | diff --git a/assets/images/Pac_Man_Game.png b/assets/images/Pac_Man_Game.png new file mode 100644 index 0000000000..e2a5d12e26 Binary files /dev/null and b/assets/images/Pac_Man_Game.png differ diff --git a/assets/images/Pac_Man_Thumbnail.png b/assets/images/Pac_Man_Thumbnail.png deleted file mode 100644 index 2fb1a59e20..0000000000 Binary files a/assets/images/Pac_Man_Thumbnail.png and /dev/null differ diff --git a/assets/js/gamesData.json b/assets/js/gamesData.json index 07dfe9fdd9..fd5112fdf4 100644 --- a/assets/js/gamesData.json +++ b/assets/js/gamesData.json @@ -2733,7 +2733,7 @@ "547":{ "gameTitle" : "Pac Man Game", "gameUrl": "Pac_Man_Game", - "thumbnailUrl":"Pac_Man_Thumbnail.png" + "thumbnailUrl":"Pac_Man_Game.png" }, "548":{ "gameTitle" : "Pattern Creation Game",