From 0cdd1cbc551d080860f3eeb403cad69d98d3d44f Mon Sep 17 00:00:00 2001 From: Axy Date: Fri, 23 Oct 2026 00:12:08 +0200 Subject: [PATCH] Building, makefile improvements, partial readme, and refactor --- .gitignore | 2 +- Makefile | 4 +- README.md | 79 +++++++++++++++++++++++++++++++++++++ requirements.txt | 19 +++++++++ src/pacman/game/__init__.py | 16 -------- 5 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index eed60d3..858b83f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ a.txt **/__pycache__ .mypy_cache .ruff_cache -dist/ +/pacman diff --git a/Makefile b/Makefile index 824a78f..ff0e902 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,6 @@ clean: find . -type d -name ".mypy_cache" -exec rm -r {} + find . -type d -name ".ruff_cache" -exec rm -r {} + find . -type d -name "*.pyc" -delete -# @rm -rf .venv lint: uv run flake8 src @@ -37,4 +36,5 @@ check: uv run ty check build: - uv build + uv pip compile pyproject.toml -o requirements.txt + uv run shiv -o pacman -e pacman:main -r requirements.txt . diff --git a/README.md b/README.md index f541daa..09edb8d 100644 --- a/README.md +++ b/README.md @@ -1 +1,80 @@ *This project has been created as part of the 42 curriculum by agilliar and trimelen* + +# Description + +`pacman` is a simple 2d arcade game made in python. +It was implemented using a custom ECS engine, and pygame as a rendering frontend. + +# Instructions + +`uv` is required to run or build the program. + +It can simply be built with +```bash +uv run pacman ./config.json +``` +It can also be built with +```bash +make build +``` +followed by +```bash +./pacman ./config.json +``` + +`pacman` must be given a json config file to run. + +# Resources + +TODO + +# Configuration + +TODO + +# Highscore + +The highscore is a simple json file written to when changed. Only one highscore per name. + +# Maze Generation + +The mazegen api is simply installed through the wheel, and called to generate the maze. + +# Implementation + +An ECS engine was used, as it is generally very effective at expressing game logic. +No already existing python ECS engine was adequately featured, so a custom one was made, with features including: +* Archetypal querying +* Complex scheduling +* System argument extraction based on type hints +* Component hooks +Pygame was used as a very simple rendering backend within the ECS, making for very reusable code for other game applications. +Thanks to ECS, the core game logic was straightforwardly implemented with little thought required for rendering or asset loading once they were implemented in engine. + +# General Software Architecture + +The whole engine is centered around the `ecs` module: +The `World` centralizes all the data and behavior. It schedules `System`s, ordered on a `DAG`. +`System`s are function whose arguments may be extracted from a `World`, like a `Query` or `Resource`. +The `World` stores its data on `Entity`s, as `Component`s, which may be later queried. +`ComponentHook`s are used to get notified when changes occur for specific types. +The `World` may extend its behavior through `Plugin`s. + +`Entity`s support hierarchy through the `ChildOf` and `Children` component, whose invariants are maintained through `ComponentHooks`. +The hierarchy (queriable through `Hierarchy`) is, among other things, used to update children coordinates and depth relative to their parents. + +`Asset`s are managed in the `ecs.assets` module, allowing for caching stored in `Resouce`s. + +The `gui` module allows for text rendering and basic layout operations, such as `Window` relative positionning. + +The rendering and input management is done very simply through a single `Plugin`, `ecs.graphics`, bridging between `pygame` and the ECS. + +The general game logic is then implemented on top of that in a single `game` module containing all desired behavior. +This includes `Maze` generation through the provided `mazegen` library, `Ghost` pathing, `GameState`, menus, etc. + +The whole is packaged as an executable for distribution using `shiv`. + + +# Project Management + +TODO diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0610ff7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,19 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml -o requirements.txt +annotated-types==0.8.0 + # via pydantic +mazegenerator-2.0.2-py3-none-any.whl + # via pacman (pyproject.toml) +pydantic==2.14.1 + # via pacman (pyproject.toml) +pydantic-core==2.50.1 + # via pydantic +pygame==2.6.1 + # via pacman (pyproject.toml) +typing-extensions==4.16.0 + # via + # pydantic + # pydantic-core + # typing-inspection +typing-inspection==0.4.4 + # via pydantic diff --git a/src/pacman/game/__init__.py b/src/pacman/game/__init__.py index ceff113..e23322e 100644 --- a/src/pacman/game/__init__.py +++ b/src/pacman/game/__init__.py @@ -151,8 +151,6 @@ class Highscores(Resource, BaseModel): class GameIsOver(Resource): """Resource set when game is over.""" - pass - @dataclass class PlayerName(Resource): @@ -175,44 +173,30 @@ class GameState(Resource): class CheatMode(Component): """Component for the cheat mod.""" - pass - class MainMenu(Component): """Component for main menu items.""" - pass - class GameMenu(Component): """Component for game menu items.""" - pass - class GameOver(Component): """Component for game menu items.""" - pass - class GameGui(Component): """Component for game graphical user interface items.""" - pass - class PacGum(Component): """Component for pacgums items.""" - pass - class SuperPacGum(Component): """Component for super pacgums items.""" - pass - @dataclass class Pacman(Component): -- 2.53.0