Système de vies: 3 vies avec affichage en cœurs, redémarrage du niveau en cas de perte

This commit is contained in:
2025-11-28 19:20:23 +01:00
parent f075234e6b
commit 28063d9ba8
3 changed files with 97 additions and 4 deletions

88
game.js
View File

@ -2,6 +2,7 @@ const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score'); const scoreElement = document.getElementById('score');
const levelElement = document.getElementById('level'); const levelElement = document.getElementById('level');
const livesElement = document.getElementById('lives');
const statusElement = document.getElementById('status'); const statusElement = document.getElementById('status');
const restartBtn = document.getElementById('restartBtn'); const restartBtn = document.getElementById('restartBtn');
const usernameInput = document.getElementById('username'); const usernameInput = document.getElementById('username');
@ -131,6 +132,7 @@ let cherriesEaten = 0;
let isChangingLevel = false; let isChangingLevel = false;
let cherryEatenRecently = false; let cherryEatenRecently = false;
let cherryEatenTimer = 0; let cherryEatenTimer = 0;
let lives = 3;
class Pacman { class Pacman {
constructor() { constructor() {
@ -597,10 +599,17 @@ function checkCollisions() {
); );
if (distance < CELL_SIZE * 0.6) { if (distance < CELL_SIZE * 0.6) {
gameRunning = false; lives--;
statusElement.textContent = 'Game Over !'; updateLivesDisplay();
restartBtn.style.display = 'block';
saveScore(); if (lives <= 0) {
gameRunning = false;
statusElement.textContent = 'Game Over !';
restartBtn.style.display = 'block';
saveScore();
} else {
restartCurrentLevel();
}
} }
} }
} }
@ -631,6 +640,75 @@ function gameLoop() {
} }
} }
function updateLivesDisplay() {
const hearts = livesElement.querySelectorAll('.heart');
hearts.forEach((heart, index) => {
if (index < lives) {
heart.style.opacity = '1';
} else {
heart.style.opacity = '0.3';
}
});
}
function restartCurrentLevel() {
if (isChangingLevel) return;
console.log('Redémarrage du niveau actuel');
isChangingLevel = true;
gameRunning = false;
requestAnimationFrame(() => {
const currentLevel = level;
const mazeIndex = (currentLevel - 1) % mazeVariants.length;
const currentMaze = mazeVariants[mazeIndex];
maze = [];
for (let i = 0; i < currentMaze.length; i++) {
maze[i] = [...currentMaze[i]];
}
fillEmptySpaces();
randomizeMaze();
countDots();
bonuses = [];
placeBonuses();
pacman = new Pacman();
pacman.speed = pacman.baseSpeed * (1 + (level - 1) * 0.05);
ghosts[0] = new Ghost(14, 11, '#ff0000');
ghosts[1] = new Ghost(15, 11, '#ff00ff');
ghosts[2] = new Ghost(14, 12, '#00ffff');
ghosts[3] = new Ghost(15, 12, '#ffa500');
for (let ghost of ghosts) {
ghost.updateSpeed();
}
cherriesEaten = 0;
cherryEatenRecently = false;
cherryEatenTimer = 0;
statusElement.textContent = `Niveau ${level} - Recommencement !`;
statusElement.style.color = '#ff6b6b';
drawMaze();
pacman.draw();
for (let ghost of ghosts) {
ghost.draw();
}
setTimeout(() => {
isChangingLevel = false;
gameRunning = true;
statusElement.textContent = 'En jeu';
statusElement.style.color = '#ffd700';
gameLoop();
}, 2000);
});
}
function nextLevel() { function nextLevel() {
console.log('=== nextLevel() appelée ==='); console.log('=== nextLevel() appelée ===');
console.log('gameRunning:', gameRunning, 'isChangingLevel:', isChangingLevel); console.log('gameRunning:', gameRunning, 'isChangingLevel:', isChangingLevel);
@ -921,9 +999,11 @@ function initGame() {
countDots(); countDots();
score = 0; score = 0;
level = 1; level = 1;
lives = 3;
cherriesEaten = 0; cherriesEaten = 0;
scoreElement.textContent = score; scoreElement.textContent = score;
levelElement.textContent = level; levelElement.textContent = level;
updateLivesDisplay();
gameRunning = true; gameRunning = true;
statusElement.textContent = 'En jeu'; statusElement.textContent = 'En jeu';
statusElement.style.color = '#ffd700'; statusElement.style.color = '#ffd700';

View File

@ -17,6 +17,7 @@
<div class="game-info"> <div class="game-info">
<div class="score">Score: <span id="score">0</span></div> <div class="score">Score: <span id="score">0</span></div>
<div class="level">Niveau: <span id="level">1</span></div> <div class="level">Niveau: <span id="level">1</span></div>
<div class="lives">Vies: <span id="lives"><span class="heart"></span><span class="heart"></span><span class="heart"></span></span></div>
<div class="status" id="status">Prêt à jouer</div> <div class="status" id="status">Prêt à jouer</div>
</div> </div>
<canvas id="gameCanvas" width="600" height="600"></canvas> <canvas id="gameCanvas" width="600" height="600"></canvas>

View File

@ -105,6 +105,18 @@ h1 {
color: #ffd700; color: #ffd700;
} }
.lives {
font-size: 1.5em;
font-weight: bold;
}
.lives .heart {
color: #ff0000;
font-size: 1.2em;
margin: 0 2px;
transition: opacity 0.3s;
}
#status { #status {
font-size: 1.2em; font-size: 1.2em;
color: #ffd700; color: #ffd700;