]> Untitled Git - axy/ft/pacman.git/commitdiff
proper pacman movement added
authorThomas Rimelen <trimelen@k1r2p12.42mulhouse.fr>
Wed, 30 Sep 2026 14:38:01 +0000 (16:38 +0200)
committerThomas Rimelen <trimelen@k1r2p12.42mulhouse.fr>
Wed, 30 Sep 2026 14:38:01 +0000 (16:38 +0200)
src/pacman/ecs/graphics.py
src/pacman/game/__init__.py

index dcc587128d159c5c9bc2c95577c940462401f675..1ea9c9e439838df38c35d4e67c522e79483811a3 100644 (file)
@@ -41,9 +41,11 @@ class WindowEvents(Resource):
             if e.type == pygame.MOUSEBUTTONDOWN
         )
 
-    def keys(self) -> Iterator[int]:
+    def keys_itr(self) -> Iterator[tuple[int, bool]]:
         return (
-            cast(int, (e.key)) for e in self.events if e.type == pygame.KEYDOWN
+            (cast(int, (e.key)), e.type == pygame.KEYDOWN)
+            for e in self.events
+            if e.type == pygame.KEYDOWN or e.type == pygame.KEYUP
         )
 
 
@@ -66,6 +68,9 @@ class Sprite2D(Component, Asset):
         del ty
         return Sprite2D(pygame.image.load(path))
 
+    def copy(self) -> "Sprite2D":
+        return Sprite2D(self.surface)
+
 
 def poll_events(events: WindowEvents) -> None:
     events.events = pygame.event.get()
@@ -118,7 +123,7 @@ def insert_animation_sprites(
 ) -> None:
     inserts = []
     for ent, anim in query:
-        inserts.append((ent, anim.curr_frame))
+        inserts.append((ent, anim.curr_frame.copy()))
     world.insert_many(Sprite2D, inserts)
 
 
@@ -131,6 +136,7 @@ def update_animations(
 
 
 GraphicsSystems = SystemSet("graphics-systems")
+InputsSystems = SystemSet("inputs-systems")
 
 
 def graphics_plugins(world: World) -> None:
@@ -143,5 +149,7 @@ def graphics_plugins(world: World) -> None:
         )
         .chain()
         .in_set(PostUpdate, GraphicsSystems),
-        Systems(poll_events, close_on_close).chain().in_set(PreUpdate),
+        Systems(poll_events, close_on_close)
+        .chain()
+        .in_set(PreUpdate, InputsSystems),
     )
index c5a8edfc8529f680638ed4961b2967a44d09f463..de33de8c0a30a01744a6900c6ed83fa0eff5cb95 100644 (file)
@@ -3,7 +3,7 @@ from dataclasses import dataclass
 from random import random
 
 from mazegenerator import MazeGenerator
-from pygame import Vector3
+from pygame import K_a, K_d, K_s, K_w, Vector3
 from pygame.math import clamp
 
 from pacman.ecs import minimal_plugins
@@ -11,14 +11,17 @@ from pacman.ecs.assets import Assets
 from pacman.ecs.coord import Coord2D, CoordAbs2D
 from pacman.ecs.graphics import (
     AnimationSet,
+    GraphicsSystems,
+    InputsSystems,
     ShouldRender,
     Sprite2D,
+    WindowEvents,
     graphics_plugins,
 )
 from pacman.ecs.hierarchy import ChildOf
 from pacman.ecs.schedule import StartupSchedule, UpdateSchedule
-from pacman.ecs.update import Update
-from pacman.ecs.world import Component, Entity, Query, Systems, World
+from pacman.ecs.update import PostUpdate, PreUpdate, Update
+from pacman.ecs.world import Component, Entity, Query, Resource, Systems, World
 
 
 class Maze(Component):
@@ -226,8 +229,24 @@ def move_to_target(
         motion.pos = nxt
 
 
+@dataclass
+class Inputs(Resource):
+    inputs: set[int]
+
+    def get_dir(self) -> int | None:
+        if K_w in self.inputs:
+            return 0
+        if K_d in self.inputs:
+            return 1
+        if K_s in self.inputs:
+            return 2
+        if K_a in self.inputs:
+            return 3
+
+
+@dataclass
 class Pacman(Component):
-    pass
+    current_direction: int
 
 
 def spawn_pacman(
@@ -244,9 +263,9 @@ def spawn_pacman(
             AnimationSet,
             Pacman,
             ShouldRender,
-            TargetTile,
             InMotion,
             MoveSpeed,
+            TilePos,
         ],
         (
             Coord2D(0, 0, -10),
@@ -261,26 +280,77 @@ def spawn_pacman(
                     ]
                     for direction in "URDL"
                 ],
-                4,
+                6,
             ),
-            Pacman(),
+            Pacman(1),
             ShouldRender(),
-            TargetTile(maze._cells[(14, 14)]),
             InMotion(maze._cells[(0, 0)], maze._cells[(0, 0)]),
-            MoveSpeed(4.0),
+            MoveSpeed(3.0),
+            TilePos(maze._cells[(0, 0)]),
         ),
     )
 
 
+def move_pacman(
+    pacman_q: Query[tuple[Pacman, Coord2D, InMotion, TilePos]],
+    inputs: Inputs,
+    cells: Query[tuple[Cell, Coord2D]],
+    maze_q: Query[Maze],
+) -> None:
+    maze = maze_q.single()
+    if maze is None:
+        return
+    for pacman, coord, motion, pos in pacman_q:
+        direction = inputs.get_dir()
+        cell, cell_pos = cells[pos.pos]
+        if coord.xy.distance_to(cell_pos.xy) < 12.0:
+            if direction is None:
+                direction = pacman.current_direction
+            if cell.walls()[direction]:
+                direction = pacman.current_direction
+            if not cell.walls()[direction]:
+                motion.src = pos.pos
+                motion.pos = maze._cells[cell.neighbor(direction)]
+                pacman.current_direction = direction
+        elif ((pacman.current_direction + 2) % 4) == direction:
+            tmp = motion.pos
+            motion.pos = motion.src
+            motion.src = tmp
+            pacman.current_direction = direction
+
+
+def update_pacman_anim(pacman_q: Query[tuple[Pacman, AnimationSet]]) -> None:
+    for pacman, anim in pacman_q:
+        anim.idx = pacman.current_direction
+
+
+def setup_resources(world: World) -> None:
+    world.spawn(Inputs, Inputs(set()))
+
+
+def update_inputs(inputs: Inputs, events: WindowEvents) -> None:
+    for key, state in events.keys_itr():
+        if state:
+            inputs.inputs.add(key)
+        else:
+            inputs.inputs.remove(key)
+
+
 def run_game() -> None:
     World().with_plugins(graphics_plugins, minimal_plugins).with_systems(
         StartupSchedule,
         Systems(
-            setup_maze, spawn_superpacgums, spawn_pacgums, spawn_pacman
+            setup_resources,
+            setup_maze,
+            spawn_superpacgums,
+            spawn_pacgums,
+            spawn_pacman,
         ).chain(),
     ).with_systems(
         UpdateSchedule,
-        Systems(move_in_motion, update_tile_pos, move_to_target)
+        Systems(move_pacman, move_in_motion, update_tile_pos, move_to_target)
         .chain()
         .in_set(Update),
+        Systems(update_inputs).in_set(PreUpdate).after(InputsSystems),
+        Systems(update_pacman_anim).before(GraphicsSystems).in_set(PostUpdate),
     ).run_main()