Mentions légales du service

Skip to content
Snippets Groups Projects
Commit e92aaccf authored by PEDERSEN Ny Aina's avatar PEDERSEN Ny Aina
Browse files

arcade: use payload to update the UI

- Remove super and call explicitly the parent.
  It is better for readability and to prevent bugs
  (Obj is calling a method in its init method)
- Add name to objects
parent 344ebab8
No related branches found
No related tags found
No related merge requests found
......@@ -76,6 +76,7 @@ class AbstractLevel(ABC):
expand_expr("exit_x", self.alias),
expand_expr("exit_y", self.alias),
char_rep="@",
name="exit",
)
self.map.add_exit(exit_obj)
for expr in [exit_obj.var_x, exit_obj.var_y]:
......@@ -95,8 +96,8 @@ class AbstractLevel(ABC):
self.event_list.connect(f"value_change:{variable}", wop.update)
# Create custom objects
for _, obj_dict in metadata_dict["objs"].items():
obj = Object(self.variables, **obj_dict)
for label, obj_dict in metadata_dict["objs"].items():
obj = Object(self.variables, **obj_dict, name=f"OBJ{label}")
self.map.add_object(obj)
variables_to_watch = (
list_variables(obj.var_x, self.alias)
......
......@@ -18,20 +18,12 @@ class LevelArcade(AbstractLevel):
map_dest = "map.tmx"
create_map(map_dest)
self.gui = ArcadeUI(map_dest)
# TODO add buttons
def update_map(self):
"""Update the GUI map."""
player_x = self.get_variable("player_x")
player_y = self.get_variable("player_y")
if player_x is not None and player_y is not None:
# TODO use player update hooks
payload = {
"topic": "player_update",
"coord_x": player_x,
"coord_y": player_y
}
self.gui.queue.send(payload)
# Connect the objects to the arcade UI
for object in self.map.nammed_objects.values():
object.set_ipc_hook_queue(self.gui.queue)
for object in self.map.unnammed_objects:
object.set_ipc_hook_queue(self.gui.queue)
def print_stdout(self) -> None:
"""Prints the inferior stdout."""
......@@ -67,7 +59,6 @@ class LevelArcade(AbstractLevel):
self.update_state()
# Show the map
self.update_map()
self.print_wowm_msg()
# Read a command and run it
......
......@@ -104,26 +104,25 @@ class Map:
return ascii_map
def add_object(self, obj: Object, name: Optional[str] = None) -> None:
def add_object(self, obj: Object) -> None:
"""
Add an object to the map.
:param obj: The object to add.
:param name: The obj's name.
"""
if name is None:
if obj.name is None:
self.unnammed_objects.add(obj)
else:
self.nammed_objects[name] = obj
self.nammed_objects[obj.name] = obj
def add_player(self, player: Player) -> None:
"""Add a player to the map."""
self.add_object(player, "player")
self.add_object(player)
self.player = player
def add_exit(self, exit_obj: Object) -> None:
"""Add an exit to the map."""
self.add_object(exit_obj, "exit")
self.add_object(exit_obj)
self.exit = exit_obj
def add_wop(self, wop: Wop) -> None:
......
......@@ -3,14 +3,14 @@
from typing import Any, Union, Optional
from level.variables import value
from level.arcade_utils.ipc import IpcQueue
# Default direction
_DIRECTION_DICT = {"up": 0, "down": 1, "left": 2, "right": 3}
# pylint: disable=too-many-instance-attributes too-many-arguments
# pylint: disable=too-few-public-methods fixme
# pylint: disable=too-many-instance-attributes too-many-arguments fixme
class Object:
"""Object class."""
......@@ -22,6 +22,7 @@ class Object:
var_dir: str = "3", # Default: right
char_rep: str = "o",
visibility_conditions: str = "True",
name: Optional[str] = None,
direction_dict: Optional[dict[str, Union[int, str]]] = None,
):
"""
......@@ -33,6 +34,7 @@ class Object:
:param var_dir: The variable that stores its direction.
:param char_rep: Its ascii character representation.
:param visibility_conditions: The python condition that determines its
:param name: The name/label of the WOP.
:param direction_dict: Dictionnary that maps string directions to integers.
visibility.
"""
......@@ -42,7 +44,9 @@ class Object:
self.var_dir = var_dir
self._char_rep = char_rep
self.visibility_conditions = visibility_conditions
self.name = name
self.dir_mapping = _DIRECTION_DICT if direction_dict is None else direction_dict
self.ipc_hook: Optional[IpcQueue] = None
# dynamic properties
self.coord_x: Union[int, None] = None
self.coord_y: Union[int, None] = None
......@@ -53,18 +57,21 @@ class Object:
def __repr__(self):
"""String representation."""
return (
f"Object({self.var_x = }, {self.var_y = }, {self.var_dir = }, "
f"{self.coord_x = }, {self.coord_y = }, {self.direction = }, "
f"{self.visibility_conditions = }, {self.visible = })"
)
def update(self, var: str, new_value: Union[int, None]) -> None:
attr = {
key: value for key, value in self.__dict__.items()
if key not in ['env', 'ipc_hook', 'dir_mapping']
}
return f"Object({attr})"
def update(
self, var: str, new_value: Union[int, None], run_hook: bool = True
) -> None:
"""
Update object property.
:param var: The variable that has been updated.
:param new_value: The updated value.
:param run_hook: Tells if the updates should be send to the ipc queue (if any).
"""
assert not var or self.env[var] == new_value
......@@ -84,6 +91,29 @@ class Object:
and self.var_dir is not None
)
if run_hook:
payload = {
"topic": "object_update",
"object_name": self.name,
"coord_x": self.coord_x,
"coord_y": self.coord_y,
"direction": self.direction,
}
self.send_update(payload)
def set_ipc_hook_queue(self, queue: Optional[IpcQueue] = None) -> None:
"""Set a IPC queue for post update hook."""
self.ipc_hook = queue
def send_update(self, payload: dict) -> None:
"""
Send update informations to hook functions.
The argument given to the hooks is a IPC payload (ref: ipc.py)
"""
if self.ipc_hook is not None:
self.ipc_hook.send(payload)
@property
def char_rep(self) -> str:
"""Get the character representation of the player."""
......@@ -93,6 +123,10 @@ class Object:
class Player(Object):
"""Player class."""
def __init__(self, *args, **kwargs):
kwargs["name"] = "player"
Object.__init__(self, *args, **kwargs)
@property
def char_rep(self) -> str:
"""Get the character representation of the player."""
......@@ -111,15 +145,18 @@ class Player(Object):
return ">"
return "?" # Unknown direction
def update(self, var: str, new_value: Union[int, None]) -> None:
def update(
self, var: str, new_value: Union[int, None], run_hook: bool = True
) -> None:
"""
Update object property.
:param var: The variable that has been updated.
:param new_value: The updated value.
:param run_hook: Tells if then hook (if existing) should be called on update.
"""
# Call the parent update
super().update(var, new_value)
Object.update(self, var, new_value, run_hook=False)
# Post-update hook that adds the player vars to the env.
if self.coord_x is not None:
......@@ -129,8 +166,16 @@ class Player(Object):
if self.direction is not None:
self.env["player_direction"] = self.direction
if run_hook:
payload = {
"topic": "player_update",
"coord_x": self.coord_x,
"coord_y": self.coord_y,
"direction": self.direction,
}
self.send_update(payload)
# TODO rename all occurences of WOWM to WOP
class Wop(Object):
"""Wise old person class."""
......@@ -167,7 +212,8 @@ class Wop(Object):
message_conditions = expand_condition(wop["message_conditions"])
# Object initialization
super().__init__(
Object.__init__(
self,
variables_env,
str(wop["x"]),
str(wop["y"]),
......@@ -184,18 +230,34 @@ class Wop(Object):
self.triggered = False
self.talks = False
def update(self, var: str, new_value: Union[int, None]) -> None:
def update(
self, var: str, new_value: Union[int, None], run_hook: bool = True
) -> None:
"""
Update object property.
:param var: The variable that has been updated.
:param new_value: The updated value.
:param run_hook: Tells if then hook (if existing) should be called on update.
"""
if self.triggered:
return # TODO handle non oneshot wop
# Call parent's update
super().update(var, new_value)
Object.update(self, var, new_value, run_hook=False)
# Post-update hook that updates the message condition
self.talks = self.visible and value(self.message_conditions, self.env)
if run_hook:
payload = {
"topic": "wop_update",
"object_name": self.name,
"coord_x": self.coord_x,
"coord_y": self.coord_y,
"direction": self.direction,
"visible": self.visible,
"talks": self.talks,
"message_list": self.message_list,
}
self.send_update(payload)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment