From: Thomas Rimelen Date: Wed, 21 Oct 2026 13:26:58 +0000 (+0200) Subject: fix dockstring, game over in progress X-Git-Url: https://git.uwuaxy.net/Project%20Status.png?a=commitdiff_plain;h=c80d3ab54dd8a39e7c576ace8ce571c42aa41867;p=axy%2Fft%2Fpacman.git fix dockstring, game over in progress --- diff --git a/highscores.json b/highscores.json index 2ff216e..416a837 100644 --- a/highscores.json +++ b/highscores.json @@ -2,6 +2,21 @@ "scores": { "Axel": 30, "Thomas": 20, - "Garobert": 1 + "Garobert": 1, + "agilliar": 5, + "agilliaras": 5, + "": 7, + "sdasd": 7, + "sdasdswwsw": 7, + "asads": 6, + "sswswss": 6, + "dds": 7, + "s": 8, + "sssd": 7, + "w": 8, + "ssswsws": 7, + "sssssaaa": 7, + "ssss": 8, + "sws": 8 } } \ No newline at end of file diff --git a/src/pacman/game/__init__.py b/src/pacman/game/__init__.py index 39af5ec..9040306 100644 --- a/src/pacman/game/__init__.py +++ b/src/pacman/game/__init__.py @@ -149,6 +149,8 @@ class GameIsOver(Resource): @dataclass class PlayerName(Resource): + """Resource for player name.""" + name: str = "" @@ -181,8 +183,7 @@ class GameMenu(Component): class GameOver(Component): - """Component for game menu items. - """ + """Component for game menu items.""" pass @@ -224,9 +225,7 @@ class GhostStatus(Component): @dataclass class Ghost(Component): - """Component for ghost items storing the ghost variant and the home - coordinates and entity. - """ + """Component for ghost.""" variant: GhostVariant home: tuple[int, int] @@ -249,9 +248,7 @@ class TilePos(Component): @dataclass class InMotion(Component): - """Component for pacman or ghost movement storing the position, the provenance - and the direction. - """ + """Component for pacman or ghost movement.""" src: Entity pos: Entity @@ -260,17 +257,16 @@ class InMotion(Component): @dataclass class MoveSpeed(Component): - """Component for movement storing the movement speed by pixels per frames.""" + """Component storing the movement speed by pixels per frames.""" pixels_per_frame: float class Maze(Component): - """Component for maze storing the x and y dimension and the cells in a - dictionnary (coordonate entity). - """ + """Component for maze storing dimension and cells.""" def __init__(self, x: int, y: int) -> None: + """Init the maze with size.""" self._cells: dict[tuple[int, int], Entity] = {} self._x = x self._y = y @@ -278,7 +274,7 @@ class Maze(Component): @dataclass class Cell(Component): - """Component for the cells of the maze storing the value and the position.""" + """Component for the cells of the maze.""" n: int grid_pos: tuple[int, int] @@ -299,9 +295,7 @@ def remove_comment(s: str) -> str: def load_config(world: World) -> None: - """Load the configuration json file given in first argument and spawn the - Config resource. - """ + """Load the configuration json.""" if len(sys.argv) != 2: raise Exception( f"Expected exactly 1 argument, got {len(sys.argv) - 1}" @@ -332,7 +326,7 @@ def save_highscores(config: Config, scores: Highscores) -> None: def create_maze( world: World, assets: Assets[Sprite2D] ) -> Callable[[MazeGenerator], Entity]: - """System creating and adding the maze to the world.""" + """Add the maze to the world.""" def inner(maze: MazeGenerator) -> Entity: root_maze = Maze(len(maze.maze[0]), len(maze.maze)) @@ -375,7 +369,7 @@ def create_maze( def spawn_superpacgums( world: World, mazes: Query[Maze], assets: Assets[Sprite2D] ) -> None: - """System creating and adding super pacgums to the maze.""" + """Add super pacgums to the maze.""" pacgums = [] for maze in mazes: for pos in [ @@ -406,7 +400,7 @@ def spawn_pacgums( superpacgums: Query[ChildOf, SuperPacGum], assets: Assets[Sprite2D], ) -> None: - """System creating and adding pacgums to the maze.""" + """Add pacgums to the maze.""" ignore = {e.parent for e in superpacgums} pacgums = [] for ent, cell in cells: @@ -432,7 +426,7 @@ def spawn_pacgums( def setup_maze(world: World) -> None: - """System running the 'create_maze' system with a give MazeGenerator.""" + """Create maze with a given MazeGenerator.""" world.run_system(create_maze, MazeGenerator((14, 14))) @@ -440,7 +434,7 @@ def move_in_motion( entities: Query[tuple[InMotion, Coord2D, MoveSpeed]], positions: Query[Coord2D], ) -> None: - """System enabling movement operation for entity wit InMotion component.""" + """Enable movement operation for entity wit InMotion component.""" for motion, pos, speed in entities: if (dst := positions.get(motion.pos)) is None: continue @@ -455,7 +449,7 @@ def update_tile_pos( entities: Query[tuple[InMotion, Coord2D, TilePos]], cells: Query[Coord2D], ) -> None: - """System updating the tile position for entity wit InMotion component.""" + """Update the tile position for entity with InMotion component.""" for motion, coord, pos in entities: src = cells[motion.src] dst = cells[motion.pos] @@ -471,7 +465,7 @@ def spawn_pacman( cells: Query[Cell], config: Config, ) -> None: - """System creating and adding pacman to the maze.""" + """Add pacman to the maze.""" if (maze_t := maze_q.single()) is None: return maze, maze_ent = maze_t @@ -523,7 +517,7 @@ def spawn_ghosts( maze_q: Query[tuple[Maze, Entity]], config: Config, ) -> None: - """System creating and adding ghosts to the maze.""" + """Add ghosts to the maze.""" if (maze_t := maze_q.single()) is None: return maze, maze_ent = maze_t @@ -588,7 +582,7 @@ def move_pacman( cells: Query[tuple[Cell, Coord2D]], maze_q: Query[Maze], ) -> None: - """System giving target movement to pacman with the input given by the user.""" + """Give target movement to pacman with the input given by the user.""" if (maze := maze_q.single()) is None: return for coord, motion, pos in pacman_q: @@ -617,7 +611,7 @@ def collect_pacgum( score: GameState, config: Config, ) -> None: - """System managing the collision and collection of pacgum by pacman.""" + """Manage the collision and collection of pacgum by pacman.""" collided = [ pacgum for coord, pacgum in pacgums @@ -636,9 +630,7 @@ def collect_superpacgum( score: GameState, config: Config, ) -> None: - """System managing the collision and collection of superpacgum by pacman and - starting the ghost flee state if a superpacgum is collected. - """ + """Manage the collision and collection of superpacgum by pacman.""" collided = [ pacgum for pacgum_pos, pacgum in pacgums @@ -660,7 +652,7 @@ def collect_superpacgum( def respawn_pacman(pacmans: Query[tuple[Pacman, Coord2D, InMotion]]) -> None: - """System reseting pacman position when touched by ghost.""" + """Reset pacman position when touched by ghost.""" for pacman, pos, motion in pacmans: pos.xy = Vector2(*pacman.home).elementwise() * 64 motion.pos = pacman.home_entity @@ -668,7 +660,7 @@ def respawn_pacman(pacmans: Query[tuple[Pacman, Coord2D, InMotion]]) -> None: def respawn_ghost(ghosts: Query[tuple[Ghost, Coord2D, InMotion]]) -> None: - """System reseting ghost fleeing position when touched by pacman.""" + """Reset ghost fleeing position when touched by pacman.""" for ghost, pos, motion in ghosts: pos.xy = Vector2(*ghost.home).elementwise() * 64 motion.pos = ghost.home_entity @@ -685,7 +677,7 @@ def collide_ghost( state: GameState, config: Config, ) -> None: - """System managing the collision between by pacman and ghost.""" + """Manage the collision between by pacman and ghost.""" for pacman_pos in pacmans: for ghost_pos, status, ghost, motion, pos in ghosts: if ( @@ -719,7 +711,7 @@ def move_to_target( cells: Query[tuple[Cell, Coord2D]], maze_q: Query[Maze], ) -> None: - """System giving target movement to ghost.""" + """Give target movement to ghost.""" if (maze := maze_q.single()) is None: return for target, motion, pos, status in entities: @@ -759,7 +751,7 @@ def update_ghost_targets( pacman_q: Query[tuple[InMotion, TilePos], Pacman], cells: Query[Cell], ) -> None: - """System updating target to ghost.""" + """Update target to ghost.""" player = pacman_q.single() if player is None: return @@ -786,7 +778,7 @@ def update_ghost_targets( def update_chase_status(status_q: Query[GhostStatus], config: Config) -> None: - """System updating ghost status and cycle.""" + """Update ghost status and cycle.""" for status in status_q: target_time: int next_state: GhostState @@ -823,7 +815,7 @@ def update_chase_status(status_q: Query[GhostStatus], config: Config) -> None: def update_ghost_speed( ghost: Query[tuple[MoveSpeed, GhostStatus]], config: Config ) -> None: - """System updating ghost speed according to his state.""" + """Update ghost speed according to his state.""" for speed, status in ghost: match status.state: case GhostState.chase | GhostState.wander: @@ -835,7 +827,7 @@ def update_ghost_speed( def update_pacman_anim( pacman_q: Query[tuple[InMotion, AnimationSet], Pacman], ) -> None: - """System updating pacman animation according to his direction.""" + """Update pacman animation according to his direction.""" for motion, anim in pacman_q: anim.idx = motion.direction @@ -844,7 +836,7 @@ def update_ghost_anim( ghost_q: Query[tuple[InMotion, AnimationSet, GhostStatus], Ghost], config: Config, ) -> None: - """System updating pacman animation according to his direction and state.""" + """Update ghost animation according to his direction and state.""" for motion, anim, status in ghost_q: match status.state: case GhostState.chase | GhostState.wander: @@ -860,15 +852,12 @@ def update_ghost_anim( def start_pause_timer(timer: "InitialPauseTimer") -> None: - """System starting the initial pause timer.""" + """Start initial pause timer.""" timer.tick = 0 def setup_new_maze(world: World) -> None: - """System setting up the maze by running 'setup_maze', 'spawn_superpacgums', - 'spawn_pacgums', 'spawn_pacman', 'spawn_ghosts' and - 'start_pause_timer' systems. - """ + """Set up all system to spawn a new maze.""" for system in ( setup_maze, spawn_superpacgums, @@ -881,16 +870,17 @@ def setup_new_maze(world: World) -> None: def maze_exists(itr: Query[Maze]) -> bool: - """System cheking maze existance.""" + """Return if maze exist.""" return next(itr.__iter__(), None) is not None def game_is_over(game_over: Query[GameIsOver]) -> bool: + """Return if game is over.""" return next(game_over.__iter__(), None) is not None def in_game(world: World) -> bool: - """System cheking that the game is running.""" + """Return if the game is running.""" return world.run_simple_system( maze_exists ) and not world.run_simple_system(in_game_menu) @@ -899,7 +889,7 @@ def in_game(world: World) -> bool: def level_is_finished( pacgums: Query[SuperPacGum | PacGum], _: Not[GameIsOver] ) -> bool: - """System cheking the level completion.""" + """Return if level is completed.""" return next(iter(pacgums), None) is None @@ -909,9 +899,7 @@ def victory( queue: CommandQueue, state: GameState, ) -> None: - """System called when level is completed, generating a new level or finishing - the game if all levels are completed. - """ + """Despawn maze and spawn new maze or init game over.""" for maze in mazes: queue.queue(hierarchy.despawn_with_children(maze)) if state.level == 2: @@ -931,56 +919,47 @@ def level_is_lost( def spawn_game_over(world: World, fonts: Assets[Font]) -> None: # FIXME + """Display game over menu.""" + root = world.spawn( + tuple[WindowPositionned, GameOver], + ( + WindowPositionned(Vector2(0.5, 0), Vector2(0, 100)), + GameOver(), + ), + ) + font = fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:100") + text = "GAME OVER" world.spawn( - tuple[WindowPositionned, ShouldRender, TextDisplay, GameOver], + tuple[ChildOf, ShouldRender, CoordBundle, TextDisplay], ( - WindowPositionned(Vector2(0.5, 0), Vector2(-300, 100)), + ChildOf(root), ShouldRender(), - TextDisplay( - "GAME OVER", - fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:100"), - ), - GameOver(), + font.center_text_for(text, Vector2(0, 0)), + TextDisplay(text, font), ), ) + font = fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:40") world.spawn( - tuple[ - WindowPositionned, - ShouldRender, - ComputedText, - TextDisplay, - GameOver, - ], + tuple[ChildOf, ShouldRender, CoordBundle, ComputedText, TextDisplay], ( - WindowPositionned(Vector2(0.5, 0), Vector2(-100, 300)), + ChildOf(root), ShouldRender(), - ComputedText(cast(System[str], print_score)), - TextDisplay( - "Score", - fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:40"), - ), - GameOver(), + font.center_text_for("", Vector2(0, 300)), + ComputedText(cast(System[str], print_name)), + TextDisplay("", font), ), ) + font = fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30") world.spawn( - tuple[ - WindowPositionned, - ShouldRender, - ComputedText, - TextDisplay, - GameOver, - ], + tuple[ChildOf, ShouldRender, CoordBundle, ComputedText, TextDisplay], ( - WindowPositionned(Vector2(0.5, 0), Vector2(-300, 400)), + ChildOf(root), ShouldRender(), - ComputedText(cast(System[str], print_name)), - TextDisplay( - "Score", - fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30"), - ), - GameOver(), + font.center_text_for("Score = XXX", Vector2(0, 200)), + ComputedText(cast(System[str], print_score)), + TextDisplay("", font), ), ) @@ -992,7 +971,7 @@ def lose( mazes: Query[Entity, Maze], queue: CommandQueue, ) -> None: - """System called when the player lose the game.""" + """Despawn mane and run the game over.""" world.despawn_many(list(gui)) for maze in mazes: queue.queue(hierarchy.despawn_with_children(maze)) @@ -1001,20 +980,20 @@ def lose( def game_over(queue: CommandQueue) -> None: - """System called when game is finish.""" + """Spawn resources when game is over.""" queue.queue(lambda world: world.spawn_resource(GameIsOver())) queue.queue(lambda world: world.spawn_resource(PlayerName())) def update_game_timer(world: World, state: GameState) -> None: - """System updating the levels timer.""" + """Update the level timer.""" if world.run_simple_system(cheat_mode_enabled): return state.timer += 1 def initial_pause_done(timer: InitialPauseTimer, config: Config) -> bool: - """System cheking if the inital timer is done.""" + """Return if the inital timer is done.""" if timer.tick < config.initial_pos_timer: timer.tick += 1 return False @@ -1022,8 +1001,7 @@ def initial_pause_done(timer: InitialPauseTimer, config: Config) -> bool: def print_name(name: PlayerName) -> str: - """Return a string with the player score. - """ + """Return a string with the player score.""" return f"Enter your name: {name.name}" @@ -1044,9 +1022,7 @@ def print_timer(state: GameState, config: Config) -> str: def spawn_hud(world: World, fonts: Assets[Font]) -> None: - """System that print the Heads-Up Display in game with lives, levels and timer - informations. - """ + """Draw in game HUD with lives, levels and timer informations.""" world.spawn_many( tuple[ WindowPositionned, @@ -1084,7 +1060,7 @@ def start_game( hierarchy: Hierarchy[tuple[()]], menus: Query[Entity, MainMenu], ) -> None: - """System closing main menu and starting the game and Heads-Up Display.""" + """Close main menu and starting the game and HUD.""" for menu in menus: hierarchy.despawn_with_children(menu)(world) world.despawn_resource(SelectedButton) @@ -1095,14 +1071,14 @@ def start_game( def quit_game(world: World) -> None: - """System closing the game and quiting the program.""" + """Close the game and quiting the program.""" world.spawn_resource(WorldShouldExit()) def spawn_button( world: World, fonts: Assets[Font], sprites: Assets[Sprite2D] ) -> Callable[[WindowPositionned, str, System], Entity]: - """System creating and adding a button to the world.""" + """Add a button to the world.""" def inner(pos: WindowPositionned, s: str, cb: System) -> Entity: parent = world.spawn( @@ -1144,6 +1120,7 @@ def spawn_button( def spawn_cheat_info(world: World, fonts: Assets[Font]) -> None: + """Display 'CHEAT MODE ENABLED' on screen.""" world.spawn( tuple[ WindowPositionned, @@ -1166,20 +1143,24 @@ def spawn_cheat_info(world: World, fonts: Assets[Font]) -> None: def cheat_mode_enabled(cheat: Query[CheatMode]) -> bool: + """Return if cheat mode is emable.""" return next(cheat.__iter__(), None) is not None def enable_cheat_mode(world: World) -> None: + """Enable cheat mod.""" world.run_simple_system(spawn_cheat_info) world.spawn(CheatMode, CheatMode()) def disable_cheat_mode(world: World, cheats: Query[Entity, CheatMode]) -> None: + """Disable cheat mod.""" items: list[Entity] = [cheat for cheat in cheats] world.despawn_many(items) def toggle_cheat_mode(world: World) -> None: + """Enable or disable cheat mod.""" if world.run_simple_system(cheat_mode_enabled): world.run_simple_system(disable_cheat_mode) else: @@ -1193,7 +1174,7 @@ def close_current_game( gui: Query[Entity, GameGui], queue: CommandQueue, ) -> None: - """System removing maze with childrens and game graphical user interface.""" + """Remove maze with childrens and game GUI.""" world.run_simple_system(close_game_menu) world.despawn_resource(GameState) world.despawn_many(list(gui)) @@ -1204,18 +1185,18 @@ def close_current_game( def back_to_main_menu(world: World) -> None: - """System closing the current game and opening the main menu.""" + """Close the current game and open the main menu.""" world.run_simple_system(close_current_game) world.run_simple_system(setup_main_menu) def in_game_menu(menus: Query[GameMenu]) -> bool: - """System cheking if the main menu is running.""" + """Check if the main menu is running.""" return next(menus.__iter__(), None) is not None def toggle_game_menu(world: World) -> None: - """System opening or closing the game menu.""" + """Open or close the game menu.""" if world.run_simple_system(in_game_menu): world.run_simple_system(close_game_menu) else: @@ -1412,36 +1393,50 @@ def setup_main_menu(world: World) -> None: def test(events: WindowEvents) -> None: # FIXME + """Test.""" for key, state in events.keys_itr(): if state: print(key) def add_score( - world: World, name: PlayerName, state: GameState, scores: Highscores + world: World, + name: PlayerName, + state: GameState, + scores: Highscores, + menus: Query[Entity, GameOver], + queue: CommandQueue, + hierarchy: Hierarchy[tuple[()]], ) -> None: + """Add players score to highscores, save it and go to main menu.""" # FIXME scores.scores[name.name] = state.score world.run_simple_system(save_highscores) + # items = [item for item in menus] + # # world.despawn_many(items) + for menu in menus: + queue.queue(hierarchy.despawn_with_children(menu)) + world.despawn_resource(GameIsOver) world.run_simple_system(setup_main_menu) def get_player_name( world: World, events: WindowEvents, name: PlayerName ) -> None: + """Get the player name.""" for key, state in events.keys_itr(): if state and key == K_BACKSPACE and name.name != "": name.name = name.name[: len(name.name) - 1] if state and key in range(K_a, K_z) and len(name.name) < 10: char = "abcdefghijklmnopqrstuvwxyz"[key - K_a] name.name += char - if state and key == K_RETURN: + if state and key == K_RETURN and name.name != "": world.run_simple_system(add_score) return def run_game() -> None: - """Start with all necessary plugins and system to run the game.""" + """Run the game with all necessary plugins and system.""" World().with_plugins(graphics_plugins, minimal_plugins).with_systems( StartupSchedule, Systems(load_config, load_highscores, setup_main_menu) @@ -1458,7 +1453,6 @@ def run_game() -> None: update_chase_status, update_ghost_speed, update_game_timer, - test, ) .chain() .run_if(initial_pause_done, in_game)