diff --git a/game.js b/game.js index 18a112f..0dbba0e 100644 --- a/game.js +++ b/game.js @@ -38,6 +38,7 @@ const closeCustomizeBtn = document.getElementById('closeCustomizeBtn'); const saveCustomizeBtn = document.getElementById('saveCustomizeBtn'); const playerPreviewCanvas = document.getElementById('playerPreviewCanvas'); const colorOptions = document.querySelectorAll('.color-option'); +const shapeOptions = document.querySelectorAll('.shape-option'); // Fonction pour vérifier si on est en mode plein écran function isFullscreen() { @@ -50,6 +51,7 @@ let gameOverUsername = null; // Personnalisation du joueur let playerColor = localStorage.getItem('playerColor') || 'rainbow'; +let playerShape = localStorage.getItem('playerShape') || 'round'; const CELL_SIZE = 25; const COLS = 30; @@ -253,7 +255,7 @@ let traps = []; let specialZones = []; class Pacman { - constructor(color = null) { + constructor(color = null, shape = null) { this.x = 14; this.y = 23; this.direction = 0; @@ -266,6 +268,7 @@ class Pacman { this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2; this.colorAnimation = 0; this.color = color || playerColor; + this.shape = shape || playerShape; } update() { @@ -471,9 +474,11 @@ class Pacman { ctx.rotate(rotation[this.direction]); // Utiliser la couleur personnalisée + let baseFillColor; if (this.color === 'rainbow') { const hue = (this.colorAnimation * 180 / Math.PI) % 360; - ctx.fillStyle = `hsl(${hue}, 100%, 50%)`; + baseFillColor = `hsl(${hue}, 100%, 50%)`; + ctx.fillStyle = baseFillColor; } else { const colorMap = { 'yellow': '#ffd700', @@ -484,20 +489,78 @@ class Pacman { 'orange': '#ff8844', 'pink': '#ff44aa' }; - ctx.fillStyle = colorMap[this.color] || '#ffd700'; + baseFillColor = colorMap[this.color] || '#ffd700'; + ctx.fillStyle = baseFillColor; } + const size = CELL_SIZE * 0.4; + ctx.beginPath(); - if (this.mouthOpen) { - ctx.arc(0, 0, CELL_SIZE * 0.4, 0.2, Math.PI * 2 - 0.2); + if (this.shape === 'triangle') { + const triangleSize = size * 1.5; // Plus grand pour une meilleure visibilité + + // Dessiner le triangle avec contour et yeux + ctx.beginPath(); + if (this.mouthOpen) { + // Triangle avec bouche ouverte - ouverture plus grande et visible + ctx.moveTo(0, -triangleSize * 0.9); + ctx.lineTo(-triangleSize * 0.85, triangleSize * 0.7); + ctx.lineTo(-triangleSize * 0.4, triangleSize * 0.4); + ctx.lineTo(0, triangleSize * 0.2); + ctx.lineTo(triangleSize * 0.4, triangleSize * 0.4); + ctx.lineTo(triangleSize * 0.85, triangleSize * 0.7); + ctx.closePath(); + } else { + // Triangle équilatéral complet + ctx.moveTo(0, -triangleSize); + ctx.lineTo(-triangleSize * 0.866, triangleSize * 0.5); // cos(30°) ≈ 0.866 + ctx.lineTo(triangleSize * 0.866, triangleSize * 0.5); + ctx.closePath(); + } + + // Remplir le triangle + ctx.fill(); + + // Contour noir épais pour plus de définition + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 2.5; + ctx.stroke(); + + // Dessiner les yeux + ctx.fillStyle = '#ffffff'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.12, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.12, 0, Math.PI * 2); + ctx.fill(); + + // Pupilles + ctx.fillStyle = '#000000'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.06, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.06, 0, Math.PI * 2); + ctx.fill(); + + // Reflets dans les yeux pour plus de vie + ctx.fillStyle = '#ffffff'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.22, -triangleSize * 0.17, triangleSize * 0.03, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.18, -triangleSize * 0.17, triangleSize * 0.03, 0, Math.PI * 2); + ctx.fill(); + + // Restaurer la couleur originale + ctx.fillStyle = baseFillColor; } else { - ctx.arc(0, 0, CELL_SIZE * 0.4, 0, Math.PI * 2); + // Forme ronde (par défaut) + if (this.mouthOpen) { + ctx.arc(0, 0, size, 0.2, Math.PI * 2 - 0.2); + } else { + ctx.arc(0, 0, size, 0, Math.PI * 2); + } + ctx.lineTo(0, 0); + ctx.fill(); } - ctx.lineTo(0, 0); - ctx.fill(); - ctx.restore(); } } @@ -2487,6 +2550,7 @@ if (rulesModal) { // === GESTION DU MODAL DE PERSONNALISATION === let selectedColor = playerColor; +let selectedShape = playerShape; // Ouvrir le modal de personnalisation if (customizeBtn) { @@ -2494,7 +2558,9 @@ if (customizeBtn) { if (customizeModal) { customizeModal.style.display = 'flex'; selectedColor = playerColor; + selectedShape = playerShape; updateColorSelection(); + updateShapeSelection(); updatePlayerPreview(); startPreviewAnimation(); } @@ -2532,6 +2598,17 @@ if (colorOptions) { }); } +// Gérer la sélection de forme +if (shapeOptions) { + shapeOptions.forEach(option => { + option.addEventListener('click', () => { + selectedShape = option.getAttribute('data-shape'); + updateShapeSelection(); + updatePlayerPreview(); + }); + }); +} + // Mettre à jour la sélection visuelle function updateColorSelection() { if (colorOptions) { @@ -2545,6 +2622,18 @@ function updateColorSelection() { } } +function updateShapeSelection() { + if (shapeOptions) { + shapeOptions.forEach(option => { + if (option.getAttribute('data-shape') === selectedShape) { + option.classList.add('active'); + } else { + option.classList.remove('active'); + } + }); + } +} + // Prévisualisation du joueur let previewAnimationId = null; function startPreviewAnimation() { @@ -2589,14 +2678,86 @@ function startPreviewAnimation() { mouthOpen = !mouthOpen; } + const size = 40; ctx.beginPath(); - const radius = 40; - if (mouthOpen) { - ctx.arc(0, 0, radius, 0.2, Math.PI * 2 - 0.2); + + if (selectedShape === 'triangle') { + const triangleSize = size * 1.5; // Plus grand pour une meilleure visibilité + + // Dessiner le triangle avec contour et yeux + ctx.beginPath(); + if (mouthOpen) { + // Triangle avec bouche ouverte + ctx.moveTo(0, -triangleSize * 0.9); + ctx.lineTo(-triangleSize * 0.85, triangleSize * 0.7); + ctx.lineTo(-triangleSize * 0.4, triangleSize * 0.4); + ctx.lineTo(0, triangleSize * 0.2); + ctx.lineTo(triangleSize * 0.4, triangleSize * 0.4); + ctx.lineTo(triangleSize * 0.85, triangleSize * 0.7); + ctx.closePath(); + } else { + // Triangle équilatéral complet + ctx.moveTo(0, -triangleSize); + ctx.lineTo(-triangleSize * 0.866, triangleSize * 0.5); + ctx.lineTo(triangleSize * 0.866, triangleSize * 0.5); + ctx.closePath(); + } + + // Remplir le triangle + ctx.fill(); + + // Contour noir épais + ctx.strokeStyle = '#000000'; + ctx.lineWidth = 2.5; + ctx.stroke(); + + // Dessiner les yeux + ctx.fillStyle = '#ffffff'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.12, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.12, 0, Math.PI * 2); + ctx.fill(); + + // Pupilles + ctx.fillStyle = '#000000'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.06, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.2, -triangleSize * 0.15, triangleSize * 0.06, 0, Math.PI * 2); + ctx.fill(); + + // Reflets dans les yeux + ctx.fillStyle = '#ffffff'; + ctx.beginPath(); + ctx.arc(-triangleSize * 0.22, -triangleSize * 0.17, triangleSize * 0.03, 0, Math.PI * 2); + ctx.arc(triangleSize * 0.18, -triangleSize * 0.17, triangleSize * 0.03, 0, Math.PI * 2); + ctx.fill(); + + // Restaurer la couleur originale + if (selectedColor === 'rainbow') { + 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'; + } } else { - ctx.arc(0, 0, radius, 0, Math.PI * 2); + // Dessiner un cercle + if (mouthOpen) { + ctx.arc(0, 0, size, 0.2, Math.PI * 2 - 0.2); + } else { + ctx.arc(0, 0, size, 0, Math.PI * 2); + } + ctx.lineTo(0, 0); } - ctx.lineTo(0, 0); + ctx.fill(); ctx.restore(); @@ -2622,11 +2783,14 @@ function updatePlayerPreview() { if (saveCustomizeBtn) { saveCustomizeBtn.addEventListener('click', () => { playerColor = selectedColor; + playerShape = selectedShape; localStorage.setItem('playerColor', playerColor); + localStorage.setItem('playerShape', playerShape); // Mettre à jour le joueur actuel si le jeu est en cours if (pacman) { pacman.color = playerColor; + pacman.shape = playerShape; } // Fermer le modal diff --git a/index.html b/index.html index 68e8a52..0b82c59 100644 --- a/index.html +++ b/index.html @@ -276,6 +276,19 @@ +