Skip to content

mpadronrz/pac-man

Repository files navigation

Pac-Man 🕹️

A fully playable Pac-Man clone built from scratch with Python, Pygame, and a clean MVC architecture.

Pac-Man Gameplay


Overview

A full recreation of the classic Pac-Man arcade game built from scratch in Python with Pygame — from game logic and ghost AI to the graphical interface. Features procedurally generated mazes, a persistent highscore system, and a cheat mode. Built following a strict MVC architecture designed collaboratively before any code was written.


Architecture

The entire application follows a strict Model-View-Controller pattern designed as the foundation before implementation began.

MVC Architecture Diagram

Models — State and Logic

Models own all game state and business rules. They have zero knowledge of rendering or input handling.

Class Responsibility
PacMan Position, direction, buffered input (anticipatory turning), movement physics, cell snapping
Maze Stores the bitmask matrix, manages the pellet grid, validates traversability per direction
Ghost (abstract) Base movement, direction selection via shortest-distance heuristic, vulnerable state, spawn memory
GameStats Lives, score, level counter, point values per pellet/ghost type
ConfigParser Pydantic-validated config loader with automatic fallback to defaults
HighscoresValidator Persistent top-10 leaderboard with sorted insertion and file I/O

Controllers — Orchestration and State Machines

Controllers process input, update models, and tell views what to draw. They never touch pixels directly.

Class Responsibility
MainController Master loop and screen state machine (TITLE → GAME → END → TITLE)
GameController Per-frame game tick: move entities, check collisions, eat pellets, manage power-up timer, handle pause
TitleController Menu navigation across main menu, highscores view, and instructions view
EndController Win/lose display, highscore name entry (3-char input), score persistence
ScreenController Abstract base — defines the run(dt, events) → Optional[ScreenType] contract

Views — Rendering

Views receive data and draw it. They hold no game state and make no decisions.

Class Responsibility
GameRenderer Draws the maze (bitmask walls), pellets, Pac-Man (animated mouth), ghosts, HUD, and pause overlay
TitleRenderer Renders main menu options, highscore table with aligned columns, and instructions screen
EndRenderer Draws win/lose screens, score display, and the highscore name input interface
SpriteManager Loads all PNG assets at startup into a dictionary keyed by AssetType, handles scaling and rotation

Ghost AI

Each ghost extends the abstract Ghost base class and implements a single method — get_target_cell — that defines its personality. The base class handles all shared logic: grid movement, direction selection via shortest-distance heuristic, vulnerable state retreat, and sprite animation.

Ghost Personality Behavior
Blinky Blinky (Red) Shadow Targets Pac-Man's exact tile — pure direct pursuit
Pynky Pynky (Pink) Ambusher Targets 4 tiles ahead of Pac-Man's facing direction
Inky Inky (Blue) Wildcard Picks random offset targets — chaotic, unpredictable
Clyde Clyde (Orange) Shy Chases until within radius, then retreats to corner

When Pac-Man eats a super pellet, all ghosts enter vulnerable mode — they reverse course and flee toward their spawn corners. Eating a vulnerable ghost awards bonus points and respawns it.


Key Technical Decisions

  • Delta Time: Game loop uses delta time for framerate-independent movement and animations.
  • Bitmasking & Surface Caching: Maze geometry uses a 4-bit masking system (N, E, S, W) to determine wall borders. Walls are drawn once to a static Pygame Surface per level instead of redrawing every frame.
  • Procedural Generation: Mazes are generated at runtime via a seed-based algorithm (mazegenerator), ensuring replayability with deterministic layouts.
  • Input Buffering: Pac-Man's direction input is buffered ahead of intersections, mirroring the original arcade feel.
  • Config Validation: All game parameters are externalized in config.json and validated at startup with Pydantic, with automatic fallback to defaults.

Configuration

The game is configured via a config.json file that controls maze dimensions (width, height), number of lives, levels_quantity, scoring values, maze generation seed, and level_max_time. All fields are validated with Pydantic at startup — if the file is missing or malformed, the game falls back to default_files/default_config.json automatically.

Highscores

Scores are persisted in a JSON file (path defined in config). The leaderboard is sorted in descending order on load and on every insertion. A new score is only added if it matches or exceeds the lowest score on the board.

Controls

Key Action
/ W A S D Move Pac-Man (input is buffered)
Esc Pause / Resume
Enter Confirm selection
Backspace Go back in menus

Installation & Usage

Requirements: Python 3.12+, uv

Option 1: Using Make (Recommended)

make

Option 2: Using uv manually

uv sync
uv run python3 -m pac-man.py [config.json]

Other targets:

make test          # Run unit & integration tests
make lint          # flake8 + mypy
make lint-strict   # mypy --strict
make clean         # Remove caches and venv

Technical Stack

Component Technology
Language Python 3.12+
Game framework Pygame
Data validation Pydantic
Maze generation mazegenerator (bundled wheel)
Testing Pytest
Linting flake8 + mypy
Package manager uv

Authors

Role Focus
mpadronrz Engine & Gameplay PacMan, Maze, GameController, GameRenderer — movement physics, collision system, input buffering, maze rendering
Edugs94 AI & Metagame Ghost definitions and behaviors, GameStats, parsers, MainController, ScreenController, TitleController, EndController, SpriteManager, menu renderers

The MVC architecture was designed collaboratively before any implementation began.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors