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
)
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()
) -> 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)
GraphicsSystems = SystemSet("graphics-systems")
+InputsSystems = SystemSet("inputs-systems")
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),
)
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
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):
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(
AnimationSet,
Pacman,
ShouldRender,
- TargetTile,
InMotion,
MoveSpeed,
+ TilePos,
],
(
Coord2D(0, 0, -10),
]
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()