diff --git a/actions.py b/actions.py index 8fbce9d..9e79fd1 100644 --- a/actions.py +++ b/actions.py @@ -1,9 +1,27 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from engine import Engine + from entity import Entity + class Action: - pass + def perform(self, engine: Engine, entity: Entity) -> None: + """Perform this action with the objects needed to determine its scope. + + `engine` is the scope this action is being performed in. + + `entity` is the object performing the action. + + This method must be overwritten by Action subclasses. + """ + raise NotImplementedError() class EscapeAction(Action): - pass + def perform(self, engine: Engine, entity: Entity) -> None: + raise SystemExit() class MovementAction(Action): @@ -12,3 +30,14 @@ class MovementAction(Action): self.dx = dx self.dy = dy + + def perform(self, engine: Engine, entity: Entity) -> None: + dest_x = entity.x + self.dx + dest_y = entity.y + self.dy + + if not engine.game_map.in_bounds(dest_x, dest_y): + return # Destination is out of bounds + if not engine.game_map.tiles["walkable"][dest_x, dest_y]: + return # Destination is blocked by a tile. + + entity.move(self.dx, self.dy); diff --git a/engine.py b/engine.py index 9d6f9fa..d93383d 100644 --- a/engine.py +++ b/engine.py @@ -3,15 +3,22 @@ from typing import Set, Iterable, Any from tcod.context import Context from tcod.console import Console -from actions import EscapeAction, MovementAction from entity import Entity +from game_map import GameMap from input_handlers import EventHandler class Engine: - def __init__(self, entities: Set[Entity], event_handler: EventHandler, player: Entity): + def __init__( + self, + entities: Set[Entity], + event_handler: EventHandler, + game_map: GameMap, + player: Entity + ): self.entities = entities self.event_handler = event_handler + self.game_map = game_map self.player = player def handle_events(self, events: Iterable[Any]) -> None: @@ -21,12 +28,11 @@ class Engine: if action is None: continue - if isinstance(action, MovementAction): - self.player.move(dx=action.dx, dy=action.dy) - elif isinstance(action, EscapeAction): - raise SystemExit() + action.perform(self, self.player) def render(self, console: Console, context: Context) -> None: + self.game_map.render(console) + for entity in self.entities: console.print(entity.x, entity.y, entity.char, fg=entity.color) diff --git a/main.py b/main.py index e7a4b24..2d298d0 100755 --- a/main.py +++ b/main.py @@ -3,6 +3,7 @@ import tcod from engine import Engine from entity import Entity +from game_map import GameMap from input_handlers import EventHandler @@ -10,6 +11,9 @@ def main() -> None: screen_width = 80 screen_height = 50 + map_width = 80 + map_height = 50 + tileset = tcod.tileset.load_tilesheet( "dejavu10x10_gs_tc.png", 32, @@ -23,7 +27,9 @@ def main() -> None: npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), "@", (255, 255, 0)) entities = {npc, player} - engine = Engine(entities, event_handler, player) + game_map = GameMap(map_width, map_height) + + engine = Engine(entities, event_handler, game_map, player) with tcod.context.new_terminal( screen_width,