premier
This commit is contained in:
797
game.js
Normal file
797
game.js
Normal file
@ -0,0 +1,797 @@
|
||||
const canvas = document.getElementById('gameCanvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const scoreElement = document.getElementById('score');
|
||||
const levelElement = document.getElementById('level');
|
||||
const statusElement = document.getElementById('status');
|
||||
const restartBtn = document.getElementById('restartBtn');
|
||||
const usernameInput = document.getElementById('username');
|
||||
const leaderboardElement = document.getElementById('leaderboard');
|
||||
|
||||
const CELL_SIZE = 20;
|
||||
const COLS = 30;
|
||||
const ROWS = 30;
|
||||
|
||||
const WALL = 1;
|
||||
const DOT = 2;
|
||||
const EMPTY = 0;
|
||||
const TUNNEL = 3;
|
||||
const BONUS_CHERRY = 4;
|
||||
const BONUS_LUDO = 5;
|
||||
|
||||
const originalMaze1 = [
|
||||
[1,1,1,1,1,1,1,1,1,1,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,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,1,2,2,2,2,2,2,1],
|
||||
[1,1,1,1,1,1,2,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,1,2,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,0,1,1,1,3,3,3,3,1,1,1,0,1,1,2,1,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,0,1,0,0,0,0,0,0,0,0,1,0,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,0,2,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,0,1,0,0,0,0,0,0,0,0,1,0,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,1,2,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,2,1,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,2,1,1,1,1,1,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,1,1,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,1,1,2,2,2,1],
|
||||
[1,1,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1],
|
||||
[1,1,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1],
|
||||
[1,2,2,2,2,2,2,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,1,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,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,1,1,1,1,1,1,1,1,1,1]
|
||||
];
|
||||
|
||||
const originalMaze2 = [
|
||||
[1,1,1,1,1,1,1,1,1,1,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,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,2,1,1,2,1,1,1,1,2,1,1,2,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,1,1,2,1,1,2,1,1,2,1,1,1,1,2,1,1,2,1,1,2,1,1,2,2,2,1],
|
||||
[1,1,1,2,1,1,2,2,2,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,1,1,2,1,1,1],
|
||||
[1,2,2,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,2,2,2,2,2,1],
|
||||
[1,1,1,1,1,1,2,1,1,2,2,2,2,2,1,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,0,0,0,0,0,0,0,0,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,0,1,1,3,3,1,1,0,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,2,1,0,1,0,0,0,0,1,0,1,2,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,0,2,0,0,2,0,0,1,0,0,0,0,1,0,0,2,0,0,2,0,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,2,1,0,1,0,0,0,0,1,0,1,2,1,1,2,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,0,1,1,1,1,1,1,0,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,0,0,0,0,0,0,0,0,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[0,0,0,0,0,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,2,1,1,2,2,2,2,2,1,1,2,2,2,2,2,1,1,2,1,1,1,1,1,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,1,1,1,2,1,1,2,1,1,1,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,1,1,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,1,1,2,2,2,1],
|
||||
[1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1],
|
||||
[1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,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,1,1,1,1,1,1,1,1,1,1]
|
||||
];
|
||||
|
||||
const originalMaze3 = [
|
||||
[1,1,1,1,1,1,1,1,1,1,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,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,1],
|
||||
[1,1,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1],
|
||||
[1,2,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,0,0,0,0,0,0,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,0,1,1,1,1,0,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,1,1,0,1,3,3,1,0,1,1,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,1,1,1,1,1,1,1,1,2,1,1,0,1,1,1,1,0,1,1,2,1,1,1,1,1,1,1,1,1],
|
||||
[0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0],
|
||||
[1,1,1,1,1,1,1,1,1,2,1,1,0,1,1,1,1,0,1,1,2,1,1,1,1,1,1,1,1,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,1,1,0,1,3,3,1,0,1,1,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,0,1,1,1,1,0,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,0,0,0,0,0,0,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,2,2,2,2,1],
|
||||
[1,1,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1],
|
||||
[1,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,1],
|
||||
[1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1],
|
||||
[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,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,1,1,1,1,1,1,1,1,1,1]
|
||||
];
|
||||
|
||||
const mazeVariants = [originalMaze1, originalMaze2, originalMaze3];
|
||||
let originalMaze = originalMaze1;
|
||||
let currentMazeIndex = 0;
|
||||
|
||||
let maze = originalMaze.map(row => [...row]);
|
||||
|
||||
let score = 0;
|
||||
let level = 1;
|
||||
let gameRunning = true;
|
||||
let totalDots = 0;
|
||||
const TEST_MODE = true;
|
||||
let cherriesEaten = 0;
|
||||
let isChangingLevel = false;
|
||||
|
||||
class Pacman {
|
||||
constructor() {
|
||||
this.x = 14;
|
||||
this.y = 23;
|
||||
this.direction = 0;
|
||||
this.nextDirection = 0;
|
||||
this.mouthAngle = 0;
|
||||
this.mouthOpen = true;
|
||||
this.speed = 0.15;
|
||||
this.pixelX = this.x * CELL_SIZE + CELL_SIZE / 2;
|
||||
this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!gameRunning) return;
|
||||
|
||||
this.mouthAngle += 0.2;
|
||||
if (this.mouthAngle > Math.PI * 2) {
|
||||
this.mouthAngle = 0;
|
||||
this.mouthOpen = !this.mouthOpen;
|
||||
}
|
||||
|
||||
const gridX = Math.floor(this.pixelX / CELL_SIZE);
|
||||
const gridY = Math.floor(this.pixelY / CELL_SIZE);
|
||||
|
||||
if (this.canMove(this.nextDirection)) {
|
||||
this.direction = this.nextDirection;
|
||||
}
|
||||
|
||||
if (this.canMove(this.direction)) {
|
||||
const dx = [0, 1, 0, -1];
|
||||
const dy = [-1, 0, 1, 0];
|
||||
|
||||
this.pixelX += dx[this.direction] * this.speed * CELL_SIZE;
|
||||
this.pixelY += dy[this.direction] * this.speed * CELL_SIZE;
|
||||
|
||||
if (this.pixelX < 0) {
|
||||
this.pixelX = COLS * CELL_SIZE;
|
||||
} else if (this.pixelX > COLS * CELL_SIZE) {
|
||||
this.pixelX = 0;
|
||||
}
|
||||
} else {
|
||||
this.pixelX = gridX * CELL_SIZE + CELL_SIZE / 2;
|
||||
this.pixelY = gridY * CELL_SIZE + CELL_SIZE / 2;
|
||||
}
|
||||
|
||||
this.x = Math.floor(this.pixelX / CELL_SIZE);
|
||||
this.y = Math.floor(this.pixelY / CELL_SIZE);
|
||||
|
||||
this.collectDot();
|
||||
}
|
||||
|
||||
canMove(direction) {
|
||||
const dx = [0, 1, 0, -1];
|
||||
const dy = [-1, 0, 1, 0];
|
||||
|
||||
const nextX = Math.floor((this.pixelX + dx[direction] * CELL_SIZE * 0.5) / CELL_SIZE);
|
||||
const nextY = Math.floor((this.pixelY + dy[direction] * CELL_SIZE * 0.5) / CELL_SIZE);
|
||||
|
||||
if (nextX < 0 || nextX >= COLS || nextY < 0 || nextY >= ROWS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return maze[nextY][nextX] !== WALL;
|
||||
}
|
||||
|
||||
collectDot() {
|
||||
if (maze[this.y][this.x] === DOT) {
|
||||
maze[this.y][this.x] = EMPTY;
|
||||
score += 10;
|
||||
scoreElement.textContent = score;
|
||||
totalDots--;
|
||||
|
||||
if (totalDots === 0 && !isChangingLevel) {
|
||||
console.log('Toutes les pastilles collectées, passage au niveau suivant');
|
||||
nextLevel();
|
||||
}
|
||||
} else if (maze[this.y][this.x] === BONUS_CHERRY) {
|
||||
if (isChangingLevel) {
|
||||
console.log('Changement de niveau en cours, cerise ignorée');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Cerise collectée, cherriesEaten:', cherriesEaten);
|
||||
maze[this.y][this.x] = EMPTY;
|
||||
score += 100;
|
||||
scoreElement.textContent = score;
|
||||
bonuses = bonuses.filter(b => !(b.x === this.x && b.y === this.y && b.type === BONUS_CHERRY));
|
||||
cherriesEaten++;
|
||||
|
||||
console.log('Après incrémentation, cherriesEaten:', cherriesEaten, 'TEST_MODE:', TEST_MODE, 'isChangingLevel:', isChangingLevel);
|
||||
|
||||
if (TEST_MODE && cherriesEaten >= 2 && !isChangingLevel) {
|
||||
console.log('2 cerises mangées, appel de nextLevel()');
|
||||
cherriesEaten = 0;
|
||||
nextLevel();
|
||||
}
|
||||
} else if (maze[this.y][this.x] === BONUS_LUDO) {
|
||||
maze[this.y][this.x] = EMPTY;
|
||||
score += 200;
|
||||
scoreElement.textContent = score;
|
||||
bonuses = bonuses.filter(b => !(b.x === this.x && b.y === this.y && b.type === BONUS_LUDO));
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
ctx.save();
|
||||
ctx.translate(this.pixelX, this.pixelY);
|
||||
|
||||
const rotation = [Math.PI * 1.5, 0, Math.PI * 0.5, Math.PI];
|
||||
ctx.rotate(rotation[this.direction]);
|
||||
|
||||
ctx.fillStyle = '#ffd700';
|
||||
ctx.beginPath();
|
||||
|
||||
if (this.mouthOpen) {
|
||||
ctx.arc(0, 0, CELL_SIZE * 0.4, 0.2, Math.PI * 2 - 0.2);
|
||||
} else {
|
||||
ctx.arc(0, 0, CELL_SIZE * 0.4, 0, Math.PI * 2);
|
||||
}
|
||||
|
||||
ctx.lineTo(0, 0);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
class Ghost {
|
||||
constructor(x, y, color) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.color = color;
|
||||
this.direction = Math.floor(Math.random() * 4);
|
||||
this.baseSpeed = 0.1;
|
||||
this.speed = this.baseSpeed;
|
||||
this.pixelX = this.x * CELL_SIZE + CELL_SIZE / 2;
|
||||
this.pixelY = this.y * CELL_SIZE + CELL_SIZE / 2;
|
||||
this.moveCounter = 0;
|
||||
}
|
||||
|
||||
updateSpeed() {
|
||||
this.speed = this.baseSpeed * (1 + (level - 1) * 0.15);
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!gameRunning) return;
|
||||
|
||||
this.moveCounter++;
|
||||
|
||||
if (this.moveCounter > 30 || !this.canMove(this.direction)) {
|
||||
const possibleDirections = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (this.canMove(i)) {
|
||||
possibleDirections.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (possibleDirections.length > 0) {
|
||||
this.direction = possibleDirections[Math.floor(Math.random() * possibleDirections.length)];
|
||||
}
|
||||
this.moveCounter = 0;
|
||||
}
|
||||
|
||||
const dx = [0, 1, 0, -1];
|
||||
const dy = [-1, 0, 1, 0];
|
||||
|
||||
this.pixelX += dx[this.direction] * this.speed * CELL_SIZE;
|
||||
this.pixelY += dy[this.direction] * this.speed * CELL_SIZE;
|
||||
|
||||
if (this.pixelX < 0) {
|
||||
this.pixelX = COLS * CELL_SIZE;
|
||||
} else if (this.pixelX > COLS * CELL_SIZE) {
|
||||
this.pixelX = 0;
|
||||
}
|
||||
|
||||
this.x = Math.floor(this.pixelX / CELL_SIZE);
|
||||
this.y = Math.floor(this.pixelY / CELL_SIZE);
|
||||
}
|
||||
|
||||
canMove(direction) {
|
||||
const dx = [0, 1, 0, -1];
|
||||
const dy = [-1, 0, 1, 0];
|
||||
|
||||
const nextX = Math.floor((this.pixelX + dx[direction] * CELL_SIZE * 0.5) / CELL_SIZE);
|
||||
const nextY = Math.floor((this.pixelY + dy[direction] * CELL_SIZE * 0.5) / CELL_SIZE);
|
||||
|
||||
if (nextX < 0 || nextX >= COLS || nextY < 0 || nextY >= ROWS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return maze[nextY][nextX] !== WALL;
|
||||
}
|
||||
|
||||
draw() {
|
||||
ctx.save();
|
||||
ctx.translate(this.pixelX, this.pixelY);
|
||||
ctx.fillStyle = this.color;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, -CELL_SIZE * 0.15, CELL_SIZE * 0.3, Math.PI, 0, false);
|
||||
ctx.rect(-CELL_SIZE * 0.3, -CELL_SIZE * 0.15, CELL_SIZE * 0.6, CELL_SIZE * 0.45);
|
||||
ctx.fill();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.rect(-CELL_SIZE * 0.3, CELL_SIZE * 0.3, CELL_SIZE * 0.2, CELL_SIZE * 0.2);
|
||||
ctx.rect(-CELL_SIZE * 0.1, CELL_SIZE * 0.3, CELL_SIZE * 0.2, CELL_SIZE * 0.2);
|
||||
ctx.rect(CELL_SIZE * 0.1, CELL_SIZE * 0.3, CELL_SIZE * 0.2, CELL_SIZE * 0.2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-CELL_SIZE * 0.15, -CELL_SIZE * 0.1, CELL_SIZE * 0.08, 0, Math.PI * 2);
|
||||
ctx.arc(CELL_SIZE * 0.15, -CELL_SIZE * 0.1, CELL_SIZE * 0.08, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-CELL_SIZE * 0.15, -CELL_SIZE * 0.1, CELL_SIZE * 0.04, 0, Math.PI * 2);
|
||||
ctx.arc(CELL_SIZE * 0.15, -CELL_SIZE * 0.1, CELL_SIZE * 0.04, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
class Bonus {
|
||||
constructor(x, y, type) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
this.animation = 0;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.animation += 0.1;
|
||||
if (this.animation > Math.PI * 2) {
|
||||
this.animation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
const cellX = this.x * CELL_SIZE + CELL_SIZE / 2;
|
||||
const cellY = this.y * CELL_SIZE + CELL_SIZE / 2;
|
||||
const scale = 1 + Math.sin(this.animation) * 0.2;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(cellX, cellY);
|
||||
ctx.scale(scale, scale);
|
||||
|
||||
if (this.type === BONUS_CHERRY) {
|
||||
ctx.fillStyle = '#ff0000';
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, CELL_SIZE * 0.25, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.fillStyle = '#00ff00';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-CELL_SIZE * 0.15, -CELL_SIZE * 0.2, CELL_SIZE * 0.1, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.strokeStyle = '#00aa00';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-CELL_SIZE * 0.15, -CELL_SIZE * 0.3);
|
||||
ctx.lineTo(-CELL_SIZE * 0.25, -CELL_SIZE * 0.4);
|
||||
ctx.stroke();
|
||||
} else if (this.type === BONUS_LUDO) {
|
||||
ctx.fillStyle = '#ffd700';
|
||||
ctx.font = `bold ${CELL_SIZE * 0.4}px Arial`;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText('L', 0, 0);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
let pacman = new Pacman();
|
||||
const ghosts = [
|
||||
new Ghost(14, 11, '#ff0000'),
|
||||
new Ghost(15, 11, '#ff00ff'),
|
||||
new Ghost(14, 12, '#00ffff'),
|
||||
new Ghost(15, 12, '#ffa500')
|
||||
];
|
||||
|
||||
let bonuses = [];
|
||||
|
||||
function countDots() {
|
||||
totalDots = 0;
|
||||
if (!maze || maze.length === 0) {
|
||||
console.error('countDots() - maze est vide ou undefined');
|
||||
return;
|
||||
}
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
if (!maze[y]) {
|
||||
console.error(`countDots() - maze[${y}] est undefined`);
|
||||
continue;
|
||||
}
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
if (maze[y][x] === DOT) {
|
||||
totalDots++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawMaze() {
|
||||
ctx.fillStyle = '#000';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
for (let y = 0; y < ROWS; y++) {
|
||||
for (let x = 0; x < COLS; x++) {
|
||||
const cellX = x * CELL_SIZE;
|
||||
const cellY = y * CELL_SIZE;
|
||||
|
||||
if (maze[y][x] === WALL) {
|
||||
ctx.fillStyle = '#0000ff';
|
||||
ctx.fillRect(cellX, cellY, CELL_SIZE, CELL_SIZE);
|
||||
ctx.strokeStyle = '#000080';
|
||||
ctx.strokeRect(cellX, cellY, CELL_SIZE, CELL_SIZE);
|
||||
} else if (maze[y][x] === DOT) {
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(cellX + CELL_SIZE / 2, cellY + CELL_SIZE / 2, 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let bonus of bonuses) {
|
||||
bonus.update();
|
||||
bonus.draw();
|
||||
}
|
||||
}
|
||||
|
||||
function checkCollisions() {
|
||||
if (!gameRunning) return;
|
||||
|
||||
for (let ghost of ghosts) {
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(pacman.pixelX - ghost.pixelX, 2) +
|
||||
Math.pow(pacman.pixelY - ghost.pixelY, 2)
|
||||
);
|
||||
|
||||
if (distance < CELL_SIZE * 0.6) {
|
||||
gameRunning = false;
|
||||
statusElement.textContent = 'Game Over !';
|
||||
restartBtn.style.display = 'block';
|
||||
saveScore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gameLoop() {
|
||||
if (isChangingLevel || !gameRunning) {
|
||||
if (isChangingLevel) {
|
||||
console.log('gameLoop() - Changement de niveau en cours, arrêt');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
drawMaze();
|
||||
pacman.update();
|
||||
pacman.draw();
|
||||
|
||||
for (let ghost of ghosts) {
|
||||
ghost.update();
|
||||
ghost.draw();
|
||||
}
|
||||
|
||||
checkCollisions();
|
||||
|
||||
if (gameRunning && !isChangingLevel) {
|
||||
requestAnimationFrame(gameLoop);
|
||||
} else {
|
||||
console.log('gameLoop() - Arrêt de la boucle, gameRunning:', gameRunning, 'isChangingLevel:', isChangingLevel);
|
||||
}
|
||||
}
|
||||
|
||||
function nextLevel() {
|
||||
console.log('=== nextLevel() appelée ===');
|
||||
console.log('gameRunning:', gameRunning, 'isChangingLevel:', isChangingLevel);
|
||||
|
||||
if (!gameRunning || isChangingLevel) {
|
||||
console.log('nextLevel() annulée - gameRunning:', gameRunning, 'isChangingLevel:', isChangingLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Début du changement de niveau');
|
||||
isChangingLevel = true;
|
||||
const wasRunning = gameRunning;
|
||||
gameRunning = false;
|
||||
console.log('gameRunning mis à false, wasRunning:', wasRunning);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
console.log('Dans requestAnimationFrame, changement du niveau');
|
||||
level++;
|
||||
console.log('Nouveau niveau:', level);
|
||||
levelElement.textContent = level;
|
||||
cherriesEaten = 0;
|
||||
|
||||
const mazeIndex = (level - 1) % mazeVariants.length;
|
||||
console.log('Index du labyrinthe:', mazeIndex);
|
||||
currentMazeIndex = mazeIndex;
|
||||
const newMaze = mazeVariants[mazeIndex];
|
||||
|
||||
console.log('Création du nouveau labyrinthe');
|
||||
console.log('newMaze.length:', newMaze.length, 'ROWS:', ROWS);
|
||||
console.log('newMaze[0]?.length:', newMaze[0]?.length, 'COLS:', COLS);
|
||||
|
||||
if (!newMaze || newMaze.length !== ROWS) {
|
||||
console.error('Erreur: Le nouveau labyrinthe a une taille incorrecte:', newMaze?.length);
|
||||
isChangingLevel = false;
|
||||
gameRunning = wasRunning;
|
||||
return;
|
||||
}
|
||||
|
||||
maze = [];
|
||||
for (let i = 0; i < newMaze.length; i++) {
|
||||
if (!newMaze[i] || newMaze[i].length !== COLS) {
|
||||
console.error(`Erreur: Ligne ${i} du labyrinthe a une taille incorrecte:`, newMaze[i]?.length);
|
||||
}
|
||||
maze[i] = [...newMaze[i]];
|
||||
}
|
||||
|
||||
console.log('Labyrinthe copié, maze.length:', maze.length);
|
||||
|
||||
randomizeMaze();
|
||||
|
||||
countDots();
|
||||
console.log('Total dots:', totalDots);
|
||||
|
||||
bonuses = [];
|
||||
|
||||
console.log('Réinitialisation de Pacman et des fantômes');
|
||||
pacman = new Pacman();
|
||||
ghosts[0] = new Ghost(14, 11, '#ff0000');
|
||||
ghosts[1] = new Ghost(15, 11, '#ff00ff');
|
||||
ghosts[2] = new Ghost(14, 12, '#00ffff');
|
||||
ghosts[3] = new Ghost(15, 12, '#ffa500');
|
||||
|
||||
for (let ghost of ghosts) {
|
||||
ghost.updateSpeed();
|
||||
}
|
||||
|
||||
placeBonuses();
|
||||
console.log('Bonus placés, nombre:', bonuses.length);
|
||||
|
||||
statusElement.textContent = `Niveau ${level} - Labyrinthe ${mazeIndex + 1} !`;
|
||||
statusElement.style.color = '#00ff00';
|
||||
|
||||
console.log('Redessin du labyrinthe');
|
||||
drawMaze();
|
||||
pacman.draw();
|
||||
for (let ghost of ghosts) {
|
||||
ghost.draw();
|
||||
}
|
||||
|
||||
console.log('Attente de 2 secondes avant redémarrage');
|
||||
setTimeout(() => {
|
||||
console.log('Redémarrage de la boucle de jeu');
|
||||
isChangingLevel = false;
|
||||
gameRunning = wasRunning;
|
||||
console.log('isChangingLevel:', isChangingLevel, 'gameRunning:', gameRunning);
|
||||
if (gameRunning) {
|
||||
statusElement.textContent = 'En jeu';
|
||||
statusElement.style.color = '#ffd700';
|
||||
console.log('Appel de gameLoop() pour redémarrer');
|
||||
gameLoop();
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
function randomizeMaze() {
|
||||
const modificationRate = 0.15;
|
||||
const changes = Math.floor(ROWS * COLS * modificationRate);
|
||||
|
||||
console.log('Modification aléatoire du labyrinthe,', changes, 'changements');
|
||||
|
||||
for (let i = 0; i < changes; i++) {
|
||||
const x = Math.floor(Math.random() * COLS);
|
||||
const y = Math.floor(Math.random() * ROWS);
|
||||
|
||||
if (x === 0 || x === COLS - 1 || y === 0 || y === ROWS - 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const currentCell = maze[y][x];
|
||||
|
||||
if (currentCell === WALL) {
|
||||
if (Math.random() < 0.7) {
|
||||
maze[y][x] = DOT;
|
||||
} else {
|
||||
maze[y][x] = EMPTY;
|
||||
}
|
||||
} else if (currentCell === EMPTY) {
|
||||
if (Math.random() < 0.6) {
|
||||
maze[y][x] = DOT;
|
||||
} else if (Math.random() < 0.3) {
|
||||
maze[y][x] = WALL;
|
||||
}
|
||||
} else if (currentCell === DOT) {
|
||||
if (Math.random() < 0.3) {
|
||||
maze[y][x] = EMPTY;
|
||||
} else if (Math.random() < 0.1) {
|
||||
maze[y][x] = WALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let y = 1; y < ROWS - 1; y++) {
|
||||
for (let x = 1; x < COLS - 1; x++) {
|
||||
if (maze[y][x] === WALL) {
|
||||
const neighbors = [
|
||||
maze[y-1][x], maze[y+1][x], maze[y][x-1], maze[y][x+1]
|
||||
];
|
||||
const wallCount = neighbors.filter(c => c === WALL).length;
|
||||
|
||||
if (wallCount === 0 && Math.random() < 0.4) {
|
||||
maze[y][x] = DOT;
|
||||
} else if (wallCount === 4 && Math.random() < 0.3) {
|
||||
maze[y][x] = EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Labyrinthe modifié aléatoirement');
|
||||
}
|
||||
|
||||
function placeBonuses() {
|
||||
bonuses = [];
|
||||
const bonusPositions = [
|
||||
{x: 1, y: 1, type: BONUS_CHERRY},
|
||||
{x: 28, y: 1, type: BONUS_CHERRY},
|
||||
{x: 1, y: 28, type: BONUS_CHERRY},
|
||||
{x: 28, y: 28, type: BONUS_CHERRY},
|
||||
{x: 14, y: 14, type: BONUS_LUDO},
|
||||
{x: 15, y: 14, type: BONUS_LUDO}
|
||||
];
|
||||
|
||||
for (let pos of bonusPositions) {
|
||||
if (maze[pos.y][pos.x] === EMPTY || maze[pos.y][pos.x] === DOT) {
|
||||
maze[pos.y][pos.x] = pos.type;
|
||||
bonuses.push(new Bonus(pos.x, pos.y, pos.type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initGame() {
|
||||
currentMazeIndex = 0;
|
||||
originalMaze = mazeVariants[0];
|
||||
maze = originalMaze.map(row => [...row]);
|
||||
countDots();
|
||||
score = 0;
|
||||
level = 1;
|
||||
cherriesEaten = 0;
|
||||
scoreElement.textContent = score;
|
||||
levelElement.textContent = level;
|
||||
gameRunning = true;
|
||||
statusElement.textContent = 'En jeu';
|
||||
statusElement.style.color = '#ffd700';
|
||||
restartBtn.style.display = 'none';
|
||||
|
||||
pacman = new Pacman();
|
||||
ghosts[0] = new Ghost(14, 11, '#ff0000');
|
||||
ghosts[1] = new Ghost(15, 11, '#ff00ff');
|
||||
ghosts[2] = new Ghost(14, 12, '#00ffff');
|
||||
ghosts[3] = new Ghost(15, 12, '#ffa500');
|
||||
|
||||
for (let ghost of ghosts) {
|
||||
ghost.updateSpeed();
|
||||
}
|
||||
|
||||
placeBonuses();
|
||||
countDots();
|
||||
gameLoop();
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (!gameRunning) return;
|
||||
|
||||
switch(e.key) {
|
||||
case 'ArrowUp':
|
||||
pacman.nextDirection = 0;
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
pacman.nextDirection = 1;
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
pacman.nextDirection = 2;
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
pacman.nextDirection = 3;
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
function getScores() {
|
||||
const scoresJson = localStorage.getItem('pacmanScores');
|
||||
return scoresJson ? JSON.parse(scoresJson) : [];
|
||||
}
|
||||
|
||||
function saveScore() {
|
||||
const username = usernameInput.value.trim() || 'Anonyme';
|
||||
if (score > 0) {
|
||||
const scores = getScores();
|
||||
scores.push({
|
||||
username: username,
|
||||
score: score,
|
||||
date: new Date().toISOString()
|
||||
});
|
||||
scores.sort((a, b) => b.score - a.score);
|
||||
const topScores = scores.slice(0, 10);
|
||||
localStorage.setItem('pacmanScores', JSON.stringify(topScores));
|
||||
updateLeaderboard();
|
||||
}
|
||||
}
|
||||
|
||||
function updateLeaderboard() {
|
||||
const scores = getScores();
|
||||
leaderboardElement.innerHTML = '';
|
||||
|
||||
if (scores.length === 0) {
|
||||
leaderboardElement.innerHTML = '<div class="empty-leaderboard">Aucun score enregistré</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
scores.forEach((entry, index) => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'leaderboard-item' + (index < 3 ? ' top' : '');
|
||||
|
||||
const rank = document.createElement('div');
|
||||
rank.className = 'leaderboard-rank';
|
||||
rank.textContent = (index + 1) + '.';
|
||||
|
||||
const name = document.createElement('div');
|
||||
name.className = 'leaderboard-name';
|
||||
name.textContent = entry.username;
|
||||
|
||||
const scoreDiv = document.createElement('div');
|
||||
scoreDiv.className = 'leaderboard-score';
|
||||
scoreDiv.textContent = entry.score;
|
||||
|
||||
item.appendChild(rank);
|
||||
item.appendChild(name);
|
||||
item.appendChild(scoreDiv);
|
||||
leaderboardElement.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
restartBtn.addEventListener('click', () => {
|
||||
initGame();
|
||||
});
|
||||
|
||||
updateLeaderboard();
|
||||
initGame();
|
||||
|
||||
39
index.html
Normal file
39
index.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Jeu Pacman</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-wrapper">
|
||||
<div class="container">
|
||||
<h1>PACMAN</h1>
|
||||
<div class="user-input-section">
|
||||
<label for="username">Nom d'utilisateur:</label>
|
||||
<input type="text" id="username" placeholder="Entrez votre nom" maxlength="15">
|
||||
</div>
|
||||
<div class="game-info">
|
||||
<div class="score">Score: <span id="score">0</span></div>
|
||||
<div class="level">Niveau: <span id="level">1</span></div>
|
||||
<div class="status" id="status">Prêt à jouer</div>
|
||||
</div>
|
||||
<canvas id="gameCanvas" width="600" height="600"></canvas>
|
||||
<div class="instructions">
|
||||
<p>Utilisez les flèches directionnelles pour déplacer Pacman</p>
|
||||
<button id="restartBtn" style="display: none;">Rejouer</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leaderboard-container">
|
||||
<h2>Classement</h2>
|
||||
<div id="leaderboard"></div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<p>By Ludo and Syoul</p>
|
||||
</footer>
|
||||
<script src="game.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
242
style.css
Normal file
242
style.css
Normal file
@ -0,0 +1,242 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
|
||||
color: #fff;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.main-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 30px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
margin-bottom: 20px;
|
||||
text-shadow: 3px 3px 6px rgba(0, 0, 0, 0.5);
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.game-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px 20px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 10px;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.score {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.level {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
#status {
|
||||
font-size: 1.2em;
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
#gameCanvas {
|
||||
border: 3px solid #ffd700;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.user-input-section {
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.user-input-section label {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#username {
|
||||
padding: 8px 15px;
|
||||
font-size: 1em;
|
||||
border: 2px solid #ffd700;
|
||||
border-radius: 8px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
color: #fff;
|
||||
outline: none;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
#username:focus {
|
||||
border-color: #ffed4e;
|
||||
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
.instructions {
|
||||
margin-top: 20px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.leaderboard-container {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||
min-width: 300px;
|
||||
max-height: 700px;
|
||||
}
|
||||
|
||||
.leaderboard-container h2 {
|
||||
color: #ffd700;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: 2em;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#leaderboard {
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.leaderboard-item {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-left: 4px solid #ffd700;
|
||||
}
|
||||
|
||||
.leaderboard-item.top {
|
||||
background: rgba(255, 215, 0, 0.2);
|
||||
border-left-color: #ffed4e;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.leaderboard-rank {
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
color: #ffd700;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
.leaderboard-name {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
margin-left: 15px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.leaderboard-score {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
color: #ffd700;
|
||||
min-width: 80px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.empty-leaderboard {
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
padding: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#restartBtn {
|
||||
margin-top: 15px;
|
||||
padding: 12px 30px;
|
||||
font-size: 1.2em;
|
||||
background: #ffd700;
|
||||
color: #000;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
#restartBtn:hover {
|
||||
background: #ffed4e;
|
||||
}
|
||||
|
||||
#restartBtn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding: 20px;
|
||||
color: #ffd700;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.main-wrapper {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.leaderboard-container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
#gameCanvas {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.game-info {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.user-input-section {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user