texture triangle ameliorer
This commit is contained in:
192
game.js
192
game.js
@ -38,6 +38,7 @@ const closeCustomizeBtn = document.getElementById('closeCustomizeBtn');
|
|||||||
const saveCustomizeBtn = document.getElementById('saveCustomizeBtn');
|
const saveCustomizeBtn = document.getElementById('saveCustomizeBtn');
|
||||||
const playerPreviewCanvas = document.getElementById('playerPreviewCanvas');
|
const playerPreviewCanvas = document.getElementById('playerPreviewCanvas');
|
||||||
const colorOptions = document.querySelectorAll('.color-option');
|
const colorOptions = document.querySelectorAll('.color-option');
|
||||||
|
const shapeOptions = document.querySelectorAll('.shape-option');
|
||||||
|
|
||||||
// Fonction pour vérifier si on est en mode plein écran
|
// Fonction pour vérifier si on est en mode plein écran
|
||||||
function isFullscreen() {
|
function isFullscreen() {
|
||||||
@ -50,6 +51,7 @@ let gameOverUsername = null;
|
|||||||
|
|
||||||
// Personnalisation du joueur
|
// Personnalisation du joueur
|
||||||
let playerColor = localStorage.getItem('playerColor') || 'rainbow';
|
let playerColor = localStorage.getItem('playerColor') || 'rainbow';
|
||||||
|
let playerShape = localStorage.getItem('playerShape') || 'round';
|
||||||
|
|
||||||
const CELL_SIZE = 25;
|
const CELL_SIZE = 25;
|
||||||
const COLS = 30;
|
const COLS = 30;
|
||||||
@ -253,7 +255,7 @@ let traps = [];
|
|||||||
let specialZones = [];
|
let specialZones = [];
|
||||||
|
|
||||||
class Pacman {
|
class Pacman {
|
||||||
constructor(color = null) {
|
constructor(color = null, shape = null) {
|
||||||
this.x = 14;
|
this.x = 14;
|
||||||
this.y = 23;
|
this.y = 23;
|
||||||
this.direction = 0;
|
this.direction = 0;
|
||||||
@ -266,6 +268,7 @@ class Pacman {
|
|||||||
this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2;
|
this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2;
|
||||||
this.colorAnimation = 0;
|
this.colorAnimation = 0;
|
||||||
this.color = color || playerColor;
|
this.color = color || playerColor;
|
||||||
|
this.shape = shape || playerShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@ -471,9 +474,11 @@ class Pacman {
|
|||||||
ctx.rotate(rotation[this.direction]);
|
ctx.rotate(rotation[this.direction]);
|
||||||
|
|
||||||
// Utiliser la couleur personnalisée
|
// Utiliser la couleur personnalisée
|
||||||
|
let baseFillColor;
|
||||||
if (this.color === 'rainbow') {
|
if (this.color === 'rainbow') {
|
||||||
const hue = (this.colorAnimation * 180 / Math.PI) % 360;
|
const hue = (this.colorAnimation * 180 / Math.PI) % 360;
|
||||||
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
|
baseFillColor = `hsl(${hue}, 100%, 50%)`;
|
||||||
|
ctx.fillStyle = baseFillColor;
|
||||||
} else {
|
} else {
|
||||||
const colorMap = {
|
const colorMap = {
|
||||||
'yellow': '#ffd700',
|
'yellow': '#ffd700',
|
||||||
@ -484,20 +489,78 @@ class Pacman {
|
|||||||
'orange': '#ff8844',
|
'orange': '#ff8844',
|
||||||
'pink': '#ff44aa'
|
'pink': '#ff44aa'
|
||||||
};
|
};
|
||||||
ctx.fillStyle = colorMap[this.color] || '#ffd700';
|
baseFillColor = colorMap[this.color] || '#ffd700';
|
||||||
|
ctx.fillStyle = baseFillColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size = CELL_SIZE * 0.4;
|
||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
|
||||||
if (this.mouthOpen) {
|
if (this.shape === 'triangle') {
|
||||||
ctx.arc(0, 0, CELL_SIZE * 0.4, 0.2, Math.PI * 2 - 0.2);
|
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 {
|
} 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();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2487,6 +2550,7 @@ if (rulesModal) {
|
|||||||
|
|
||||||
// === GESTION DU MODAL DE PERSONNALISATION ===
|
// === GESTION DU MODAL DE PERSONNALISATION ===
|
||||||
let selectedColor = playerColor;
|
let selectedColor = playerColor;
|
||||||
|
let selectedShape = playerShape;
|
||||||
|
|
||||||
// Ouvrir le modal de personnalisation
|
// Ouvrir le modal de personnalisation
|
||||||
if (customizeBtn) {
|
if (customizeBtn) {
|
||||||
@ -2494,7 +2558,9 @@ if (customizeBtn) {
|
|||||||
if (customizeModal) {
|
if (customizeModal) {
|
||||||
customizeModal.style.display = 'flex';
|
customizeModal.style.display = 'flex';
|
||||||
selectedColor = playerColor;
|
selectedColor = playerColor;
|
||||||
|
selectedShape = playerShape;
|
||||||
updateColorSelection();
|
updateColorSelection();
|
||||||
|
updateShapeSelection();
|
||||||
updatePlayerPreview();
|
updatePlayerPreview();
|
||||||
startPreviewAnimation();
|
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
|
// Mettre à jour la sélection visuelle
|
||||||
function updateColorSelection() {
|
function updateColorSelection() {
|
||||||
if (colorOptions) {
|
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
|
// Prévisualisation du joueur
|
||||||
let previewAnimationId = null;
|
let previewAnimationId = null;
|
||||||
function startPreviewAnimation() {
|
function startPreviewAnimation() {
|
||||||
@ -2589,14 +2678,86 @@ function startPreviewAnimation() {
|
|||||||
mouthOpen = !mouthOpen;
|
mouthOpen = !mouthOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size = 40;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
const radius = 40;
|
|
||||||
if (mouthOpen) {
|
if (selectedShape === 'triangle') {
|
||||||
ctx.arc(0, 0, radius, 0.2, Math.PI * 2 - 0.2);
|
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 {
|
} 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.fill();
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
@ -2622,11 +2783,14 @@ function updatePlayerPreview() {
|
|||||||
if (saveCustomizeBtn) {
|
if (saveCustomizeBtn) {
|
||||||
saveCustomizeBtn.addEventListener('click', () => {
|
saveCustomizeBtn.addEventListener('click', () => {
|
||||||
playerColor = selectedColor;
|
playerColor = selectedColor;
|
||||||
|
playerShape = selectedShape;
|
||||||
localStorage.setItem('playerColor', playerColor);
|
localStorage.setItem('playerColor', playerColor);
|
||||||
|
localStorage.setItem('playerShape', playerShape);
|
||||||
|
|
||||||
// Mettre à jour le joueur actuel si le jeu est en cours
|
// Mettre à jour le joueur actuel si le jeu est en cours
|
||||||
if (pacman) {
|
if (pacman) {
|
||||||
pacman.color = playerColor;
|
pacman.color = playerColor;
|
||||||
|
pacman.shape = playerShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fermer le modal
|
// Fermer le modal
|
||||||
|
|||||||
13
index.html
13
index.html
@ -276,6 +276,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="customize-section">
|
||||||
|
<h3>Forme du joueur</h3>
|
||||||
|
<div class="shape-options">
|
||||||
|
<div class="shape-option active" data-shape="round" data-name="Rond">
|
||||||
|
<div class="shape-preview round-preview"></div>
|
||||||
|
<span>Rond (Classique)</span>
|
||||||
|
</div>
|
||||||
|
<div class="shape-option" data-shape="triangle" data-name="Triangle">
|
||||||
|
<div class="shape-preview triangle-preview"></div>
|
||||||
|
<span>Triangle</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="customize-preview">
|
<div class="customize-preview">
|
||||||
<h3>Aperçu</h3>
|
<h3>Aperçu</h3>
|
||||||
<canvas id="playerPreviewCanvas" width="200" height="200"></canvas>
|
<canvas id="playerPreviewCanvas" width="200" height="200"></canvas>
|
||||||
|
|||||||
65
style.css
65
style.css
@ -1479,3 +1479,68 @@ footer {
|
|||||||
.save-customize-btn:active {
|
.save-customize-btn:active {
|
||||||
transform: translateY(0) scale(0.98);
|
transform: translateY(0) scale(0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shape-options {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shape-option {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 2px solid rgba(255, 215, 0, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shape-option:hover {
|
||||||
|
background: rgba(255, 215, 0, 0.1);
|
||||||
|
border-color: #ffd700;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shape-option.active {
|
||||||
|
background: rgba(255, 215, 0, 0.2);
|
||||||
|
border-color: #ffd700;
|
||||||
|
box-shadow: 0 0 15px rgba(255, 215, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shape-preview {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.round-preview {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ffd700;
|
||||||
|
border: 3px solid #fff;
|
||||||
|
box-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.triangle-preview {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 25px solid transparent;
|
||||||
|
border-right: 25px solid transparent;
|
||||||
|
border-bottom: 45px solid #ffd700;
|
||||||
|
border-top: none;
|
||||||
|
filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.3));
|
||||||
|
}
|
||||||
|
|
||||||
|
.shape-option span {
|
||||||
|
font-size: 0.7em;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user