From: Thomas Rimelen Date: Tue, 20 Oct 2026 14:04:03 +0000 (+0200) Subject: Cheat mod added, game over in progress X-Git-Url: https://git.uwuaxy.net/Project%20Status.png?a=commitdiff_plain;h=d9067600ac57a873aa3821a31b54bae892de6577;p=axy%2Fft%2Fpacman.git Cheat mod added, game over in progress --- diff --git a/config.json b/config.json index 0967ef4..2314f00 100644 --- a/config.json +++ b/config.json @@ -1 +1,13 @@ -{} +{ + "ghost_chase_speed": 2.5, + "ghost_flee_speed": 1.5, + "pacman_speed": 3.0, + "initial_pos_timer": 60, + "level_timer": 180, + "initial_lives": 3, + "score_pacgum": 1, + "score_superpacgum": 5, + "score_ghost": 20, + "superpacgum_duration": 480, + "highscores_path": "highscores.json" +} diff --git a/src/pacman/game/__init__.py b/src/pacman/game/__init__.py index 6bc3067..6e7b078 100644 --- a/src/pacman/game/__init__.py +++ b/src/pacman/game/__init__.py @@ -26,6 +26,7 @@ from pacman.ecs.graphics import ( ShouldRender, Sprite2D, StopAnimation, + WindowEvents, WindowPositionned, graphics_plugins, key_just_pressed, @@ -128,7 +129,7 @@ class InitialPauseTimer(Resource): class Config(Resource, BaseModel): """ - Configuration of the game. + Resource storing the configuration of the game. """ ghost_chase_speed: float = Field(default=2.5, ge=0.1, le=100.0) @@ -160,6 +161,11 @@ class GameIsOver(Resource): pass +@dataclass +class PlayerName(Resource): + name: str = "" + + @dataclass class GameState(Resource): """ @@ -172,6 +178,14 @@ class GameState(Resource): lives: int = 3 +class CheatMode(Component): + """ + Component for the cheat mod. + """ + + pass + + class MainMenu(Component): """ Component for main menu items. @@ -756,6 +770,8 @@ def collide_ghost( continue match status.state: case GhostState.wander | GhostState.chase: + if world.run_raw_system(cheat_mode_enabled): + continue world.run_raw_system(respawn_pacman) world.run_raw_system(respawn_ghost) world.run_raw_system(start_pause_timer) @@ -961,6 +977,10 @@ def maze_exists(itr: Query[Maze]) -> bool: return next(itr.__iter__(), None) is not None +def game_is_over(game_over: Query[GameIsOver]) -> bool: + return next(game_over.__iter__(), None) is not None + + def in_game(world: World) -> bool: """ System cheking that the game is running. @@ -1009,7 +1029,56 @@ def level_is_lost( return config.level_timer < state.timer or state.lives <= 0 +# def lose( +# world: World, +# queue: CommandQueue, +# ) -> None: +# """ +# System called when the player lose the game. +# """ +# world.run_raw_system(close_current_game) +# queue.queue(lambda world: world.add_raw_system(game_over)()) + + +def spawn_game_over(world: World, fonts: Assets[Font]) -> None: # FIXME + world.spawn( + tuple[ + WindowPositionned, + ShouldRender, + TextDisplay, + ], + ( + WindowPositionned(Vector2(0.5, 0), Vector2(-200, 100)), + ShouldRender(), + TextDisplay( + "GAME OVER", + fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:100"), + ), + ), + ) + + world.spawn( + tuple[ + WindowPositionned, + ShouldRender, + ComputedText, + TextDisplay, + ], + ( + WindowPositionned(Vector2(0.5, 0), Vector2(-200, 300)), + ShouldRender(), + ComputedText(cast(System[str], print_score)), # FIXME + TextDisplay( + "Score", + fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:50"), + ), + ), + ) + + def lose( + world: World, + gui: Query[Entity, GameGui], hierarchy: Hierarchy[tuple[()]], mazes: Query[Entity, Maze], queue: CommandQueue, @@ -1017,9 +1086,12 @@ def lose( """ System called when the player lose the game. """ + world.despawn_resource(GameState) + world.despawn_many(list(gui)) for maze in mazes: queue.queue(hierarchy.despawn_with_children(maze)) queue.queue(lambda world: world.add_raw_system(game_over)()) + world.run_raw_system(spawn_game_over) def game_over(queue: CommandQueue) -> None: @@ -1028,13 +1100,15 @@ def game_over(queue: CommandQueue) -> None: System called when game is finish. """ queue.queue(lambda world: world.spawn_resource(GameIsOver())) - print("Game over") + queue.queue(lambda world: world.spawn_resource(PlayerName())) -def update_game_timer(state: GameState) -> None: +def update_game_timer(world: World, state: GameState) -> None: """ System updating the levels timer. """ + if world.run_raw_system(cheat_mode_enabled): + return state.timer += 1 @@ -1177,7 +1251,50 @@ def spawn_button( return inner -def back_to_main_menu( +def spawn_cheat_info(world: World, fonts: Assets[Font]) -> None: + world.spawn( + tuple[ + WindowPositionned, + CoordBundle, + ShouldRender, + TextDisplay, + CheatMode, + ], + ( + WindowPositionned(Vector2(0.5, 0), Vector2(-500, 60)), + CoordBundle(depth=-20), + ShouldRender(), + TextDisplay( + "CHEAT MODE ENABLED", + fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:100"), + ), + CheatMode(), + ), + ) + + +def cheat_mode_enabled(cheat: Query[CheatMode]) -> bool: + return next(cheat.__iter__(), None) is not None + + +def enable_cheat_mode(world: World) -> None: + world.run_raw_system(spawn_cheat_info) + world.spawn(CheatMode, CheatMode()) + + +def disable_cheat_mode(world: World, cheats: Query[Entity, CheatMode]) -> None: + items: list[Entity] = [cheat for cheat in cheats] + world.despawn_many(items) + + +def toggle_cheat_mode(world: World) -> None: + if world.run_raw_system(cheat_mode_enabled): + world.run_raw_system(disable_cheat_mode) + else: + world.run_raw_system(enable_cheat_mode) + + +def close_current_game( world: World, hierarchy: Hierarchy[tuple[()]], mazes: Query[Entity, Maze], @@ -1185,13 +1302,22 @@ def back_to_main_menu( queue: CommandQueue, ) -> None: """ - System closing the current game and opening the main menu. + System removing maze with childrens and game graphical user interface. """ world.run_raw_system(close_game_menu) world.despawn_resource(GameState) world.despawn_many(list(gui)) for maze in mazes: queue.queue(hierarchy.despawn_with_children(maze)) + if world.run_raw_system(cheat_mode_enabled): + world.run_raw_system(disable_cheat_mode) + + +def back_to_main_menu(world: World) -> None: + """ + System closing the current game and opening the main menu. + """ + world.run_raw_system(close_current_game) world.run_raw_system(setup_main_menu) @@ -1245,7 +1371,7 @@ def setup_game_menu( spawn_button, WindowPositionned(Vector2(0.5), Vector2(-150, -40)), "Cheat mod", - quit_game, + toggle_cheat_mode, ) quit_button = world.run_system( @@ -1411,6 +1537,21 @@ def setup_main_menu(world: World) -> None: world.spawn_resource(SelectedButton(selected)) +def test(events: WindowEvents) -> None: # FIXME + for key, state in events.keys_itr(): + if state: + print(key) + + +def get_player_name(events: WindowEvents, name: PlayerName) -> None: + for key, state in events.keys_itr(): + if state and key == 8 and name.name != "": + name.name = name.name[: len(name.name) - 1] + if state and key in range(97, 124): + char = "abcdefghijklmnopqrstuvwxyz"[key - 97] + name.name += char + + def run_game() -> None: """ Start with all necessary plugins and system to run the game. @@ -1452,4 +1593,5 @@ def run_game() -> None: .before(GraphicsSystems), Systems(victory).run_if(level_is_finished, in_game), Systems(lose).run_if(level_is_lost), + Systems(get_player_name).run_if(game_is_over), ).run_main()