diff --git a/game.js b/game.js index 8bf36b3..18a112f 100644 --- a/game.js +++ b/game.js @@ -13,6 +13,9 @@ const finalScoreElement = document.getElementById('finalScore'); const finalLevelElement = document.getElementById('finalLevel'); const overlayRestartBtn = document.getElementById('overlayRestartBtn'); const confirmUsernameBtn = document.getElementById('confirmUsernameBtn'); +const gameOverUsernameInput = document.getElementById('gameOverUsername'); +const saveScoreBtn = document.getElementById('saveScoreBtn'); +const scoreSavedMsg = document.getElementById('scoreSavedMsg'); // === GESTION DU MENU === const mainMenu = document.getElementById('mainMenu'); @@ -29,6 +32,12 @@ const menuLeaderboard = document.getElementById('menuLeaderboard'); const leaderboardContainer = document.getElementById('leaderboardContainer'); const closeLeaderboardBtn = document.getElementById('closeLeaderboardBtn'); const fullscreenBtn = document.getElementById('fullscreenBtn'); +const customizeBtn = document.getElementById('customizeBtn'); +const customizeModal = document.getElementById('customizeModal'); +const closeCustomizeBtn = document.getElementById('closeCustomizeBtn'); +const saveCustomizeBtn = document.getElementById('saveCustomizeBtn'); +const playerPreviewCanvas = document.getElementById('playerPreviewCanvas'); +const colorOptions = document.querySelectorAll('.color-option'); // Fonction pour vérifier si on est en mode plein écran function isFullscreen() { @@ -37,6 +46,10 @@ function isFullscreen() { } let usernameConfirmed = false; +let gameOverUsername = null; + +// Personnalisation du joueur +let playerColor = localStorage.getItem('playerColor') || 'rainbow'; const CELL_SIZE = 25; const COLS = 30; @@ -240,7 +253,7 @@ let traps = []; let specialZones = []; class Pacman { - constructor() { + constructor(color = null) { this.x = 14; this.y = 23; this.direction = 0; @@ -252,6 +265,7 @@ class Pacman { this.pixelX = this.x * CELL_SIZE + CELL_SIZE / 2; this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2; this.colorAnimation = 0; + this.color = color || playerColor; } update() { @@ -456,8 +470,22 @@ class Pacman { const rotation = [Math.PI * 1.5, 0, Math.PI * 0.5, Math.PI]; ctx.rotate(rotation[this.direction]); - const hue = (this.colorAnimation * 180 / Math.PI) % 360; - ctx.fillStyle = `hsl(${hue}, 100%, 50%)`; + // Utiliser la couleur personnalisée + if (this.color === 'rainbow') { + const hue = (this.colorAnimation * 180 / Math.PI) % 360; + ctx.fillStyle = `hsl(${hue}, 100%, 50%)`; + } else { + const colorMap = { + 'yellow': '#ffd700', + 'red': '#ff4444', + 'blue': '#4444ff', + 'green': '#44ff44', + 'purple': '#aa44ff', + 'orange': '#ff8844', + 'pink': '#ff44aa' + }; + ctx.fillStyle = colorMap[this.color] || '#ffd700'; + } ctx.beginPath(); @@ -1237,7 +1265,7 @@ function checkCollisions() { gameRunning = false; statusElement.textContent = 'Game Over !'; showGameOver(); - saveScore(); + // Le score sera sauvegardé quand l'utilisateur clique sur "Sauvegarder" } else { restartCurrentLevel(); } @@ -1954,9 +1982,15 @@ function getScores() { return scoresJson ? JSON.parse(scoresJson) : []; } -function saveScore() { +function saveScore(usernameForScore = null) { let username; - if (!usernameConfirmed) { + + // Priorité au nom passé en paramètre, puis au nom du Game Over, puis au nom confirmé, sinon "Anonyme" + if (usernameForScore) { + username = usernameForScore.trim() || 'Anonyme'; + } else if (gameOverUsername) { + username = gameOverUsername.trim() || 'Anonyme'; + } else if (!usernameConfirmed) { username = 'Anonyme'; } else { username = usernameInput.value.trim() || 'Anonyme'; @@ -2127,6 +2161,21 @@ usernameInput.addEventListener('keypress', (e) => { function showGameOver() { finalScoreElement.textContent = score; finalLevelElement.textContent = level; + + // Réinitialiser le champ de nom et cacher le message + if (gameOverUsernameInput) { + gameOverUsernameInput.value = usernameInput.value.trim() || ''; + gameOverUsernameInput.disabled = false; + gameOverUsernameInput.focus(); + } + if (saveScoreBtn) { + saveScoreBtn.disabled = false; + } + if (scoreSavedMsg) { + scoreSavedMsg.style.display = 'none'; + } + gameOverUsername = null; // Réinitialiser + gameOverlay.classList.add('active'); restartBtn.style.display = 'block'; } @@ -2135,7 +2184,39 @@ function hideGameOver() { gameOverlay.classList.remove('active'); } +// Sauvegarder le score avec le nom du Game Over +if (saveScoreBtn && gameOverUsernameInput) { + saveScoreBtn.addEventListener('click', () => { + const username = gameOverUsernameInput.value.trim(); + if (username.length === 0) { + alert('Veuillez entrer un nom d\'utilisateur !'); + gameOverUsernameInput.focus(); + return; + } + + gameOverUsername = username; + saveScore(username); + + // Afficher le message de confirmation + if (scoreSavedMsg) { + scoreSavedMsg.style.display = 'block'; + } + + // Désactiver le champ et le bouton + gameOverUsernameInput.disabled = true; + saveScoreBtn.disabled = true; + }); + + // Permettre de sauvegarder avec la touche Entrée + gameOverUsernameInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !saveScoreBtn.disabled) { + saveScoreBtn.click(); + } + }); +} + overlayRestartBtn.addEventListener('click', () => { + hideGameOver(); initGame(); }); @@ -2404,6 +2485,161 @@ if (rulesModal) { }); } +// === GESTION DU MODAL DE PERSONNALISATION === +let selectedColor = playerColor; + +// Ouvrir le modal de personnalisation +if (customizeBtn) { + customizeBtn.addEventListener('click', () => { + if (customizeModal) { + customizeModal.style.display = 'flex'; + selectedColor = playerColor; + updateColorSelection(); + updatePlayerPreview(); + startPreviewAnimation(); + } + }); +} + +// Fermer le modal de personnalisation +if (closeCustomizeBtn) { + closeCustomizeBtn.addEventListener('click', () => { + if (customizeModal) { + customizeModal.style.display = 'none'; + stopPreviewAnimation(); + } + }); +} + +// Fermer en cliquant en dehors du modal +if (customizeModal) { + customizeModal.addEventListener('click', (e) => { + if (e.target === customizeModal) { + customizeModal.style.display = 'none'; + stopPreviewAnimation(); + } + }); +} + +// Gérer la sélection de couleur +if (colorOptions) { + colorOptions.forEach(option => { + option.addEventListener('click', () => { + selectedColor = option.getAttribute('data-color'); + updateColorSelection(); + updatePlayerPreview(); + }); + }); +} + +// Mettre à jour la sélection visuelle +function updateColorSelection() { + if (colorOptions) { + colorOptions.forEach(option => { + if (option.getAttribute('data-color') === selectedColor) { + option.classList.add('active'); + } else { + option.classList.remove('active'); + } + }); + } +} + +// Prévisualisation du joueur +let previewAnimationId = null; +function startPreviewAnimation() { + if (!playerPreviewCanvas) return; + + let angle = 0; + let mouthOpen = true; + + function animate() { + if (!playerPreviewCanvas) return; + const ctx = playerPreviewCanvas.getContext('2d'); + ctx.clearRect(0, 0, playerPreviewCanvas.width, playerPreviewCanvas.height); + + // Fond + ctx.fillStyle = '#000'; + ctx.fillRect(0, 0, playerPreviewCanvas.width, playerPreviewCanvas.height); + + // Dessiner le joueur au centre + ctx.save(); + ctx.translate(playerPreviewCanvas.width / 2, playerPreviewCanvas.height / 2); + + // Couleur + if (selectedColor === 'rainbow') { + angle += 0.05; + const hue = (angle * 180 / Math.PI) % 360; + ctx.fillStyle = `hsl(${hue}, 100%, 50%)`; + } else { + const colorMap = { + 'yellow': '#ffd700', + 'red': '#ff4444', + 'blue': '#4444ff', + 'green': '#44ff44', + 'purple': '#aa44ff', + 'orange': '#ff8844', + 'pink': '#ff44aa' + }; + ctx.fillStyle = colorMap[selectedColor] || '#ffd700'; + } + + // Animation de la bouche + if (Math.floor(angle * 5) % 2 === 0) { + mouthOpen = !mouthOpen; + } + + ctx.beginPath(); + const radius = 40; + if (mouthOpen) { + ctx.arc(0, 0, radius, 0.2, Math.PI * 2 - 0.2); + } else { + ctx.arc(0, 0, radius, 0, Math.PI * 2); + } + ctx.lineTo(0, 0); + ctx.fill(); + + ctx.restore(); + + previewAnimationId = requestAnimationFrame(animate); + } + + animate(); +} + +function stopPreviewAnimation() { + if (previewAnimationId) { + cancelAnimationFrame(previewAnimationId); + previewAnimationId = null; + } +} + +function updatePlayerPreview() { + // L'animation se mettra à jour automatiquement car elle utilise selectedColor +} + +// Sauvegarder la personnalisation +if (saveCustomizeBtn) { + saveCustomizeBtn.addEventListener('click', () => { + playerColor = selectedColor; + localStorage.setItem('playerColor', playerColor); + + // Mettre à jour le joueur actuel si le jeu est en cours + if (pacman) { + pacman.color = playerColor; + } + + // Fermer le modal + if (customizeModal) { + customizeModal.style.display = 'none'; + stopPreviewAnimation(); + } + + // Message de confirmation + alert('Personnalisation sauvegardée !'); + }); +} + // Fermer le classement dans le jeu if (closeLeaderboardBtn) { closeLeaderboardBtn.addEventListener('click', () => { diff --git a/index.html b/index.html index 70b7ccb..68e8a52 100644 --- a/index.html +++ b/index.html @@ -21,6 +21,9 @@ + @@ -87,6 +90,12 @@
Score Final: 0
Niveau Atteint: 1
+