+import pacman
from collections.abc import Callable
from dataclasses import dataclass
from enum import Enum, auto
from mazegenerator import MazeGenerator # type: ignore[import-untyped]
from pydantic import BaseModel
-from pygame import Vector2
+from pygame import Vector2, K_ESCAPE
from pygame.math import clamp
from pacman.ecs import minimal_plugins
Sprite2D,
WindowPositionned,
graphics_plugins,
+ WindowEvents,
+ key_just_pressed,
+ InputsSystems,
+ StopAnimation,
)
from pacman.ecs.gui import (
Button,
)
from pacman.ecs.hierarchy import ChildOf, Children, Hierarchy
from pacman.ecs.schedule import StartupSchedule, UpdateSchedule
-from pacman.ecs.update import PostUpdate, Update
+from pacman.ecs.update import PostUpdate, Update, PreUpdate
from pacman.ecs.world import (
CommandQueue,
Component,
world.run_raw_system(sys)
-def in_game(itr: Query[Maze]) -> bool:
- return len(list(itr)) != 0
+def maze_exists(itr: Query[Maze]) -> bool:
+ return next(itr.__iter__(), None) is not None
+
+
+def in_game(world: World) -> bool:
+ return world.run_raw_system(maze_exists) and not world.run_raw_system(
+ in_game_menu
+ )
def level_is_finished(
return inner
+def back_to_main_menu(
+ world: World,
+ hierarchy: Hierarchy[tuple[()]],
+ mazes: Query[Entity, Maze],
+ gui: Query[Entity, GameGui],
+ queue: CommandQueue,
+) -> None:
+ 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))
+ world.run_raw_system(setup_main_menu)
+
+
+def in_game_menu(menus: Query[GameMenu]) -> bool:
+ return next(menus.__iter__(), None) is not None
+
+
+def toggle_game_menu(world: World) -> None:
+ if world.run_raw_system(in_game_menu):
+ world.run_raw_system(close_game_menu)
+ else:
+ world.run_raw_system(setup_game_menu)
+
+
+def close_game_menu(
+ world: World,
+ hierarchy: Hierarchy[tuple[()]],
+ menus: Query[Entity, GameMenu],
+ animated: Query[Entity, Pacman | Ghost],
+) -> None:
+ world.remove_many(StopAnimation, list(animated))
+ for menu in menus:
+ hierarchy.despawn_with_children(menu)(world)
+ world.despawn_resource(SelectedButton)
+
+
+def setup_game_menu(
+ world: World, animated: Query[Entity, Pacman | Ghost]
+) -> None:
+ world.insert_many(StopAnimation, [(e, StopAnimation()) for e in animated])
+ selected = world.run_system(
+ spawn_button,
+ WindowPositionned(Vector2(0.5), Vector2(-150, -150)),
+ "Resume",
+ close_game_menu,
+ )
+
+ cheat_button = world.run_system(
+ spawn_button,
+ WindowPositionned(Vector2(0.5), Vector2(-150, -40)),
+ "Cheat mod",
+ quit_game,
+ )
+
+ quit_button = world.run_system(
+ spawn_button,
+ WindowPositionned(Vector2(0.5), Vector2(-150, 70)),
+ "Back to menu",
+ back_to_main_menu,
+ )
+
+ world.spawn(
+ tuple[GameMenu, Children, CoordBundle],
+ (
+ GameMenu(),
+ Children((selected, cheat_button, quit_button)),
+ CoordBundle(),
+ ),
+ )
+
+ world.spawn_resource(SelectedButton(selected))
+
+
def setup_main_menu(world: World) -> None:
selected = world.run_system(
spawn_button,
.chain()
.run_if(initial_pause_done, in_game)
.in_set(Update),
+ Systems(toggle_game_menu)
+ .run_if(key_just_pressed(K_ESCAPE), maze_exists)
+ .in_set(PreUpdate)
+ .after(InputsSystems),
Systems(update_pacman_anim, update_ghost_anim)
.before(GraphicsSystems)
.in_set(PostUpdate),