diff --git a/erynrl/engine.py b/erynrl/engine.py index e4108b9..5daa295 100644 --- a/erynrl/engine.py +++ b/erynrl/engine.py @@ -4,7 +4,7 @@ import random from dataclasses import dataclass -from typing import TYPE_CHECKING, MutableSet, NoReturn +from typing import TYPE_CHECKING, MutableSet, NoReturn, Optional import tcod @@ -58,6 +58,7 @@ class Engine: self.message_log = MessageLog() self.event_handler: 'EventHandler' = MainGameEventHandler(self) + self.current_mouse_point: Optional[Point] = None self.hero = Hero(position=self.map.generator.rooms[0].center) self.entities: MutableSet[Entity] = {self.hero} @@ -104,12 +105,20 @@ class Engine: messages_rect = Rect(Point(x=27, y=45), Size(width=40, height=5)) self.message_log.render_to_console(console, messages_rect) + entities_at_mouse_position = [] for ent in sorted(self.entities, key=lambda e: e.render_order.value): - # Only print entities that are in the field of view + # Only process entities that are in the field of view if not self.map.visible[tuple(ent.position)]: continue + ent.print_to_console(console) + if ent.position == self.current_mouse_point: + entities_at_mouse_position.append(ent) + + if len(entities_at_mouse_position) > 0: + console.print(x=1, y=43, string=', '.join(e.name for e in entities_at_mouse_position)) + def run_event_loop(self, context: tcod.context.Context, console: tcod.Console) -> NoReturn: '''Run the event loop forever. This method never returns.''' while True: @@ -118,7 +127,7 @@ class Engine: context.present(console) self.begin_turn() - self.event_handler.wait_for_events() + self.event_handler.handle_events(context) self.finish_turn() def process_input_action(self, action: Action) -> ActionResult: @@ -240,12 +249,10 @@ class Engine: def kill_actor(self, actor: Actor) -> None: '''Kill an entity. Remove it from the game.''' - if actor == self.hero: # When the hero dies, the game is over. - # TODO: Transition to game over state - log.ACTIONS.debug('Time to die.') + log.ACTIONS.info('Time to die.') self.event_handler = GameOverEventHandler(self) else: - log.ACTIONS.debug('%s dies', actor) + log.ACTIONS.info('%s dies', actor) self.entities.remove(actor) diff --git a/erynrl/events.py b/erynrl/events.py index bb1ee7f..0c736b3 100644 --- a/erynrl/events.py +++ b/erynrl/events.py @@ -8,7 +8,7 @@ import tcod from . import log from .actions import Action, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction -from .geometry import Direction +from .geometry import Direction, Point if TYPE_CHECKING: from .engine import Engine @@ -20,9 +20,10 @@ class EventHandler(tcod.event.EventDispatch[Action]): super().__init__() self.engine = engine - def wait_for_events(self): + def handle_events(self, context: tcod.context.Context): '''Wait for events and handle them.''' for event in tcod.event.wait(): + context.convert_event(event) self.handle_event(event) def handle_event(self, event: tcod.event.Event) -> None: @@ -87,6 +88,12 @@ class MainGameEventHandler(EventHandler): return action + def ev_mousemotion(self, event: tcod.event.MouseMotion) -> Optional[Action]: + mouse_point = Point(event.tile.x, event.tile.y) + if not self.engine.map.tile_is_in_bounds(mouse_point): + mouse_point = None + self.engine.current_mouse_point = mouse_point + class GameOverEventHandler(EventHandler): '''When the game is over (the hero dies, the player quits, etc), this event handler takes over.''' diff --git a/erynrl/map.py b/erynrl/map.py index 33b3bbd..18f65f8 100644 --- a/erynrl/map.py +++ b/erynrl/map.py @@ -25,6 +25,7 @@ class Map: @property def rooms(self) -> List['Room']: + '''The list of rooms in the map''' return self.generator.rooms def random_walkable_position(self) -> Point: @@ -35,9 +36,11 @@ class Map: return random_position_in_room def tile_is_in_bounds(self, point: Point) -> bool: + '''Return True if the given point is inside the bounds of the map''' return 0 <= point.x < self.size.width and 0 <= point.y < self.size.height def tile_is_walkable(self, point: Point) -> bool: + '''Return True if the tile at the given point is walkable''' return self.tiles[point.x, point.y]['walkable'] def print_to_console(self, console: tcod.Console) -> None: