Listen for clicks, detect which display was clicked

This commit is contained in:
Yohann D'ANELLO 2020-12-11 16:56:22 +01:00
parent 53cb6a89ae
commit bbe37eab97
4 changed files with 45 additions and 8 deletions

View File

@ -2,7 +2,8 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import curses import curses
from squirrelbattle.display.display import VerticalSplit, HorizontalSplit from squirrelbattle.display.display import VerticalSplit, HorizontalSplit, \
Display
from squirrelbattle.display.mapdisplay import MapDisplay from squirrelbattle.display.mapdisplay import MapDisplay
from squirrelbattle.display.messagedisplay import MessageDisplay from squirrelbattle.display.messagedisplay import MessageDisplay
from squirrelbattle.display.statsdisplay import StatsDisplay from squirrelbattle.display.statsdisplay import StatsDisplay
@ -10,7 +11,7 @@ from squirrelbattle.display.menudisplay import MainMenuDisplay, \
InventoryDisplay, SettingsMenuDisplay InventoryDisplay, SettingsMenuDisplay
from squirrelbattle.display.logsdisplay import LogsDisplay from squirrelbattle.display.logsdisplay import LogsDisplay
from squirrelbattle.display.texturepack import TexturePack from squirrelbattle.display.texturepack import TexturePack
from typing import Any from typing import Any, List
from squirrelbattle.game import Game, GameMode from squirrelbattle.game import Game, GameMode
from squirrelbattle.enums import DisplayActions from squirrelbattle.enums import DisplayActions
@ -36,11 +37,13 @@ class DisplayManager:
self.logsdisplay, self.messagedisplay] self.logsdisplay, self.messagedisplay]
self.update_game_components() self.update_game_components()
def handle_display_action(self, action: DisplayActions) -> None: def handle_display_action(self, action: DisplayActions, *params) -> None:
if action == DisplayActions.REFRESH: if action == DisplayActions.REFRESH:
self.refresh() self.refresh()
elif action == DisplayActions.UPDATE: elif action == DisplayActions.UPDATE:
self.update_game_components() self.update_game_components()
elif action == DisplayActions.MOUSE:
self.handle_mouse_click(*params)
def update_game_components(self) -> None: def update_game_components(self) -> None:
for d in self.displays: for d in self.displays:
@ -52,7 +55,20 @@ class DisplayManager:
self.logsdisplay.update_logs(self.game.logs) self.logsdisplay.update_logs(self.game.logs)
self.messagedisplay.update_message(self.game.message) self.messagedisplay.update_message(self.game.message)
def refresh(self) -> None: def handle_mouse_click(self, y: int, x: int) -> None:
displays = self.refresh()
display = None
for d in displays:
top_y, top_x, height, width = d.y, d.x, d.height, d.width
if top_y <= y < top_y + height and top_x <= x < top_x + width:
# The click coordinates correspond to the coordinates
# of that display
display = d
raise Exception(f"click at ({y}, {x})", display)
def refresh(self) -> List[Display]:
displays = []
if self.game.state == GameMode.PLAY \ if self.game.state == GameMode.PLAY \
or self.game.state == GameMode.INVENTORY: or self.game.state == GameMode.INVENTORY:
# The map pad has already the good size # The map pad has already the good size
@ -67,15 +83,22 @@ class DisplayManager:
self.rows // 5 - 1, self.cols * 4 // 5) self.rows // 5 - 1, self.cols * 4 // 5)
self.hbar.refresh(self.rows * 4 // 5, 0, 1, self.cols * 4 // 5) self.hbar.refresh(self.rows * 4 // 5, 0, 1, self.cols * 4 // 5)
self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1) self.vbar.refresh(0, self.cols * 4 // 5, self.rows, 1)
displays += [self.mapdisplay, self.statsdisplay, self.logsdisplay,
self.hbar, self.vbar]
if self.game.state == GameMode.INVENTORY: if self.game.state == GameMode.INVENTORY:
self.inventorydisplay.refresh(self.rows // 10, self.inventorydisplay.refresh(self.rows // 10,
self.cols // 2, self.cols // 2,
8 * self.rows // 10, 8 * self.rows // 10,
2 * self.cols // 5) 2 * self.cols // 5)
displays.append(self.inventorydisplay)
elif self.game.state == GameMode.MAINMENU: elif self.game.state == GameMode.MAINMENU:
self.mainmenudisplay.refresh(0, 0, self.rows, self.cols) self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
displays.append(self.mainmenudisplay)
elif self.game.state == GameMode.SETTINGS: elif self.game.state == GameMode.SETTINGS:
self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols) self.settingsmenudisplay.refresh(0, 0, self.rows, self.cols)
displays.append(self.settingsmenudisplay)
if self.game.message: if self.game.message:
height, width = 0, 0 height, width = 0, 0
@ -84,9 +107,12 @@ class DisplayManager:
width = max(width, len(line)) width = max(width, len(line))
y, x = (self.rows - height) // 2, (self.cols - width) // 2 y, x = (self.rows - height) // 2, (self.cols - width) // 2
self.messagedisplay.refresh(y, x, height, width) self.messagedisplay.refresh(y, x, height, width)
displays.append(self.messagedisplay)
self.resize_window() self.resize_window()
return displays
def resize_window(self) -> bool: def resize_window(self) -> bool:
""" """
If the window got resized, ensure that the screen size got updated. If the window got resized, ensure that the screen size got updated.

View File

@ -16,6 +16,7 @@ class DisplayActions(Enum):
""" """
REFRESH = auto() REFRESH = auto()
UPDATE = auto() UPDATE = auto()
MOUSE = auto()
class GameMode(Enum): class GameMode(Enum):
@ -32,6 +33,7 @@ class KeyValues(Enum):
""" """
Key values options used in the game Key values options used in the game
""" """
MOUSE = auto()
UP = auto() UP = auto()
DOWN = auto() DOWN = auto()
LEFT = auto() LEFT = auto()
@ -48,7 +50,9 @@ class KeyValues(Enum):
""" """
Translate the raw string key into an enum value that we can use. Translate the raw string key into an enum value that we can use.
""" """
if key in (settings.KEY_DOWN_SECONDARY, if key == "KEY_MOUSE":
return KeyValues.MOUSE
elif key in (settings.KEY_DOWN_SECONDARY,
settings.KEY_DOWN_PRIMARY): settings.KEY_DOWN_PRIMARY):
return KeyValues.DOWN return KeyValues.DOWN
elif key in (settings.KEY_LEFT_PRIMARY, elif key in (settings.KEY_LEFT_PRIMARY,

View File

@ -4,6 +4,7 @@
from json import JSONDecodeError from json import JSONDecodeError
from random import randint from random import randint
from typing import Any, Optional from typing import Any, Optional
import curses
import json import json
import os import os
import sys import sys
@ -15,7 +16,6 @@ from .resources import ResourceManager
from .settings import Settings from .settings import Settings
from . import menus from . import menus
from .translations import gettext as _, Translator from .translations import gettext as _, Translator
from typing import Callable
class Game: class Game:
@ -25,7 +25,7 @@ class Game:
map: Map map: Map
player: Player player: Player
# display_actions is a display interface set by the bootstrapper # display_actions is a display interface set by the bootstrapper
display_actions: Callable[[DisplayActions], None] display_actions: callable
def __init__(self) -> None: def __init__(self) -> None:
""" """
@ -82,6 +82,11 @@ class Game:
self.display_actions(DisplayActions.REFRESH) self.display_actions(DisplayActions.REFRESH)
return return
if key == KeyValues.MOUSE:
_ignored1, x, y, _ignored2, _ignored3 = curses.getmouse()
self.display_actions(DisplayActions.MOUSE, y, x)
return
if self.state == GameMode.PLAY: if self.state == GameMode.PLAY:
self.handle_key_pressed_play(key) self.handle_key_pressed_play(key)
elif self.state == GameMode.INVENTORY: elif self.state == GameMode.INVENTORY:

View File

@ -20,6 +20,8 @@ class TermManager: # pragma: no cover
curses.cbreak() curses.cbreak()
# make cursor invisible # make cursor invisible
curses.curs_set(False) curses.curs_set(False)
# Catch mouse events
curses.mousemask(True)
# Enable colors # Enable colors
curses.start_color() curses.start_color()