Okay, here is a complete Pac-Man game implemented in a single HTML file using HTML, CSS, and JavaScript.
This single HTML file contains the structure (HTML), styling (CSS within <style>
), and all the game logic (JavaScript within <script>
). Open this index.html
file in your browser to play the game. Use the arrow keys to control Pac-Man.
Okay, it seems like there might be an issue in the drawing logic or an early JavaScript error stopping the execution after drawing just one part of the map (likely the first wall tile).
Let's refine the code, particularly focusing on the drawing functions and ensuring the game loop runs correctly. I'll also adjust how collision detection and movement permissions are handled to be more robust.
Key Changes:
pacman.x
, pacman.y
, ghost.x
, ghost.y
now represent the center.canMove
Refinement: The canMove
function now takes the entity
as an argument and checks collision points around the entity's perimeter based on its radius and potential next position. It handles walls, ghost gate logic, and tunnel boundaries more explicitly.isAlignedToGrid
helper function to check if an entity is close enough to the center of a tile, which is crucial for making turns at intersections. Turns are now only allowed when aligned. Entities also snap to the grid center when turning or stopping at a wall.IN_HOUSE
, EXITING
) and logic for ghosts entering, waiting (with bobbing), exiting, and returning when eaten. Added simple exit delays.chooseBestDirection
and chooseRandomDirection
now use the refined canMove
and grid alignment checks. Ghosts prioritize directions based on standard Pac-Man rules (Up > Left > Right > Down).gameStarted
flag and a "Ready?" timer. The game loop now handles the initial delay and stops correctly on permanent game over or win. handleDeath
temporarily sets gameOver
to pause updates during the death sequence.map
array (though the original seemed okay, adjusted to common layouts). Ensured canvas height matches map rows.event.code
for better keyboard layout compatibility. Allowed immediate 180-degree turns.This revised version addresses potential issues with collision, movement logic, state management, and drawing that might have caused the previous version to fail or render incorrectly. Try running this updated index.html
._
Okay, if the drawing is correct but Pac-Man isn't moving, the issue likely lies in the input handling, the movement update logic (updatePacman
), or the collision detection (canMove
) preventing any movement from starting.
Let's add some console.log
statements to help diagnose where the process is breaking down and refine the movement logic slightly.
gameStarted
is true, gameOver
is false).pacman.dx
or pacman.dy
.canMove
is preventing the initial move.Here's the updated code with logging and minor adjustments:
Key Changes & Debugging Focus:
handleInput
: Added logs to confirm key presses are detected and requestedDirection
is set. Also added logic to potentially set the initial direction during the "Ready?" phase if the move is valid, allowing Pac-Man to start moving immediately when gameStarted
becomes true.updatePacman
:
console.log
) to trace the flow: checking requestedDirection
, alignment (isAlignedToGrid
), and collision (canMove
) during turns and forward movement. Check your browser's developer console (usually F12) for these messages.canMove
for the turn. It also has a condition to start movement if currently stopped.pacman.dx
or pacman.dy
is non-zero and canMove
allows it.isAlignedToGrid
: Added logging and adjusted the tolerance slightly based on speed. This function is critical for allowing turns only at the correct spots.canMove
: Added logging to pinpoint potential collision issues. Made sure tunnel logic correctly handles coordinates going out of bounds.init
: Corrected Pac-Man's starting X coordinate to be properly centered (TILE_SIZE * 10.5
). Reset readyTimer
in init
.gameStarted
becomes true and when the loop stops. Capped deltaTime
to prevent extreme jumps if the tab loses focus.gameOver
correctly pauses updates during the death sequence and resumes if lives remain. gameWon
also stops updates. Input is ignored if gameOver
or gameWon
.To Use:
index.html
file in your browser.Key pressed...
, Requested Direction Set...
).updatePacman
each frame (alignment, turn attempts, movement attempts, canMove
results).gameStarted
becomes true.Look for patterns: Is requestedDirection
being set but never applied? Is isAlignedToGrid
always false? Is canMove
always returning false when you try to move? The console logs should guide you to the exact point of failure._
Okay, the logs show the game initializes, starts, then Pac-Man immediately dies, resets, and dies again. This strongly suggests an instant collision is happening right at the start of the level or immediately after Pac-Man respawns.
The most likely causes are:
10.5 * TILE_SIZE
, 16.5 * TILE_SIZE
) is somehow causing an immediate collision check failure with a ghost's initial/reset position (especially Blinky, who starts outside the house at 10.5 * TILE_SIZE
, 8.5 * TILE_SIZE
).checkGhostCollisions
function's distance calculation or threshold is triggering incorrectly at the start.CHASE
instead of going back to IN_HOUSE
or SCATTER
appropriately) and instantly hits the newly spawned Pac-Man.Let's add more specific logging inside checkGhostCollisions
to see exactly which ghost is causing the collision and what their positions/states are. We'll also log the positions during the reset.
Changes Made:
checkGhostCollisions
: Added a console.log
that prints the positions, states, distance, and threshold only when Pac-Man and a ghost are potentially close (within one tile + threshold). This helps identify the culprit without flooding the console. Also added a specific log when a collision is detected. Made the collision threshold slightly more lenient (- 2
instead of - 4
).resetPositionsAfterDeath
: Added logs to confirm Pac-Man's reset position and that ghosts are being recreated. Recreating ghosts (createGhosts()
) is generally the safest way to ensure they are in the correct initial state after a death.handleDeath
: Slightly shortened the delay. Crucially, ensured gameOver
is set to true
immediately to stop further updates during the pause, and only set back to false
after positions are reset and the new readyTimer
starts.createGhosts
: Added logging to show the state and position of each ghost upon creation/reset. Increased the staggering of exit delays.init
: Ensured pacman
object is defined before createGhosts
is called. Added logging for Pac-Man's initial position.update
function: game must be started, not currently in the death pause (!gameOver
), and not won.Next Steps:
Collision Check:
logs. Which ghost (Ghost id
) is close to Pac-Man? What are their states and positions? Is the distance less than the threshold immediately?!!! Collision detected !!!
log. This confirms which ghost triggered handleDeath
.This detailed logging should pinpoint exactly why the instant death is occurring._
Okay, if the ghosts aren't leaving the cage, the problem is likely within the state management for IN_HOUSE
and EXITING
states in the updateGhosts
function, or potentially how canMove
handles the ghost house tiles (4 and 5) for ghosts trying to leave.
Let's focus on debugging that specific logic:
console.log
statements within the IN_HOUSE
and EXITING
state blocks in updateGhosts
to track their progress.canMove
: Double-check the conditions in canMove
related to ghosts, the gate (tile 4), and the house interior (tile 5). Ensure exiting ghosts can pass through the gate.ghostHouseCenter
and ghostExitPos
are correct relative to the map.Here's the code with added logging specifically for ghost exiting:
Changes Made:
canMove
: Explicitly added continue
statements for tile 5 (house interior) and tile 4 (gate) when the ghost state is EXITING
or EATEN
. This ensures they are allowed to be on these tiles in those specific states. Added a check to block non-exiting/eaten ghosts from entering the gate (tile 4).updateGhosts
:
IN_HOUSE
state to track the exitDelayTimer
.EXITING
.EXITING
state to track the ghost's Y position relative to the target ghostExitPos.y
.console.error
) if canMove
returns false
during an EXITING
movement attempt, as this indicates a problem.console.warn
) if any ghost movement gets blocked.How to Debug:
Ghost X ...
:
Waiting in house...
? Does the timer decrease?Reached center X, changing state to EXITING...
?Exiting. y=..., targetY=...
? Does the y
value decrease towards the targetY
?CANNOT MOVE while EXITING!
errors? If so, this points directly to the canMove
function or the coordinates being wrong.Exited house! ...
?This should clearly show at which step the exiting process is failing for each ghost (Pinky, Inky, Clyde).*_