From eab98868ef87a823a19c6acadc35c7b27d1fc200 Mon Sep 17 00:00:00 2001 From: thedevilbox Date: Mon, 1 Dec 2025 22:46:43 +0100 Subject: [PATCH] amelioration jeu --- game.js | 157 ++++++++++++++++++++++++++++++++++++++++++++++++----- index.html | 4 ++ style.css | 39 ++++++++++++- 3 files changed, 185 insertions(+), 15 deletions(-) diff --git a/game.js b/game.js index f046345..ea5cefb 100644 --- a/game.js +++ b/game.js @@ -146,12 +146,16 @@ let maze = originalMaze.map(row => [...row]); let score = 0; let level = 1; let gameRunning = true; +let isPaused = false; let totalDots = 0; let cherriesEaten = 0; let isChangingLevel = false; let cherryEatenRecently = false; let cherryEatenTimer = 0; let lives = 3; +let dotsRemainingElement = document.getElementById('dotsRemaining'); +let pursuitIndicator = document.getElementById('pursuitIndicator'); +let pursuitTimerElement = document.getElementById('pursuitTimer'); class Pacman { constructor() { @@ -169,7 +173,7 @@ class Pacman { } update() { - if (!gameRunning) return; + if (!gameRunning || isPaused) return; this.mouthAngle += 0.2; if (this.mouthAngle > Math.PI * 2) { @@ -232,6 +236,9 @@ class Pacman { score += 10; scoreElement.textContent = score; totalDots--; + if (dotsRemainingElement) { + dotsRemainingElement.textContent = totalDots; + } } else if (maze[this.y][this.x] === BONUS_CHERRY) { if (isChangingLevel) { console.log('Changement de niveau en cours, cerise ignorée'); @@ -248,6 +255,18 @@ class Pacman { cherryEatenRecently = true; cherryEatenTimer = Math.max(150, 300 - (level - 1) * 20); + // Rendre tous les fantômes vulnérables + const vulnerableTime = Math.max(180, 360 - (level - 1) * 30); + for (let ghost of ghosts) { + ghost.isVulnerable = true; + ghost.vulnerableTimer = vulnerableTime; + } + + // Afficher l'indicateur de poursuite + if (pursuitIndicator) { + pursuitIndicator.style.display = 'block'; + } + console.log('Après incrémentation, cherriesEaten:', cherriesEaten, 'isChangingLevel:', isChangingLevel); if (cherriesEaten >= 4 && !isChangingLevel) { @@ -300,6 +319,10 @@ class Ghost { this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2; this.moveCounter = 0; this.moveInterval = 30; + this.isVulnerable = false; + this.vulnerableTimer = 0; + this.startX = x; + this.startY = y; } updateSpeed() { @@ -307,12 +330,24 @@ class Ghost { } update() { - if (!gameRunning) return; + if (!gameRunning || isPaused) return; + + // Gestion de la vulnérabilité + if (this.isVulnerable) { + this.vulnerableTimer--; + if (this.vulnerableTimer <= 0) { + this.isVulnerable = false; + } + } if (cherryEatenTimer > 0) { cherryEatenTimer--; } else { cherryEatenRecently = false; + // Rendre les fantômes vulnérables quand une cerise est mangée + if (!this.isVulnerable && cherryEatenTimer === 0) { + // La vulnérabilité est gérée dans collectDot() + } } this.moveInterval = Math.max(15, 30 - (level - 1) * 2); @@ -423,7 +458,13 @@ class Ghost { const size = CELL_SIZE * 0.75; - ctx.fillStyle = this.color; + // Si vulnérable, afficher en bleu clignotant + if (this.isVulnerable) { + const flash = Math.floor(this.vulnerableTimer / 10) % 2; + ctx.fillStyle = flash === 0 ? '#0000ff' : '#ffffff'; + } else { + ctx.fillStyle = this.color; + } ctx.strokeStyle = '#000000'; ctx.lineWidth = 2; @@ -579,6 +620,10 @@ function countDots() { } } } + // Mettre à jour l'affichage + if (dotsRemainingElement) { + dotsRemainingElement.textContent = totalDots; + } } function drawMaze() { @@ -611,7 +656,7 @@ function drawMaze() { } function checkCollisions() { - if (!gameRunning) return; + if (!gameRunning || isPaused) return; for (let ghost of ghosts) { const distance = Math.sqrt( @@ -620,16 +665,31 @@ function checkCollisions() { ); if (distance < CELL_SIZE * 0.6) { - lives--; - updateLivesDisplay(); - - if (lives <= 0) { - gameRunning = false; - statusElement.textContent = 'Game Over !'; - showGameOver(); - saveScore(); + if (ghost.isVulnerable) { + // Manger le fantôme + score += 200; + scoreElement.textContent = score; + ghost.isVulnerable = false; + ghost.vulnerableTimer = 0; + // Réinitialiser la position du fantôme + ghost.x = ghost.startX; + ghost.y = ghost.startY; + ghost.pixelX = ghost.x * CELL_SIZE + CELL_SIZE / 2; + ghost.pixelY = ghost.y * CELL_SIZE + CELL_SIZE / 2; + ghost.direction = Math.floor(Math.random() * 4); } else { - restartCurrentLevel(); + // Perdre une vie + lives--; + updateLivesDisplay(); + + if (lives <= 0) { + gameRunning = false; + statusElement.textContent = 'Game Over !'; + showGameOver(); + saveScore(); + } else { + restartCurrentLevel(); + } } } } @@ -644,9 +704,40 @@ function gameLoop() { } drawMaze(); + + // Gestion de la pause + if (isPaused) { + ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#ffd700'; + ctx.font = 'bold 48px "Press Start 2P"'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('PAUSE', canvas.width/2, canvas.height/2); + ctx.font = 'bold 16px "Press Start 2P"'; + ctx.fillText('Appuyez sur ESPACE ou ECHAP', canvas.width/2, canvas.height/2 + 40); + requestAnimationFrame(gameLoop); + return; + } + pacman.update(); pacman.draw(); + // Mettre à jour l'indicateur de poursuite + if (pursuitIndicator && cherryEatenTimer > 0) { + const seconds = Math.ceil(cherryEatenTimer / 60); + if (pursuitTimerElement) { + pursuitTimerElement.textContent = seconds; + } + // Vérifier si tous les fantômes sont encore vulnérables + const allVulnerable = ghosts.every(g => g.isVulnerable); + if (!allVulnerable && pursuitIndicator.style.display !== 'none') { + pursuitIndicator.style.display = 'none'; + } + } else if (pursuitIndicator) { + pursuitIndicator.style.display = 'none'; + } + for (let ghost of ghosts) { ghost.update(); ghost.draw(); @@ -705,11 +796,16 @@ function restartCurrentLevel() { for (let ghost of ghosts) { ghost.updateSpeed(); + ghost.isVulnerable = false; + ghost.vulnerableTimer = 0; } cherriesEaten = 0; cherryEatenRecently = false; cherryEatenTimer = 0; + if (pursuitIndicator) { + pursuitIndicator.style.display = 'none'; + } statusElement.textContent = `Niveau ${level} - Recommencement !`; statusElement.style.color = '#ff6b6b'; @@ -796,8 +892,15 @@ function nextLevel() { for (let ghost of ghosts) { ghost.updateSpeed(); + ghost.isVulnerable = false; + ghost.vulnerableTimer = 0; } + cherryEatenTimer = 0; + if (pursuitIndicator) { + pursuitIndicator.style.display = 'none'; + } + placeBonuses(); console.log('Bonus placés, nombre:', bonuses.length); @@ -1024,6 +1127,7 @@ function initGame() { level = 1; lives = 3; cherriesEaten = 0; + isPaused = false; scoreElement.textContent = score; levelElement.textContent = level; updateLivesDisplay(); @@ -1032,6 +1136,9 @@ function initGame() { statusElement.style.color = '#ffd700'; restartBtn.style.display = 'none'; hideGameOver(); + if (pursuitIndicator) { + pursuitIndicator.style.display = 'none'; + } pacman = new Pacman(); pacman.speed = pacman.baseSpeed * (1 + (level - 1) * 0.05); @@ -1042,6 +1149,12 @@ function initGame() { for (let ghost of ghosts) { ghost.updateSpeed(); + ghost.isVulnerable = false; + ghost.vulnerableTimer = 0; + } + + if (pursuitIndicator) { + pursuitIndicator.style.display = 'none'; } placeBonuses(); @@ -1050,7 +1163,23 @@ function initGame() { } document.addEventListener('keydown', (e) => { - if (!gameRunning) return; + // Système de pause + if (e.key === 'Escape' || e.key === ' ') { + if (gameRunning && !isChangingLevel) { + isPaused = !isPaused; + if (isPaused) { + statusElement.textContent = 'PAUSE'; + statusElement.style.color = '#ffd700'; + } else { + statusElement.textContent = 'En jeu'; + statusElement.style.color = '#ffd700'; + } + e.preventDefault(); + return; + } + } + + if (!gameRunning || isPaused) return; switch(e.key) { case 'ArrowUp': diff --git a/index.html b/index.html index 2ec770e..da4cefc 100644 --- a/index.html +++ b/index.html @@ -45,8 +45,12 @@
Score: 0
Niveau: 1
Vies:
+
Pastilles: 0
Prêt à jouer
+ diff --git a/style.css b/style.css index 134a0e6..b2ca2d6 100644 --- a/style.css +++ b/style.css @@ -452,7 +452,7 @@ h1 { flex-wrap: wrap; } -.score, .level, .lives { +.score, .level, .lives, .dots-remaining { font-size: 0.9em; font-weight: bold; background: rgba(0, 0, 0, 0.4); @@ -462,6 +462,10 @@ h1 { transition: all 0.3s; } +.dots-remaining { + color: #00ffff; +} + .score.updated { animation: scoreUp 0.3s ease-out; } @@ -490,6 +494,39 @@ h1 { text-shadow: 0 0 10px rgba(255, 215, 0, 0.5); } +/* === INDICATEUR DE poursuite === */ +.pursuit-indicator { + margin: 15px auto; + padding: 12px 25px; + background: linear-gradient(180deg, rgba(255, 0, 0, 0.3), rgba(255, 0, 0, 0.1)); + border: 2px solid #ff0000; + border-radius: 10px; + text-align: center; + animation: pursuitPulse 1s ease-in-out infinite; + max-width: 300px; +} + +@keyframes pursuitPulse { + 0%, 100% { + box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); + } + 50% { + box-shadow: 0 0 20px rgba(255, 0, 0, 0.8); + } +} + +.pursuit-text { + font-size: 0.8em; + color: #ff0000; + text-shadow: 0 0 10px rgba(255, 0, 0, 0.8); +} + +#pursuitTimer { + color: #ffff00; + font-weight: bold; + font-size: 1.2em; +} + /* === CANVAS AVEC GLOW ET EFFET 3D === */ #gameCanvas { border: 4px solid #ffd700;