Compare commits

...

2 Commits

2 changed files with 24 additions and 16 deletions

38
game.js
View File

@ -354,7 +354,7 @@ class Pacman {
cherryEatenTimer = Math.max(150, 300 - (level - 1) * 20);
// Rendre tous les fantômes vulnérables
const vulnerableTime = Math.max(180, 360 - (level - 1) * 30);
const vulnerableTime = Math.max(60, 180 - (level - 1) * 15);
for (let ghost of ghosts) {
ghost.isVulnerable = true;
ghost.vulnerableTimer = vulnerableTime;
@ -538,7 +538,7 @@ class Ghost {
}
}
this.moveInterval = Math.max(8, 20 - (level - 1) * 2);
this.moveInterval = Math.max(5, 15 - (level - 1) * 1.5);
this.moveCounter++;
@ -555,15 +555,20 @@ class Ghost {
// Fuir le joueur quand vulnérable
this.direction = this.getDirectionAwayFromPacman(possibleDirections);
} else {
// Comportement selon le type
if (this.type === GHOST_HUNTER) {
this.direction = this.getDirectionToPacman(possibleDirections);
} else if (this.type === GHOST_PATROL) {
this.direction = this.getPatrolDirection(possibleDirections);
} else if (this.type === GHOST_FAST || this.type === GHOST_INVISIBLE) {
this.direction = this.getDirectionToPacman(possibleDirections);
// Tous les fantômes chassent le joueur (sauf patrouilleurs qui patrouillent si très loin)
if (this.type === GHOST_PATROL) {
const distance = Math.sqrt(
Math.pow(pacman.x - this.x, 2) +
Math.pow(pacman.y - this.y, 2)
);
// Si proche, chasser, sinon patrouiller (seulement si très loin)
if (distance < 12) {
this.direction = this.getDirectionToPacman(possibleDirections);
} else {
this.direction = this.getPatrolDirection(possibleDirections);
}
} else {
// Normal : toujours poursuivre
// Tous les autres chassent directement
this.direction = this.getDirectionToPacman(possibleDirections);
}
}
@ -595,10 +600,13 @@ class Ghost {
let targetX = pacman.x;
let targetY = pacman.y;
// Prédiction améliorée pour tous les niveaux
const predictionSteps = level >= 3 ? 4 : 3;
// Si Pacman bouge, prédire où il sera
if (pacman.direction !== undefined) {
const futureX = pacman.x + dx[pacman.direction] * 2;
const futureY = pacman.y + dy[pacman.direction] * 2;
const futureX = pacman.x + dx[pacman.direction] * predictionSteps;
const futureY = pacman.y + dy[pacman.direction] * predictionSteps;
if (futureX >= 0 && futureX < COLS && futureY >= 0 && futureY < ROWS) {
targetX = futureX;
targetY = futureY;
@ -612,10 +620,8 @@ class Ghost {
const oppositeDirection = (this.direction + 2) % 4;
for (let dir of possibleDirections) {
// Éviter la direction opposée sauf si c'est la seule option
if (possibleDirections.length > 1 && dir === oppositeDirection) {
continue;
}
// Permettre le retour en arrière si c'est la meilleure direction
// (pas de restriction pour une poursuite plus agressive)
const nextX = this.x + dx[dir];
const nextY = this.y + dy[dir];

View File

@ -19,6 +19,7 @@ body {
padding: 20px;
position: relative;
overflow-x: hidden;
cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='32' viewBox='0 0 36 32'%3E%3Cdefs%3E%3Cfilter id='glow'%3E%3CfeGaussianBlur stdDeviation='1.5' result='coloredBlur'/%3E%3CfeMerge%3E%3CfeMergeNode in='coloredBlur'/%3E%3CfeMergeNode in='SourceGraphic'/%3E%3C/feMerge%3E%3C/filter%3E%3ClinearGradient id='ghostGrad' x1='0%25' y1='0%25' x2='0%25' y2='100%25'%3E%3Cstop offset='0%25' style='stop-color:%23ff4444;stop-opacity:1' /%3E%3Cstop offset='100%25' style='stop-color:%23cc0000;stop-opacity:1' /%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M18 4 Q22 2 26 4 Q30 6 30 10 L30 20 Q30 24 28 26 Q26 28 24 28 Q22 30 20 28 Q18 30 16 28 Q14 30 12 28 Q10 30 8 28 Q6 30 4 28 Q2 26 2 22 L2 10 Q2 6 6 4 Q10 2 14 4 Q16 2 18 4 Z' fill='url(%23ghostGrad)' filter='url(%23glow)' stroke='%23ffffff' stroke-width='0.3'/%3E%3Cpath d='M8 22 Q6 24 8 26 Q9 24 8 22 M14 22 Q12 24 14 26 Q15 24 14 22 M20 22 Q18 24 20 26 Q21 24 20 22 M26 22 Q24 24 26 26 Q27 24 26 22' fill='url(%23ghostGrad)' filter='url(%23glow)'/%3E%3Ccircle cx='12' cy='10' r='3' fill='%23ffffff'/%3E%3Ccircle cx='24' cy='10' r='3' fill='%23ffffff'/%3E%3Ccircle cx='12' cy='10' r='1.8' fill='%23000000'/%3E%3Ccircle cx='24' cy='10' r='1.8' fill='%23000000'/%3E%3Cellipse cx='12.5' cy='9.5' rx='0.6' ry='0.8' fill='%23ffffff'/%3E%3Cellipse cx='24.5' cy='9.5' rx='0.6' ry='0.8' fill='%23ffffff'/%3E%3C/svg%3E") 18 16, auto;
}
body::before {
@ -143,6 +144,7 @@ body::after {
height: 100%;
z-index: 1000;
overflow: hidden;
cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='32' viewBox='0 0 36 32'%3E%3Cdefs%3E%3Cfilter id='glow'%3E%3CfeGaussianBlur stdDeviation='1.5' result='coloredBlur'/%3E%3CfeMerge%3E%3CfeMergeNode in='coloredBlur'/%3E%3CfeMergeNode in='SourceGraphic'/%3E%3C/feMerge%3E%3C/filter%3E%3ClinearGradient id='ghostGrad' x1='0%25' y1='0%25' x2='0%25' y2='100%25'%3E%3Cstop offset='0%25' style='stop-color:%23ff4444;stop-opacity:1' /%3E%3Cstop offset='100%25' style='stop-color:%23cc0000;stop-opacity:1' /%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M18 4 Q22 2 26 4 Q30 6 30 10 L30 20 Q30 24 28 26 Q26 28 24 28 Q22 30 20 28 Q18 30 16 28 Q14 30 12 28 Q10 30 8 28 Q6 30 4 28 Q2 26 2 22 L2 10 Q2 6 6 4 Q10 2 14 4 Q16 2 18 4 Z' fill='url(%23ghostGrad)' filter='url(%23glow)' stroke='%23ffffff' stroke-width='0.3'/%3E%3Cpath d='M8 22 Q6 24 8 26 Q9 24 8 22 M14 22 Q12 24 14 26 Q15 24 14 22 M20 22 Q18 24 20 26 Q21 24 20 22 M26 22 Q24 24 26 26 Q27 24 26 22' fill='url(%23ghostGrad)' filter='url(%23glow)'/%3E%3Ccircle cx='12' cy='10' r='3' fill='%23ffffff'/%3E%3Ccircle cx='24' cy='10' r='3' fill='%23ffffff'/%3E%3Ccircle cx='12' cy='10' r='1.8' fill='%23000000'/%3E%3Ccircle cx='24' cy='10' r='1.8' fill='%23000000'/%3E%3Cellipse cx='12.5' cy='9.5' rx='0.6' ry='0.8' fill='%23ffffff'/%3E%3Cellipse cx='24.5' cy='9.5' rx='0.6' ry='0.8' fill='%23ffffff'/%3E%3C/svg%3E") 18 16, auto;
}
/* === CANVAS ARRIERE-PLAN MENU === */