jeux html

This commit is contained in:
2026-08-21 16:25:40 +02:00
commit c8390721a7
4 changed files with 915 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
# 🕹️ Rétro Arcade en HTML5 / JavaScript
Bienvenue dans ce dépôt de jeux d'arcade classiques entièrement développés en HTML5, CSS (Tailwind) et JavaScript pur (Vanilla JS). Aucun framework lourd ni installation complexe n'est requise : chaque jeu est contenu dans un unique fichier autonome.
---
## 📋 Table des matières
1. [Pac-Man](#-pac-man)
2. [Breakout](#-breakout)
3. [Lancer les jeux](#-lancer-les-jeux)
---
## 🟡 Pac-Man
Une adaptation moderne et fluide du célèbre jeu de labyrinthe arcade, optimisée pour le jeu directement dans le navigateur.
### Fonctionnalités :
- **Labyrinthe classique** avec gestion des pac-gommes et des scores en temps réel.
- **Système de Tunnels** fonctionnel sur les côtés pour traverser l'écran.
- **IA des fantômes** : déplacement intelligent aux intersections et évitement des blocages.
- **Commandes fluides** avec anticipation des virages pour un meilleur confort de jeu.
### Commandes :
- **Déplacement :** Touches fléchées `←` `↑` `↓` `→` ou les touches `Z` `Q` `S` `D`.
---
## 🧱 Breakout
\*_(Jeu classique de casse-briques)_
_(Section à compléter lors de l'ajout du code Breakout dans votre dépôt)_
---
## 🚀 Lancer les jeux
Aucun serveur ni installation de dépendances (comme Node.js) n'est nécessaire.
1. Téléchargez ou clonez les fichiers sur votre machine.
2. Ouvrez le fichier de votre choix (par exemple `pacman.html`) directement dans n'importe quel navigateur web moderne (**Google Chrome**, **Firefox**, **Edge**, etc.).
Bonne partie ! 🎮
+251
View File
@@ -0,0 +1,251 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Casse-briques Agrandit</title>
<!-- Chargement de Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body
class="bg-slate-900 text-slate-100 flex flex-col items-center justify-center min-h-screen select-none"
>
<h1 class="text-3xl font-extrabold mb-4 tracking-wider text-amber-400">
CASSE-BRIQUES
</h1>
<!-- Conteneur du jeu élargi -->
<div
class="relative bg-slate-800 p-4 rounded-2xl shadow-2xl border border-slate-700"
>
<!-- Canvas plus grand (600x450) -->
<canvas
id="gameCanvas"
width="600"
height="450"
class="bg-slate-950 rounded-lg shadow-inner block"
></canvas>
</div>
<p class="text-xs text-slate-400 mt-4">
Utilisez les touches fléchées **←** et **→** (ou **Q** et **D**) pour
déplacer la raquette.
</p>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// Paramètres de la balle
let x = canvas.width / 2;
let y = canvas.height - 40;
let dx = 3;
let dy = -3;
const ballRadius = 7;
// Paramètres de la raquette (élargie proportionnellement)
const paddleHeight = 12;
const paddleWidth = 90;
let paddleX = (canvas.width - paddleWidth) / 2;
// Contrôles
let rightPressed = false;
let leftPressed = false;
// Paramètres des briques (plus larges pour occuper l'espace de 600px)
const brickRowCount = 5;
const brickColumnCount = 8;
const brickWidth = 62;
const brickHeight = 22;
const brickPadding = 10;
const brickOffsetTop = 60; // Espace important entre le haut et les cibles
const brickOffsetLeft = 32;
let score = 0;
let lives = 3;
// Initialisation du tableau des briques
const bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
// Écouteurs d'événements clavier
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (
e.key === "Right" ||
e.key === "ArrowRight" ||
e.key === "d" ||
e.key === "D"
) {
rightPressed = true;
} else if (
e.key === "Left" ||
e.key === "ArrowLeft" ||
e.key === "q" ||
e.key === "Q"
) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (
e.key === "Right" ||
e.key === "ArrowRight" ||
e.key === "d" ||
e.key === "D"
) {
rightPressed = false;
} else if (
e.key === "Left" ||
e.key === "ArrowLeft" ||
e.key === "q" ||
e.key === "Q"
) {
leftPressed = false;
}
}
// Détection des collisions avec les briques
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const b = bricks[c][r];
if (b.status === 1) {
if (
x > b.x &&
x < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
dy = -dy;
b.status = 0;
score += 10;
// Victoire
if (score === brickRowCount * brickColumnCount * 10) {
alert("VICTOIRE ! Félicitations !");
document.location.reload();
}
}
}
}
}
}
// Dessiner la balle
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#f43f5e";
ctx.fill();
ctx.closePath();
}
// Dessiner la raquette
function drawPaddle() {
ctx.beginPath();
ctx.rect(
paddleX,
canvas.height - paddleHeight - 15,
paddleWidth,
paddleHeight,
);
ctx.fillStyle = "#38bdf8";
ctx.fill();
ctx.closePath();
}
// Dessiner les briques
function drawBricks() {
const colors = ["#f59e0b", "#10b981", "#6366f1", "#ec4899", "#8b5cf6"];
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = colors[r % colors.length];
ctx.fill();
ctx.closePath();
}
}
}
}
// Afficher le score et les vies
function drawScoreAndLives() {
ctx.font = "14px monospace";
ctx.fillStyle = "#94a3b8";
ctx.fillText("Score: " + score, 25, 30);
ctx.fillText("Vies: " + lives, canvas.width - 75, 30);
}
// Boucle principale du jeu
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScoreAndLives();
collisionDetection();
// Rebond sur les murs (gauche / droite)
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
// Rebond sur le mur du haut
if (y + dy < ballRadius) {
dy = -dy;
}
// Gestion de la raquette et du bas (perte de vie)
else if (y + dy > canvas.height - ballRadius - 15) {
if (x > paddleX && x < paddleX + paddleWidth) {
let hitPoint = x - (paddleX + paddleWidth / 2);
dx = hitPoint * 0.15;
dy = -dy;
} else {
lives--;
if (!lives) {
alert("GAME OVER");
document.location.reload();
} else {
x = canvas.width / 2;
y = canvas.height - 40;
dx = 3;
dy = -3;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
// Mouvement de la raquette
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
// Mouvement de la balle
x += dx;
y += dy;
requestAnimationFrame(draw);
}
// Lancement du jeu
draw();
</script>
</body>
</html>
+251
View File
@@ -0,0 +1,251 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Casse-briques Autonome</title>
<!-- Chargement de Tailwind CSS pour le design de la page -->
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body
class="bg-slate-900 text-slate-100 flex flex-col items-center justify-center min-h-screen select-none"
>
<h1 class="text-3xl font-extrabold mb-4 tracking-wider text-amber-400">
CASSE-BRIQUES
</h1>
<!-- Conteneur du jeu -->
<div
class="relative bg-slate-800 p-4 rounded-2xl shadow-2xl border border-slate-700"
>
<canvas
id="gameCanvas"
width="480"
height="320"
class="bg-slate-950 rounded-lg shadow-inner block"
></canvas>
</div>
<p class="text-xs text-slate-400 mt-4">
Utilisez les touches fléchées **←** et **→** (ou **Q** et **D**) pour
déplacer la raquette.
</p>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// Paramètres de la balle
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;
const ballRadius = 6;
// Paramètres de la raquette
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;
// Contrôles
let rightPressed = false;
let leftPressed = false;
// Paramètres des briques
const brickRowCount = 4;
const brickColumnCount = 7;
const brickWidth = 60;
const brickHeight = 20;
const brickPadding = 8;
const brickOffsetTop = 30;
const brickOffsetLeft = 18;
let score = 0;
let lives = 3;
// Initialisation du tableau des briques
const bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
// Écouteurs d'événements clavier
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (
e.key === "Right" ||
e.key === "ArrowRight" ||
e.key === "d" ||
e.key === "D"
) {
rightPressed = true;
} else if (
e.key === "Left" ||
e.key === "ArrowLeft" ||
e.key === "q" ||
e.key === "Q"
) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (
e.key === "Right" ||
e.key === "ArrowRight" ||
e.key === "d" ||
e.key === "D"
) {
rightPressed = false;
} else if (
e.key === "Left" ||
e.key === "ArrowLeft" ||
e.key === "q" ||
e.key === "Q"
) {
leftPressed = false;
}
}
// Détection des collisions avec les briques
function collisionDetection() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const b = bricks[c][r];
if (b.status === 1) {
if (
x > b.x &&
x < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
dy = -dy;
b.status = 0;
score += 10;
// Victoire
if (score === brickRowCount * brickColumnCount * 10) {
alert("VICTOIRE ! Félicitations !");
document.location.reload();
}
}
}
}
}
}
// Dessiner la balle
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#f43f5e"; // Rouge vif
ctx.fill();
ctx.closePath();
}
// Dessiner la raquette
function drawPaddle() {
ctx.beginPath();
ctx.rect(
paddleX,
canvas.height - paddleHeight - 10,
paddleWidth,
paddleHeight,
);
ctx.fillStyle = "#38bdf8"; // Bleu clair
ctx.fill();
ctx.closePath();
}
// Dessiner les briques
function drawBricks() {
const colors = ["#f59e0b", "#10b981", "#6366f1", "#ec4899"]; // Couleurs par ligne
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = colors[r % colors.length];
ctx.fill();
ctx.closePath();
}
}
}
}
// Afficher le score et les vies
function drawScoreAndLives() {
ctx.font = "12px monospace";
ctx.fillStyle = "#94a3b8";
ctx.fillText("Score: " + score, 20, 20);
ctx.fillText("Vies: " + lives, canvas.width - 60, 20);
}
// Boucle principale du jeu
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScoreAndLives();
collisionDetection();
// Rebond sur les murs (gauche / droite)
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
// Rebond sur le mur du haut
if (y + dy < ballRadius) {
dy = -dy;
}
// Gestion de la raquette et du bas (perte de vie)
else if (y + dy > canvas.height - ballRadius - 10) {
if (x > paddleX && x < paddleX + paddleWidth) {
// Effet d'angle selon l'endroit où la balle tape la raquette
let hitPoint = x - (paddleX + paddleWidth / 2);
dx = hitPoint * 0.15;
dy = -dy;
} else {
lives--;
if (!lives) {
alert("GAME OVER");
document.location.reload();
} else {
x = canvas.width / 2;
y = canvas.height - 30;
dx = 2;
dy = -2;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
// Mouvement de la raquette
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 6;
} else if (leftPressed && paddleX > 0) {
paddleX -= 6;
}
// Mouvement de la balle
x += dx;
y += dy;
requestAnimationFrame(draw);
}
// Lancement du jeu
draw();
</script>
</body>
</html>
+366
View File
@@ -0,0 +1,366 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pac-Man Grand Format - Contrôles Fluides</title>
<!-- Chargement de Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body
class="bg-slate-950 text-slate-100 flex flex-col items-center justify-center min-h-screen select-none"
>
<h1 class="text-3xl font-extrabold mb-3 tracking-widest text-yellow-400">
PAC-MAN
</h1>
<!-- Tableau de bord (Score / Vies) -->
<div
class="flex justify-between w-[800px] mb-2 px-2 font-mono text-base text-slate-300"
>
<div>
Score : <span id="score" class="text-yellow-400 font-bold">0</span>
</div>
<div>Vies : <span id="lives" class="text-red-500 font-bold">3</span></div>
</div>
<!-- Conteneur du jeu (800x800) -->
<div
class="relative bg-black p-4 rounded-2xl shadow-2xl border-2 border-blue-600"
>
<canvas id="gameCanvas" width="800" height="800" class="block"></canvas>
</div>
<p class="text-xs text-slate-400 mt-4">
Utilisez les touches fléchées **← ↑ ↓ →** (ou **Z Q S D**) pour guider
Pac-Man.
</p>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const tileSize = 40;
const speed = 4;
const map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],
[1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1],
[1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1],
[0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0],
[1, 1, 1, 1, 2, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 2, 1, 1, 1, 1],
[0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0],
[1, 1, 1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1],
[0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0],
[1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1],
[1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1],
[1, 2, 2, 1, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 2, 1],
[1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1],
[1, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
];
let score = 0;
let lives = 3;
let pacman = {
x: 9 * tileSize + tileSize / 2,
y: 16 * tileSize + tileSize / 2,
radius: tileSize / 2 - 4,
dx: 0,
dy: 0,
nextDx: 0,
nextDy: 0,
};
let ghosts = [
{
x: 9 * tileSize + tileSize / 2,
y: 9 * tileSize + tileSize / 2,
color: "#ef4444",
dx: speed,
dy: 0,
},
{
x: 10 * tileSize + tileSize / 2,
y: 9 * tileSize + tileSize / 2,
color: "#ec4899",
dx: -speed,
dy: 0,
},
{
x: 9 * tileSize + tileSize / 2,
y: 10 * tileSize + tileSize / 2,
color: "#06b6d4",
dx: 0,
dy: -speed,
},
{
x: 10 * tileSize + tileSize / 2,
y: 10 * tileSize + tileSize / 2,
color: "#f97316",
dx: 0,
dy: speed,
},
];
window.addEventListener("keydown", (e) => {
switch (e.key) {
case "ArrowLeft":
case "q":
case "Q":
pacman.nextDx = -speed;
pacman.nextDy = 0;
break;
case "ArrowRight":
case "d":
case "D":
pacman.nextDx = speed;
pacman.nextDy = 0;
break;
case "ArrowUp":
case "z":
case "Z":
pacman.nextDx = 0;
pacman.nextDy = -speed;
break;
case "ArrowDown":
case "s":
case "S":
pacman.nextDx = 0;
pacman.nextDy = speed;
break;
}
});
function isWall(pixelX, pixelY) {
let c = Math.floor(pixelX / tileSize);
let r = Math.floor(pixelY / tileSize);
if (r === 8 || r === 10 || r === 12) {
if (pixelX < 0 || pixelX >= canvas.width) return false;
}
if (r < 0 || r >= map.length || c < 0 || c >= map[0].length)
return true;
return map[r][c] === 1;
}
function checkCollisionBox(x, y, radius) {
const corners = [
{ x: x - radius, y: y - radius },
{ x: x + radius, y: y - radius },
{ x: x - radius, y: y + radius },
{ x: x + radius, y: y + radius },
];
for (let corner of corners) {
if (isWall(corner.x, corner.y)) return true;
}
return false;
}
function isAtIntersection(x, y) {
return (
(x - tileSize / 2) % tileSize === 0 &&
(y - tileSize / 2) % tileSize === 0
);
}
function update() {
if (pacman.x < -tileSize / 2) {
pacman.x = canvas.width + tileSize / 2;
} else if (pacman.x > canvas.width + tileSize / 2) {
pacman.x = -tileSize / 2;
}
// Changement de direction immédiat si la voie est libre dans la nouvelle direction désirée
if (pacman.nextDx !== 0 || pacman.nextDy !== 0) {
// Demi-tour instantané autorisé
if (pacman.nextDx === -pacman.dx && pacman.nextDy === -pacman.dy) {
pacman.dx = pacman.nextDx;
pacman.dy = pacman.nextDy;
}
// Changement normal si on passe par une intersection ou si l'axe change proprement
else if (
!checkCollisionBox(
pacman.x + pacman.nextDx,
pacman.y + pacman.nextDy,
pacman.radius,
)
) {
// Si on change d'axe (ex: on va verticalement et on veut aller horizontalement), on s'assure d'être aligné sur la grille
if (
(pacman.dx !== 0 && pacman.nextDy !== 0) ||
(pacman.dy !== 0 && pacman.nextDx !== 0)
) {
if (isAtIntersection(pacman.x, pacman.y)) {
pacman.dx = pacman.nextDx;
pacman.dy = pacman.nextDy;
}
} else {
pacman.dx = pacman.nextDx;
pacman.dy = pacman.nextDy;
}
}
}
// Avancer Pac-Man s'il n'y a pas de mur devant lui
if (
!checkCollisionBox(
pacman.x + pacman.dx,
pacman.y + pacman.dy,
pacman.radius,
)
) {
pacman.x += pacman.dx;
pacman.y += pacman.dy;
} else {
pacman.dx = 0;
pacman.dy = 0;
}
let gridX = Math.floor(pacman.x / tileSize);
let gridY = Math.floor(pacman.y / tileSize);
if (
gridY >= 0 &&
gridY < map.length &&
gridX >= 0 &&
gridX < map[0].length
) {
if (map[gridY][gridX] === 2) {
map[gridY][gridX] = 0;
score += 10;
document.getElementById("score").innerText = score;
}
}
ghosts.forEach((ghost) => {
if (ghost.x < -tileSize / 2) ghost.x = canvas.width + tileSize / 2;
if (ghost.x > canvas.width + tileSize / 2) ghost.x = -tileSize / 2;
if (isAtIntersection(ghost.x, ghost.y)) {
const possibleDirs = [
{ dx: speed, dy: 0 },
{ dx: -speed, dy: 0 },
{ dx: 0, dy: speed },
{ dx: 0, dy: -speed },
];
const oppositeDx = -ghost.dx;
const oppositeDy = -ghost.dy;
let validDirs = possibleDirs.filter((d) => {
if (d.dx === oppositeDx && d.dy === oppositeDy) return false;
let nextX = ghost.x + d.dx * 4;
let nextY = ghost.y + d.dy * 4;
return !checkCollisionBox(nextX, nextY, tileSize / 2 - 4);
});
if (validDirs.length === 0) {
validDirs = [{ dx: oppositeDx, dy: oppositeDy }];
}
let chosen =
validDirs[Math.floor(Math.random() * validDirs.length)];
ghost.dx = chosen.dx;
ghost.dy = chosen.dy;
}
if (
checkCollisionBox(
ghost.x + ghost.dx,
ghost.y + ghost.dy,
tileSize / 2 - 4,
)
) {
ghost.dx = -ghost.dx;
ghost.dy = -ghost.dy;
}
ghost.x += ghost.dx;
ghost.y += ghost.dy;
let dist = Math.hypot(pacman.x - ghost.x, pacman.y - ghost.y);
if (dist < tileSize / 2) {
lives--;
document.getElementById("lives").innerText = lives;
if (lives <= 0) {
alert("GAME OVER ! Score final : " + score);
document.location.reload();
} else {
pacman.x = 9 * tileSize + tileSize / 2;
pacman.y = 16 * tileSize + tileSize / 2;
pacman.dx = 0;
pacman.dy = 0;
pacman.nextDx = 0;
pacman.nextDy = 0;
}
}
});
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let r = 0; r < map.length; r++) {
for (let c = 0; c < map[r].length; c++) {
if (map[r][c] === 1) {
ctx.fillStyle = "#2563eb";
ctx.fillRect(c * tileSize, r * tileSize, tileSize, tileSize);
} else if (map[r][c] === 2) {
ctx.fillStyle = "#fde047";
ctx.beginPath();
ctx.arc(
c * tileSize + tileSize / 2,
r * tileSize + tileSize / 2,
6,
0,
Math.PI * 2,
);
ctx.fill();
}
}
}
ctx.fillStyle = "#facc15";
ctx.beginPath();
let angle = 0.2;
if (pacman.dx > 0) angle = 0.2;
if (pacman.dx < 0) angle = 1.2;
if (pacman.dy > 0) angle = 0.7;
if (pacman.dy < 0) angle = 1.7;
ctx.arc(
pacman.x,
pacman.y,
pacman.radius,
angle * Math.PI,
(angle + 1.6) * Math.PI,
);
ctx.lineTo(pacman.x, pacman.y);
ctx.fill();
ghosts.forEach((ghost) => {
ctx.fillStyle = ghost.color;
ctx.beginPath();
ctx.arc(ghost.x, ghost.y - 4, tileSize / 2 - 4, Math.PI, 0, false);
ctx.lineTo(ghost.x + tileSize / 2 - 4, ghost.y + tileSize / 2);
ctx.lineTo(ghost.x - tileSize / 2 + 4, ghost.y + tileSize / 2);
ctx.fill();
});
}
function loop() {
update();
draw();
setTimeout(loop, 1000 / 45);
}
loop();
</script>
</body>
</html>