diff --git a/input_handlers.py b/input_handlers.py index 11db90b..99e1a10 100644 --- a/input_handlers.py +++ b/input_handlers.py @@ -56,6 +56,11 @@ WAIT_KEYS = { tcod.event.K_CLEAR, } +CONFIRM_KEYS = { + tcod.event.K_RETURN, + tcod.event.K_KP_ENTER, +} + class EventHandler(tcod.event.EventDispatch[Action]): def __init__(self, engine: Engine): @@ -225,6 +230,70 @@ class InventoryDropHandler(InventoryEventHandler): return actions.DropItem(self.engine.player, item) +class SelectIndexHandler(AskUserEventHandler): + """Handles asking the user for an index on the map.""" + + def __init__(self, engine: Engine): + """Sets the cursor to the player when this handler is constructed.""" + super().__init__(engine) + player = self.engine.player + engine.mouse_location = player.x, player.y + + def on_render(self, console: tcod.Console) -> None: + """Highlight the tile under the cursor.""" + super().on_render(console) + x, y = self.engine.mouse_location + console.tiles_rgb["bg"][x, y] = color.white + console.tiles_rgb["fg"][x, y] = color.black + + def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]: + """Check for key movement or confirmation keys.""" + key = event.sym + if key in MOVE_KEYS: + modifier = 1 # Holding modifier keys will speed up key movement + if event.mod & (tcod.event.KMOD_LSHIFT | tcod.event.KMOD_RSHIFT): + modifier *= 5 + if event.mod & (tcod.event.KMOD_LCTRL | tcod.event.KMOD_RCTRL): + modifier *= 10 + if event.mod & (tcod.event.KMOD_LALT | tcod.event.KMOD_RALT): + modifier *= 20 + + x, y = self.engine.mouse_location + dx, dy = MOVE_KEYS[key] + x += dx * modifier + y += dy * modifier + # Clamp the cursor index to the map size. + x = max(0, min(x, self.engine.game_map.width - 1)) + y = max(0, min(y, self.engine.game_map.height - 1)) + self.engine.mouse_location = x, y + + return None + elif key in CONFIRM_KEYS: + return self.on_index_selected(*self.engine.mouse_location) + + return super().ev_keydown(event) + + def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown) -> Optional[Action]: + """Left click confirms a selection.""" + if self.engine.game_map.in_bounds(*event.tile): + if event.button == 1: + return self.on_index_selected(*event.tile) + + return super().ev_mousebuttondown(event) + + @overload + def on_index_selected(self, x: int, y: int) -> Optional[Action]: + """Called when an index is selected.""" + + +class LookHandler(SelectIndexHandler): + """Lets the player look around using the keyboard.""" + + def on_index_selected(self, x: int, y: int) -> None: + """Return to main handler.""" + self.engine.event_handler = MainGameEventHandler(self.engine) + + class MainGameEventHandler(EventHandler): def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]: action: Optional[Action] = None @@ -252,6 +321,8 @@ class MainGameEventHandler(EventHandler): self.engine.event_handler = InventoryActivateHandler(self.engine) elif key == tcod.event.K_d: self.engine.event_handler = InventoryDropHandler(self.engine) + elif key == tcod.event.K_SLASH: + self.engine.event_handler = LookHandler(self.engine) # No valid key was pressed return action