]> Untitled Git - axy/ft/pacman.git/commitdiff
Menus and fixed dumb issue with python range usage in archetypes
author= <=>
Mon, 12 Oct 2026 13:35:14 +0000 (15:35 +0200)
committer= <=>
Mon, 12 Oct 2026 13:35:14 +0000 (15:35 +0200)
src/pacman/ecs/gui.py
src/pacman/ecs/world.py
src/pacman/game/__init__.py

index 5bd5aeb7ae08f192e557dc1fb1c9be0ca25b6617..b5b38845d2ec3036af477a899e3e62a5522e915b 100644 (file)
@@ -4,10 +4,14 @@ from enum import Enum, auto
 from typing import override
 
 import pygame
-from pygame import Color
+from pygame import Color, Vector2
 
 from pacman.ecs.assets import Asset
-from pacman.ecs.coord import CoordAbs2D, PropagateTransform
+from pacman.ecs.coord import (
+    CoordAbs2D,
+    CoordBundle,
+    PropagateTransform,
+)
 from pacman.ecs.graphics import (
     AnimationSet,
     GraphicsSystems,
@@ -41,6 +45,14 @@ class Font(Asset, Component):
         path, size = path.split(":")
         return Font(pygame.font.Font(path, int(size)))
 
+    def center_text_for(self, text: str, dims: Vector2) -> CoordBundle:
+        width, _ = self.font.size(text)
+        height = self.font.get_ascent() + self.font.get_descent()
+        return CoordBundle(
+            (dims.x - width) / 2,
+            (dims.y - height) / 2 + self.font.get_descent(),
+        )
+
 
 @dataclass
 class TextDisplay(Component):
index 2dc675799402c6893844e22608bbfce7865dca9a..ce049c7192dab7cf4e9b7d88bdd21982c6b7501f 100644 (file)
@@ -151,7 +151,9 @@ class Archetype:
                 return kv[ty]
             return map(self._components[ty].__getitem__, positions)
 
-        itr = range(len(dst._entities) - len(components), len(dst._entities))
+        itr = lambda: range(
+            len(dst._entities) - len(components), len(dst._entities)
+        )
         dst._extend(cb)
         self._discard(positions)
 
@@ -159,12 +161,12 @@ class Archetype:
             for k, lst in moved_comps:
                 hooks = self._world._components_cache[k][1]
                 hooks._remove(
-                    zip((dst._entities[i] for i in itr), lst, strict=True)
+                    zip((dst._entities[i] for i in itr()), lst, strict=True)
                 )
             for k in comps_ty:
                 lst = dst._components[k]
                 hooks = self._world._components_cache[k][1]
-                hooks._insert((dst._entities[i], lst[i]) for i in itr)
+                hooks._insert((dst._entities[i], lst[i]) for i in itr())
 
         return res
 
index 662c46c6da49b0cef14d9fb31509bb7f931ca9ec..1e364d75f7d8203aac72a41e651848cf068222d2 100644 (file)
@@ -32,7 +32,7 @@ from pacman.ecs.gui import (
     SelectedButton,
     TextDisplay,
 )
-from pacman.ecs.hierarchy import ChildOf, Hierarchy
+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.world import (
@@ -42,8 +42,10 @@ from pacman.ecs.world import (
     Not,
     Query,
     Resource,
+    System,
     Systems,
     World,
+    WorldShouldExit,
 )
 
 _DIR_OFFSETS = [(0, -1), (1, 0), (0, 1), (-1, 0)]
@@ -782,21 +784,52 @@ def print_timer(state: GameState, config: Config) -> str:
     return f"{time // 60}"
 
 
-def print_a() -> None:
-    print("a")
+def start_game() -> None:
+    print("Game started")
 
 
-def print_b() -> None:
-    print("b")
+def quit_game(world: World) -> None:
+    world.spawn_resource(WorldShouldExit())
 
 
-def print_c() -> None:
-    print("c")
+def spawn_button(
+    world: World, fonts: Assets[Font], sprites: Assets[Sprite2D]
+) -> Callable[[Vector2, str, System], Entity]:
+    def inner(pos: Vector2, s: str, cb: System) -> Entity:
+        parent = world.spawn(
+            tuple[CoordBundle, ShouldRender, AnimationSet, Button],
+            (
+                CoordBundle(*pos.xy, depth=-100),
+                ShouldRender(),
+                AnimationSet(
+                    [
+                        [sprites.load("./asset/gui/button_unselected.png")],
+                        [sprites.load("./asset/gui/button_selected.png")],
+                        [sprites.load("./asset/gui/button_selected.png")],
+                    ],
+                    1,
+                ),
+                Button(cb),
+            ),
+        )
+        font = fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30")
+        world.spawn(
+            tuple[CoordBundle, ShouldRender, TextDisplay, ChildOf],
+            (
+                font.center_text_for(s, Vector2(300, 80)),
+                ShouldRender(),
+                TextDisplay(s, font),
+                ChildOf(parent),
+            ),
+        )
+        return parent
+
+    return inner
 
 
 def setup_text(world: World, fonts: Assets[Font]) -> None:
-    spawned = world.spawn_many(
-        tuple[CoordBundle, ShouldRender, ComputedText, TextDisplay, Button],
+    world.spawn_many(
+        tuple[CoordBundle, ShouldRender, ComputedText, TextDisplay],
         [
             (
                 CoordBundle(depth=-20),
@@ -806,7 +839,6 @@ def setup_text(world: World, fonts: Assets[Font]) -> None:
                     "",
                     fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30"),
                 ),
-                Button(print_a),
             ),
             (
                 CoordBundle(y=100, depth=-20),
@@ -816,7 +848,6 @@ def setup_text(world: World, fonts: Assets[Font]) -> None:
                     "",
                     fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30"),
                 ),
-                Button(print_b),
             ),
             (
                 CoordBundle(y=200, depth=-20),
@@ -826,11 +857,25 @@ def setup_text(world: World, fonts: Assets[Font]) -> None:
                     "",
                     fonts.load("./asset/fonts/JetBrainsMonoNL-Regular.ttf:30"),
                 ),
-                Button(print_c),
             ),
         ],
     )
-    world.spawn_resource(SelectedButton(spawned[0]))
+
+    selected = world.run_system(
+        spawn_button,
+        Vector2((1600 - 300) / 2, (1200 - 200) / 2),
+        "Start game",
+        start_game,
+    )
+
+    world.run_system(
+        spawn_button,
+        Vector2((1600 - 300) / 2, (1200 - 200) / 2 + 120),
+        "Quit",
+        quit_game,
+    )
+
+    world.spawn_resource(SelectedButton(selected))
 
 
 def run_game() -> None: