]> Untitled Git - axy/ft/pacman.git/commitdiff
Cheat mod added, game over in progress
authorThomas Rimelen <trimelen@k1r1p9.42mulhouse.fr>
Tue, 20 Oct 2026 14:04:03 +0000 (16:04 +0200)
committerThomas Rimelen <trimelen@k1r1p9.42mulhouse.fr>
Tue, 20 Oct 2026 14:04:03 +0000 (16:04 +0200)
config.json
src/pacman/game/__init__.py

index 0967ef424bce6791893e9a57bb952f80fd536e93..2314f002783bc02c5940e8f8392075fbd7908a4e 100644 (file)
@@ -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"
+}
index 6bc30671b44fe159b8eec932563f3d1d10d80940..6e7b078685f6638fe3104dff79f1fb8175cc7f0d 100644 (file)
@@ -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()