This is a complete implementation of the classic Pac-Man game for the LandTiger LPC1768 development board, developed using Keil uVision. The project features modular code, real-time interrupt handling, and an optimized rendering system.
This project was developed for the course Computer Architectures in my Master's Degree in Artificial Intelligence and Data Analytics at Politecnico di Torino.
- Pac-Man Movement: Controlled via the joystick, managed by Timer 0 interrupts.
- Ghost AI (Blinky): Moves autonomously using the A pathfinding algorithm*, with movement controlled by Timer 2.
- Game Map: Defined as a character array containing walls, empty spaces, normal pills, and power pills.
- Scoring System:
- 10 points for eating a normal pill.
- 50 points for eating a power pill.
- Power Mode: Activated upon eating a power pill, allowing Pac-Man to eat ghosts for a limited time, managed by Timer 2.
- Lives System: Pac-Man starts with a set number of lives, which decrease upon being caught by a ghost.
- Game Timer: A countdown timer displayed on the screen, managed by Timer 1.
- Win/Loss Conditions:
- The game ends when Pac-Man runs out of lives.
- The game is won when all pills are collected.
The project is divided into multiple C and header files for clarity and maintainability:
- AsciiLib.c / AsciiLib.h: Handles 8x16 ASCII characters.
- HzLib.c / HzLib.h: Manages GB2312 Chinese characters.
- CAN.h: Interface for CAN communication, defining the
CAN_msgstructure. - GLCD.c / GLCD.h: Handles LCD display interface.
- TouchPanel.c / TouchPanel.h: Manages the touch panel via SPI (SSP1).
- RIT.h: Header for RIT interrupts.
- IRQ_CAN.c: Handles CAN communication interrupts.
- IRQ_RIT.c: Manages the RIT timer interrupt, used for joystick input.
- IRQ_timer.c: Controls game timing, Pac-Man movement, ghost movement, and countdown.
- funct_led.c: Manages LED functions.
- functions.h: Declares global variables (countdown, score, path, open_list, closed_list, game state flags).
- game.c: Implements scoring system, pill management, and power mode.
- blinky.c: Implements Blinky’s movement and pathfinding.
- pacman.c: Handles Pac-Man's movement and interactions.
- lib_CAN.c: Implements CAN communication.
- lib_RIT.c: Provides RIT timer functions.
- lib_timer.c: Manages timer-based events.
- music.h: Defines musical notes and durations.
- joystick.h: Defines joystick input handling.
- led.h: Defines LED control functions.
- mpu_armv7.h: Provides Memory Protection Unit (MPU) configuration.
- sample.c: The main game logic file.
- Function:
move_pacman()inpacman.c- Calculates Pac-Man's new position based on the current direction (
UP,DOWN,LEFT,RIGHT), set by the joystick input handled by the RIT interrupt (IRQ_RIT.c). - Validates the new position by checking the
game_map. If the next position contains a wall (WALL,HOR_WALL,VER_WALL), the movement is blocked. - Updates the
game_mapwith Pac-Man's new position and clears the old position by drawing an empty space (EMPTY). The position is stored in global variablespacman_xandpacman_y. - Teleportation: If Pac-Man moves off the map sides, he reappears on the opposite side.
- Pill Interaction: Calls
compute_score()if Pac-Man moves onto a cell containing a pill (PILLorPOWER_PILL). - Ghost Interaction: Checks if Pac-Man is on the same position as Blinky (
blinky_x,blinky_y). Callseat_ghost()if in power mode (is_power_mode = PM_ON), otherwise callslose_life().
- Calculates Pac-Man's new position based on the current direction (
- Function:
move_blinky()inblinky.c- Responsible for Blinky's movement, based on the path calculated by
find_path()and stored in the global variablepath. - Movement is controlled by Timer 2, moving Blinky towards the next node in the path.
- Updates the
game_mapwith Blinky's new position and clears the old position. - Power Mode: Changes Blinky's color to blue when power mode is active (
is_power_mode = PM_ON), otherwise red. - Pac-Man Interaction: Checks if Blinky is on the same position as Pac-Man. Calls
eat_ghost()if in power mode, otherwise callslose_life().
- Responsible for Blinky's movement, based on the path calculated by
- Function:
find_path()inblinky.c- Computes the shortest path for Blinky to reach its destination.
- Destination is determined by
compute_destination(), which selects Pac-Man's position if power mode is off, otherwise selects a corner of the map. - Uses two lists:
open_list(nodes to explore) andclosed_list(explored nodes). Functionsadd_open_list()andadd_closed_list()manage these lists. - At each iteration, the node with the lowest cost
f(sum ofgandh) is extracted fromopen_listusingpop_lowest_f()and added toclosed_list. - Cost
grepresents the distance from the starting point, whilehis a heuristic estimate of the distance to the destination, calculated bydistance(). - Once the path is found, it is reconstructed using
previous_indexvalues and saved in the global variablepath. - Atomic locks
find_lockandmove_lockprevent race conditions during execution.
- Function:
compute_score()ingame.c- Updates the score when Pac-Man eats a pill.
- Normal pills (
PILL) add 10 points, while power pills (POWER_PILL) add 50 points and activate power mode. - Score is stored in the global variable
score. - Lives are updated graphically using
remove_life()ingame.c. - Score and lives are updated on the screen using
GLCD,AsciiLib, andHzLib.
- Activated when Pac-Man eats a power pill (
POWER_PILL), signaled byis_power_mode = PM_ON. - During power mode, Blinky turns blue in
move_blinky(). - Duration is managed by Timer 2, setting a specific timer value when power mode is activated.
is_power_modeis checked inIRQ_timer.c. - When time expires, power mode is deactivated (
is_power_mode = PM_OFF), and Blinky's pathfinding is recalculated inIRQ_timer.c. - If Pac-Man eats Blinky in power mode, extra points are awarded, and Blinky's path is reset.
- Function:
lose_life()ingame.c- Called when Pac-Man is caught by Blinky outside power mode.
- Decrements the life counter (
lives_counter) and updates the graphical representation by callingremove_life()to erase a yellow circle representing a life. - If
lives_counterreaches 0,gameover()is called.
- Represented by the global variable
countdown, decremented every second by Timer 1 inIRQ_timer.c. - When
countdownreaches 0,gameover()is called. previous_countdownis used to send the current countdown value via CAN inIRQ_timer.c.
- Manages Pac-Man's movement (via
move_pacman()in the interrupt handler) and decrementscountdown. - Also handles music playback by calling
playNote().isNotePlaying()checks if a note is currently playing. - Music logic is managed by a software timer in
IRQ_RIT.cand hardware timers Timer 0 and Timer 3, with functionsinit_timer(),enable_timer(), andreset_timer()inlib_timer.c. - Note duration is controlled by Timer 3 using the
durationparameter in theNOTEstruct defined inmusic.h.
- Manages countdown decrement and displays the game-over message when the timer expires.
- Manages Blinky's movement (via
move_blinky()). - Controls the duration of power mode.
- Sends updated game data (score, lives, and remaining time) via CAN every second in
IRQ_timer.c. Data is sent using theCAN_TxMsgstructure andCAN_wrMsg()function. - Synchronizes the duration of musical notes in
music.candIRQ_RIT.c.
- Manages joystick input reading and sets the command for Pac-Man's movement.
- Implemented with
CAN_wrMsg()(writes a CAN message) andCAN_wrFilter()(configures filters) inlib_CAN.c. - The
CAN_msgstructure inCAN.hcontains fieldsformat,type,id,len, anddatafor message transmission. - Game data (score, lives, and remaining time) is transmitted cyclically via
CAN_wrMsg()inIRQ_timer.cto communicate with other systems. Message reception is handled by theCAN_IRQHandler. - The global variable
icrinIRQ_CAN.ctracks the status of CAN interrupts.
- Open the project in Keil uVision.
- Set the target to
"LandTiger_LPC1768". - Compile the project.
- Connect the LandTiger board via USB.
- Download and execute the program on the board.
- Ghost AI: The current implementation of A* search for Blinky can be improved for better performance.
- Joystick Responsiveness: Some delay occurs in movement recognition.
- CAN Communication: The feature is not fully utilized in the current version.
This project is released under the MIT License.
Developed by Marco as part of an embedded systems project.
If you find this project helpful, feel free to ⭐ the repository! 🚀