texture zebre plus sourie menu
This commit is contained in:
301
game.js
301
game.js
@ -550,6 +550,124 @@ class Pacman {
|
||||
|
||||
// Restaurer la couleur originale
|
||||
ctx.fillStyle = baseFillColor;
|
||||
} else if (this.shape === 'zebre') {
|
||||
// Dessiner un zèbre plus réaliste
|
||||
const bodyWidth = size * 1.8;
|
||||
const bodyHeight = size * 1.4;
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Corps (ellipse allongée)
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, size * 0.2, bodyWidth, bodyHeight, 0, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// Rayures noires horizontales sur le corps
|
||||
ctx.fillStyle = '#000000';
|
||||
const stripeCount = 8;
|
||||
const stripeSpacing = (bodyHeight * 2) / stripeCount;
|
||||
|
||||
for (let i = 0; i < stripeCount; i++) {
|
||||
if (i % 2 === 1) { // Alterner les rayures
|
||||
const yPos = -bodyHeight + (i * stripeSpacing);
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, yPos + size * 0.2, bodyWidth * 0.95, stripeSpacing * 0.5, 0, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
// Tête (cercle légèrement plus petit au-dessus du corps)
|
||||
const headSize = size * 0.9;
|
||||
ctx.beginPath();
|
||||
if (this.mouthOpen) {
|
||||
ctx.arc(0, -bodyHeight - headSize * 0.2, headSize, 0.15, Math.PI * 2 - 0.15);
|
||||
ctx.lineTo(0, -bodyHeight - headSize * 0.2);
|
||||
ctx.closePath();
|
||||
} else {
|
||||
ctx.arc(0, -bodyHeight - headSize * 0.2, headSize, 0, Math.PI * 2);
|
||||
}
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// Rayures sur la tête (verticales)
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.fillRect(-headSize * 0.4, -bodyHeight - headSize * 0.5, headSize * 0.15, headSize * 0.6);
|
||||
ctx.fillRect(headSize * 0.25, -bodyHeight - headSize * 0.5, headSize * 0.15, headSize * 0.6);
|
||||
|
||||
// Oreilles pointues
|
||||
ctx.beginPath();
|
||||
// Oreille gauche
|
||||
ctx.moveTo(-headSize * 0.6, -bodyHeight - headSize * 0.8);
|
||||
ctx.lineTo(-headSize * 0.8, -bodyHeight - headSize * 1.4);
|
||||
ctx.lineTo(-headSize * 0.4, -bodyHeight - headSize * 0.9);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
|
||||
// Rayure sur l'oreille gauche
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-headSize * 0.65, -bodyHeight - headSize * 0.95);
|
||||
ctx.lineTo(-headSize * 0.75, -bodyHeight - headSize * 1.3);
|
||||
ctx.lineTo(-headSize * 0.55, -bodyHeight - headSize * 1.0);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Oreille droite
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(headSize * 0.6, -bodyHeight - headSize * 0.8);
|
||||
ctx.lineTo(headSize * 0.8, -bodyHeight - headSize * 1.4);
|
||||
ctx.lineTo(headSize * 0.4, -bodyHeight - headSize * 0.9);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
|
||||
// Rayure sur l'oreille droite
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(headSize * 0.65, -bodyHeight - headSize * 0.95);
|
||||
ctx.lineTo(headSize * 0.75, -bodyHeight - headSize * 1.3);
|
||||
ctx.lineTo(headSize * 0.55, -bodyHeight - headSize * 1.0);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Yeux
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.15, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.15, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Pupilles
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.08, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.08, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Reflets dans les yeux
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.32, -bodyHeight - headSize * 0.32, headSize * 0.03, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.28, -bodyHeight - headSize * 0.32, headSize * 0.03, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Queue (petite touffe)
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(bodyWidth * 0.6, bodyHeight * 0.6, size * 0.2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
} else {
|
||||
// Forme ronde (par défaut)
|
||||
if (this.mouthOpen) {
|
||||
@ -2339,9 +2457,25 @@ class MenuGhost {
|
||||
this.size = 30 + Math.random() * 20;
|
||||
this.color = ['#ff0000', '#ff00ff', '#00ffff', '#ffa500'][Math.floor(Math.random() * 4)];
|
||||
this.animation = Math.random() * Math.PI * 2;
|
||||
this.isDestroyed = false;
|
||||
this.destroyAnimation = 0;
|
||||
}
|
||||
|
||||
// Vérifier si le curseur touche le fantôme
|
||||
isPointInside(mouseX, mouseY) {
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(mouseX - this.x, 2) +
|
||||
Math.pow(mouseY - this.y, 2)
|
||||
);
|
||||
return distance < this.size * 0.7;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this.isDestroyed) {
|
||||
this.destroyAnimation += 0.1;
|
||||
return;
|
||||
}
|
||||
|
||||
this.x += this.speedX;
|
||||
this.y += this.speedY;
|
||||
this.animation += 0.05;
|
||||
@ -2360,6 +2494,33 @@ class MenuGhost {
|
||||
}
|
||||
|
||||
draw() {
|
||||
if (this.isDestroyed) {
|
||||
// Animation de destruction (particules qui s'éparpillent)
|
||||
if (this.destroyAnimation > 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuCtx.save();
|
||||
menuCtx.globalAlpha = 1 - (this.destroyAnimation / 2);
|
||||
|
||||
// Dessiner des particules qui s'éparpillent
|
||||
const particleCount = 8;
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
const angle = (Math.PI * 2 / particleCount) * i + this.destroyAnimation * 2;
|
||||
const distance = this.destroyAnimation * 30;
|
||||
const particleX = this.x + Math.cos(angle) * distance;
|
||||
const particleY = this.y + Math.sin(angle) * distance;
|
||||
|
||||
menuCtx.fillStyle = this.color;
|
||||
menuCtx.beginPath();
|
||||
menuCtx.arc(particleX, particleY, 4, 0, Math.PI * 2);
|
||||
menuCtx.fill();
|
||||
}
|
||||
|
||||
menuCtx.restore();
|
||||
return;
|
||||
}
|
||||
|
||||
menuCtx.save();
|
||||
menuCtx.translate(this.x, this.y);
|
||||
|
||||
@ -2440,6 +2601,13 @@ function animateMenu() {
|
||||
ghost.draw();
|
||||
});
|
||||
|
||||
// Remplacer les fantômes complètement détruits
|
||||
for (let i = 0; i < menuGhosts.length; i++) {
|
||||
if (menuGhosts[i].isDestroyed && menuGhosts[i].destroyAnimation > 2) {
|
||||
menuGhosts[i] = new MenuGhost();
|
||||
}
|
||||
}
|
||||
|
||||
menuAnimationFrame = requestAnimationFrame(animateMenu);
|
||||
}
|
||||
|
||||
@ -2488,6 +2656,25 @@ if (mainMenu) {
|
||||
menuObserver.observe(mainMenu, { attributes: true, attributeFilter: ['style'] });
|
||||
}
|
||||
|
||||
// Gestion de la destruction des fantômes avec le curseur
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
|
||||
menuCanvas.addEventListener('mousemove', (e) => {
|
||||
const rect = menuCanvas.getBoundingClientRect();
|
||||
mouseX = e.clientX - rect.left;
|
||||
mouseY = e.clientY - rect.top;
|
||||
|
||||
// Vérifier les collisions avec les fantômes
|
||||
menuGhosts.forEach(ghost => {
|
||||
if (!ghost.isDestroyed && ghost.isPointInside(mouseX, mouseY)) {
|
||||
// Détruire le fantôme
|
||||
ghost.isDestroyed = true;
|
||||
ghost.destroyAnimation = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// === GESTION DU MENU ===
|
||||
// Afficher le jeu
|
||||
playBtn.addEventListener('click', () => {
|
||||
@ -2748,6 +2935,120 @@ function startPreviewAnimation() {
|
||||
};
|
||||
ctx.fillStyle = colorMap[selectedColor] || '#ffd700';
|
||||
}
|
||||
} else if (selectedShape === 'zebre') {
|
||||
// Dessiner un zèbre plus réaliste
|
||||
const bodyWidth = size * 1.8;
|
||||
const bodyHeight = size * 1.4;
|
||||
|
||||
// Corps (ellipse allongée)
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, size * 0.2, bodyWidth, bodyHeight, 0, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// Rayures noires horizontales sur le corps
|
||||
ctx.fillStyle = '#000000';
|
||||
const stripeCount = 8;
|
||||
const stripeSpacing = (bodyHeight * 2) / stripeCount;
|
||||
|
||||
for (let i = 0; i < stripeCount; i++) {
|
||||
if (i % 2 === 1) { // Alterner les rayures
|
||||
const yPos = -bodyHeight + (i * stripeSpacing);
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, yPos + size * 0.2, bodyWidth * 0.95, stripeSpacing * 0.5, 0, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
|
||||
// Tête (cercle légèrement plus petit au-dessus du corps)
|
||||
const headSize = size * 0.9;
|
||||
ctx.beginPath();
|
||||
if (mouthOpen) {
|
||||
ctx.arc(0, -bodyHeight - headSize * 0.2, headSize, 0.15, Math.PI * 2 - 0.15);
|
||||
ctx.lineTo(0, -bodyHeight - headSize * 0.2);
|
||||
ctx.closePath();
|
||||
} else {
|
||||
ctx.arc(0, -bodyHeight - headSize * 0.2, headSize, 0, Math.PI * 2);
|
||||
}
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
|
||||
// Rayures sur la tête (verticales)
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.fillRect(-headSize * 0.4, -bodyHeight - headSize * 0.5, headSize * 0.15, headSize * 0.6);
|
||||
ctx.fillRect(headSize * 0.25, -bodyHeight - headSize * 0.5, headSize * 0.15, headSize * 0.6);
|
||||
|
||||
// Oreilles pointues
|
||||
ctx.beginPath();
|
||||
// Oreille gauche
|
||||
ctx.moveTo(-headSize * 0.6, -bodyHeight - headSize * 0.8);
|
||||
ctx.lineTo(-headSize * 0.8, -bodyHeight - headSize * 1.4);
|
||||
ctx.lineTo(-headSize * 0.4, -bodyHeight - headSize * 0.9);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
|
||||
// Rayure sur l'oreille gauche
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-headSize * 0.65, -bodyHeight - headSize * 0.95);
|
||||
ctx.lineTo(-headSize * 0.75, -bodyHeight - headSize * 1.3);
|
||||
ctx.lineTo(-headSize * 0.55, -bodyHeight - headSize * 1.0);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Oreille droite
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(headSize * 0.6, -bodyHeight - headSize * 0.8);
|
||||
ctx.lineTo(headSize * 0.8, -bodyHeight - headSize * 1.4);
|
||||
ctx.lineTo(headSize * 0.4, -bodyHeight - headSize * 0.9);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
|
||||
// Rayure sur l'oreille droite
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(headSize * 0.65, -bodyHeight - headSize * 0.95);
|
||||
ctx.lineTo(headSize * 0.75, -bodyHeight - headSize * 1.3);
|
||||
ctx.lineTo(headSize * 0.55, -bodyHeight - headSize * 1.0);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
// Yeux
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.15, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.15, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Pupilles
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.08, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.3, -bodyHeight - headSize * 0.3, headSize * 0.08, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Reflets dans les yeux
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-headSize * 0.32, -bodyHeight - headSize * 0.32, headSize * 0.03, 0, Math.PI * 2);
|
||||
ctx.arc(headSize * 0.28, -bodyHeight - headSize * 0.32, headSize * 0.03, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Queue (petite touffe)
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(bodyWidth * 0.6, bodyHeight * 0.6, size * 0.2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
} else {
|
||||
// Dessiner un cercle
|
||||
if (mouthOpen) {
|
||||
|
||||
Reference in New Issue
Block a user