Show Entity under mouse cursor in a line above the hit points

This commit is contained in:
Eryn Wells 2022-05-15 16:50:24 -07:00
parent 4e585a2650
commit d4e4684694
3 changed files with 26 additions and 9 deletions

View file

@ -4,7 +4,7 @@
import random import random
from dataclasses import dataclass from dataclasses import dataclass
from typing import TYPE_CHECKING, MutableSet, NoReturn from typing import TYPE_CHECKING, MutableSet, NoReturn, Optional
import tcod import tcod
@ -58,6 +58,7 @@ class Engine:
self.message_log = MessageLog() self.message_log = MessageLog()
self.event_handler: 'EventHandler' = MainGameEventHandler(self) self.event_handler: 'EventHandler' = MainGameEventHandler(self)
self.current_mouse_point: Optional[Point] = None
self.hero = Hero(position=self.map.generator.rooms[0].center) self.hero = Hero(position=self.map.generator.rooms[0].center)
self.entities: MutableSet[Entity] = {self.hero} 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)) messages_rect = Rect(Point(x=27, y=45), Size(width=40, height=5))
self.message_log.render_to_console(console, messages_rect) 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): 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)]: if not self.map.visible[tuple(ent.position)]:
continue continue
ent.print_to_console(console) 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: def run_event_loop(self, context: tcod.context.Context, console: tcod.Console) -> NoReturn:
'''Run the event loop forever. This method never returns.''' '''Run the event loop forever. This method never returns.'''
while True: while True:
@ -118,7 +127,7 @@ class Engine:
context.present(console) context.present(console)
self.begin_turn() self.begin_turn()
self.event_handler.wait_for_events() self.event_handler.handle_events(context)
self.finish_turn() self.finish_turn()
def process_input_action(self, action: Action) -> ActionResult: def process_input_action(self, action: Action) -> ActionResult:
@ -240,12 +249,10 @@ class Engine:
def kill_actor(self, actor: Actor) -> None: def kill_actor(self, actor: Actor) -> None:
'''Kill an entity. Remove it from the game.''' '''Kill an entity. Remove it from the game.'''
if actor == self.hero: if actor == self.hero:
# When the hero dies, the game is over. # When the hero dies, the game is over.
# TODO: Transition to game over state log.ACTIONS.info('Time to die.')
log.ACTIONS.debug('Time to die.')
self.event_handler = GameOverEventHandler(self) self.event_handler = GameOverEventHandler(self)
else: else:
log.ACTIONS.debug('%s dies', actor) log.ACTIONS.info('%s dies', actor)
self.entities.remove(actor) self.entities.remove(actor)

View file

@ -8,7 +8,7 @@ import tcod
from . import log from . import log
from .actions import Action, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction from .actions import Action, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction
from .geometry import Direction from .geometry import Direction, Point
if TYPE_CHECKING: if TYPE_CHECKING:
from .engine import Engine from .engine import Engine
@ -20,9 +20,10 @@ class EventHandler(tcod.event.EventDispatch[Action]):
super().__init__() super().__init__()
self.engine = engine self.engine = engine
def wait_for_events(self): def handle_events(self, context: tcod.context.Context):
'''Wait for events and handle them.''' '''Wait for events and handle them.'''
for event in tcod.event.wait(): for event in tcod.event.wait():
context.convert_event(event)
self.handle_event(event) self.handle_event(event)
def handle_event(self, event: tcod.event.Event) -> None: def handle_event(self, event: tcod.event.Event) -> None:
@ -87,6 +88,12 @@ class MainGameEventHandler(EventHandler):
return action 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): class GameOverEventHandler(EventHandler):
'''When the game is over (the hero dies, the player quits, etc), this event handler takes over.''' '''When the game is over (the hero dies, the player quits, etc), this event handler takes over.'''

View file

@ -25,6 +25,7 @@ class Map:
@property @property
def rooms(self) -> List['Room']: def rooms(self) -> List['Room']:
'''The list of rooms in the map'''
return self.generator.rooms return self.generator.rooms
def random_walkable_position(self) -> Point: def random_walkable_position(self) -> Point:
@ -35,9 +36,11 @@ class Map:
return random_position_in_room return random_position_in_room
def tile_is_in_bounds(self, point: Point) -> bool: 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 return 0 <= point.x < self.size.width and 0 <= point.y < self.size.height
def tile_is_walkable(self, point: Point) -> bool: 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'] return self.tiles[point.x, point.y]['walkable']
def print_to_console(self, console: tcod.Console) -> None: def print_to_console(self, console: tcod.Console) -> None: