import React, { useState, useEffect, useCallback } from 'react'; import { Pacman, Ghost, Bonus } from '../../utils/entities'; import { mazeVariants } from '../../utils/mazeData'; import { fillEmptySpaces, randomizeMaze, getBonusPositions, countDots } from '../../utils/gameLogic'; import GameCanvas from '../GameCanvas/GameCanvas'; import GameInfo from '../GameInfo/GameInfo'; import UserInput from '../UserInput/UserInput'; import Leaderboard from '../Leaderboard/Leaderboard'; import { useGameState } from '../../hooks/useGameState'; import { useKeyboard } from '../../hooks/useKeyboard'; import { useLeaderboard } from '../../hooks/useLeaderboard'; import { saveScore } from '../../utils/leaderboard'; function Game() { const gameState = useGameState(); const { scores, addScore: addLeaderboardScore } = useLeaderboard(); const [username, setUsername] = useState(''); const [maze, setMaze] = useState([]); const [pacman, setPacman] = useState(null); const [ghosts, setGhosts] = useState([]); const [bonuses, setBonuses] = useState([]); const initializeGame = useCallback(() => { const initialMaze = mazeVariants[0].map(row => [...row]); fillEmptySpaces(initialMaze); randomizeMaze(initialMaze); setMaze(initialMaze); const newPacman = new Pacman(); newPacman.speed = newPacman.baseSpeed * (1 + (gameState.level - 1) * 0.05); setPacman(newPacman); const newGhosts = [ new Ghost(14, 11, '#ff0000'), new Ghost(15, 11, '#ff00ff'), new Ghost(14, 12, '#00ffff'), new Ghost(15, 12, '#ffa500') ]; newGhosts.forEach(ghost => ghost.updateSpeed(gameState.level)); setGhosts(newGhosts); const bonusPositions = getBonusPositions(); const newBonuses = []; const mazeCopy = initialMaze.map(row => [...row]); for (let pos of bonusPositions) { if (mazeCopy[pos.y][pos.x] === 0 || mazeCopy[pos.y][pos.x] === 2) { mazeCopy[pos.y][pos.x] = pos.type; newBonuses.push(new Bonus(pos.x, pos.y, pos.type)); } } setBonuses(newBonuses); setMaze(mazeCopy); }, [gameState.level]); useEffect(() => { initializeGame(); gameState.resetGame(); }, []); const handleCollect = useCallback((type, points) => { gameState.addScore(points); if (type === 'cherry') { const newCherriesEaten = gameState.cherriesEaten + 1; gameState.setCherriesEaten(newCherriesEaten); gameState.setCherryEatenRecently(true); gameState.setCherryEatenTimer(Math.max(150, 300 - (gameState.level - 1) * 20)); } }, [gameState]); const handleCollision = useCallback(() => { const newLives = gameState.lives - 1; gameState.setLives(newLives); if (newLives <= 0) { gameState.setGameRunning(false); gameState.setStatus('Game Over !'); if (username.trim() !== '') { saveScore(username, gameState.score); addLeaderboardScore(username, gameState.score); } } else { gameState.restartLevel(); setTimeout(() => { initializeGame(); gameState.setIsChangingLevel(false); gameState.setGameRunning(true); gameState.setStatus('En jeu'); }, 2000); } }, [gameState, username, initializeGame, addLeaderboardScore]); const handleNextLevel = useCallback(() => { const newLevel = gameState.level + 1; gameState.setLevel(newLevel); gameState.setCherriesEaten(0); gameState.setIsChangingLevel(true); gameState.setCherryEatenRecently(false); gameState.setCherryEatenTimer(0); setTimeout(() => { const mazeIndex = (newLevel - 1) % mazeVariants.length; const newMaze = mazeVariants[mazeIndex].map(row => [...row]); fillEmptySpaces(newMaze); randomizeMaze(newMaze); setMaze(newMaze); const newPacman = new Pacman(); newPacman.speed = newPacman.baseSpeed * (1 + (newLevel - 1) * 0.05); setPacman(newPacman); const newGhosts = [ new Ghost(14, 11, '#ff0000'), new Ghost(15, 11, '#ff00ff'), new Ghost(14, 12, '#00ffff'), new Ghost(15, 12, '#ffa500') ]; newGhosts.forEach(ghost => ghost.updateSpeed(newLevel)); setGhosts(newGhosts); const bonusPositions = getBonusPositions(); const newBonuses = []; const mazeCopy = newMaze.map(row => [...row]); for (let pos of bonusPositions) { if (mazeCopy[pos.y][pos.x] === 0 || mazeCopy[pos.y][pos.x] === 2) { mazeCopy[pos.y][pos.x] = pos.type; newBonuses.push(new Bonus(pos.x, pos.y, pos.type)); } } setBonuses(newBonuses); setMaze(mazeCopy); gameState.setIsChangingLevel(false); gameState.setGameRunning(true); gameState.setStatus('En jeu'); }, 2000); }, [gameState]); const handleKeyPress = useCallback((key) => { if (!gameState.gameRunning || !pacman) return; switch(key) { case 'ArrowUp': pacman.nextDirection = 0; break; case 'ArrowRight': pacman.nextDirection = 1; break; case 'ArrowDown': pacman.nextDirection = 2; break; case 'ArrowLeft': pacman.nextDirection = 3; break; default: break; } }, [gameState.gameRunning, pacman]); useKeyboard(handleKeyPress); const handleRestart = useCallback(() => { initializeGame(); gameState.resetGame(); }, [initializeGame, gameState]); useEffect(() => { if (gameState.cherryEatenTimer > 0) { const timer = setInterval(() => { const newTimer = gameState.cherryEatenTimer - 1; if (newTimer <= 0) { gameState.setCherryEatenRecently(false); gameState.setCherryEatenTimer(0); } else { gameState.setCherryEatenTimer(newTimer); } }, 16); return () => clearInterval(timer); } }, [gameState.cherryEatenTimer, gameState]); useEffect(() => { if (gameState.cherriesEaten >= 4 && !gameState.isChangingLevel && gameState.gameRunning) { handleNextLevel(); } }, [gameState.cherriesEaten, gameState.isChangingLevel, gameState.gameRunning, handleNextLevel]); return (
Utilisez les flèches directionnelles pour déplacer Oulvic
{!gameState.gameRunning && ( )}