diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 2b980877828189671859ef2cec20a66745f6dfbb..8e76013e7ce405e8215a249122eeea4f9b22da5c 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -84,8 +84,7 @@ class Counter: self.uuid = uuid.uuid4().hex if uid is None else None self.pos: npt.NDArray[float] = pos self.occupied_by: Optional[Item] = occupied_by - self.orientation: npt.NDArray[float] = np.zeros(2) - self.orientation[0] = 1 + self.orientation: npt.NDArray[float] = np.array([0, 1], dtype=float) @property def occupied(self): @@ -164,6 +163,7 @@ class Counter: "category": COUNTER_CATEGORY, "type": self.__class__.__name__, "pos": self.pos.tolist(), + "orientation": self.orientation.tolist(), "occupied_by": None if self.occupied_by is None else ( diff --git a/overcooked_simulator/game_content/layouts/rot_test.layout b/overcooked_simulator/game_content/layouts/rot_test.layout new file mode 100644 index 0000000000000000000000000000000000000000..d3bd23d0a2dbe378bbc7a128995e8240ebb916fb --- /dev/null +++ b/overcooked_simulator/game_content/layouts/rot_test.layout @@ -0,0 +1,5 @@ +##S+# +S___# ++___S +#___+ +#+SP# \ No newline at end of file diff --git a/overcooked_simulator/gui_2d_vis/drawing.py b/overcooked_simulator/gui_2d_vis/drawing.py index c257730d3be73f30bbacbcbc090a045da3b34eb1..5d047bd2df564eb53b9da0f2ca02960440c0e475 100644 --- a/overcooked_simulator/gui_2d_vis/drawing.py +++ b/overcooked_simulator/gui_2d_vis/drawing.py @@ -1,5 +1,4 @@ import colorsys -import math from datetime import datetime, timedelta from pathlib import Path @@ -21,6 +20,12 @@ SHOW_INTERACTION_RANGE = False SHOW_COUNTER_CENTERS = False +def calc_angle(vec_a: list[float], vec_b: list[float]) -> float: + a = pygame.math.Vector2(vec_a) + b = pygame.math.Vector2(vec_b) + return a.angle_to(b) + + def create_polygon(n, length): if n == 1: return np.array([0, 0]) @@ -141,7 +146,7 @@ class Visualizer: player_dict: PlayerState pos = np.array(player_dict["pos"]) * grid_size - facing = np.array(player_dict["facing_direction"]) + facing = np.array(player_dict["facing_direction"], dtype=float) if USE_PLAYER_COOK_SPRITES: pygame.draw.circle( @@ -152,8 +157,7 @@ class Visualizer: ) img_path = self.config["Cook"]["parts"][0]["path"] - rel_x, rel_y = facing - angle = -np.rad2deg(math.atan2(rel_y, rel_x)) + 90 + angle = calc_angle(facing.tolist(), [0, 1]) size = self.config["Cook"]["parts"][0]["size"] * grid_size self.draw_image(screen, img_path, size, pos, angle) @@ -224,6 +228,7 @@ class Visualizer: grid_size: float, parts: list[dict[str]], scale: float = 1.0, + orientation: list[float] | None = None, ): """Draws an item, based on its visual parts specified in the visualization config. @@ -233,21 +238,32 @@ class Visualizer: pos: Where to draw the item parts. parts: The visual parts to draw. scale: Rescale the item by this factor. + orientation: Rotate the item to face this direction. """ for part in parts: part_type = part["type"] match part_type: case "image": + angle, angle_offset = 0, 0 + if orientation is not None: + angle_offset = calc_angle(orientation, [0, 1]) + if "rotate_image" in part.keys(): + if part["rotate_image"]: + angle = calc_angle(orientation, [0, 1]) + else: + angle = angle_offset if "center_offset" in part: - d = np.array(part["center_offset"]) * grid_size + d = pygame.math.Vector2(part["center_offset"]) * grid_size + d.rotate_ip(angle_offset) pos = np.array(pos) - pos += d + pos += np.array(d) self.draw_image( screen, part["path"], part["size"] * scale * grid_size, pos, + rot_angle=angle, ) case "rect": height = part["height"] * grid_size @@ -371,9 +387,21 @@ class Visualizer: """ pos = np.array(counter_dict["pos"]) * grid_size counter_type = counter_dict["type"] - self.draw_thing(screen, pos, grid_size, self.config["Counter"]["parts"]) + self.draw_thing( + screen, + pos, + grid_size, + self.config["Counter"]["parts"], + orientation=counter_dict["orientation"], + ) if counter_type in self.config: - self.draw_thing(screen, pos, grid_size, self.config[counter_type]["parts"]) + self.draw_thing( + screen, + pos, + grid_size, + self.config[counter_type]["parts"], + orientation=counter_dict["orientation"], + ) else: if counter_type in self.config: parts = self.config[counter_type]["parts"] @@ -429,9 +457,26 @@ class Visualizer: grid_size, np.array(counter["pos"]) * grid_size, ) + if SHOW_COUNTER_CENTERS: - pygame.draw.circle( - screen, colors["green1"], np.array(counter["pos"]) * grid_size, 3 + pos = np.array(counter["pos"]) * grid_size + pygame.draw.circle(screen, colors["green1"], pos, 3) + pygame.draw.circle(screen, colors["green1"], pos, 3) + facing = np.array(counter["orientation"]) + pygame.draw.polygon( + screen, + colors["red"], + ( + ( + pos[0] + (facing[1] * 0.1 * grid_size), + pos[1] - (facing[0] * 0.1 * grid_size), + ), + ( + pos[0] - (facing[1] * 0.1 * grid_size), + pos[1] + (facing[0] * 0.1 * grid_size), + ), + pos + (facing * 0.5 * grid_size), + ), ) def draw_orders( diff --git a/overcooked_simulator/gui_2d_vis/images/arrow_right.png b/overcooked_simulator/gui_2d_vis/images/arrow_right.png index 522ec051e8f1ad938c8e53cd0e8b563f1e383cb1..a1ea0946b67e89bed858a0312ed6ee70ea68c1c7 100644 Binary files a/overcooked_simulator/gui_2d_vis/images/arrow_right.png and b/overcooked_simulator/gui_2d_vis/images/arrow_right.png differ diff --git a/overcooked_simulator/gui_2d_vis/visualization.yaml b/overcooked_simulator/gui_2d_vis/visualization.yaml index 21005007a59ecf3fe868e69f1c8ff48363c68114..6fbd622cbd53ec51e6b73dda3ea98f00260acccc 100644 --- a/overcooked_simulator/gui_2d_vis/visualization.yaml +++ b/overcooked_simulator/gui_2d_vis/visualization.yaml @@ -2,7 +2,7 @@ GameWindow: WhatIsFixed: grid # grid or window_width or window_height - size: 50 + size: 80 screen_margin: 100 min_width: 700 min_height: 600 @@ -22,10 +22,13 @@ Kitchen: Counter: parts: - - type: rect - height: 1 - width: 1 - color: whitesmoke + # - type: rect + # height: 1 + # width: 1 + # color: whitesmoke + - type: image + path: images/counter2.png + size: 1 CuttingBoard: parts: @@ -92,14 +95,15 @@ Dispenser: ServingWindow: parts: - - type: image - path: images/arrow_right.png - size: 1 - center_offset: [ 0, 0 ] + # - type: image + # path: images/arrow_right.png + # size: 1 + # center_offset: [ 0, 0 ] - type: image path: images/bell_gold.png size: 0.5 - center_offset: [ 0.1, -0.4 ] + center_offset: [ -0.4, 0.1 ] + rotate_image: False Stove: parts: diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index 1707b515f5e03cb4aad1d3b621fe271a13fd3e70..837eb7ed1142b42e4bea7f90334b85cd3328d350 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -304,11 +304,7 @@ class Environment: for character in line: character = character.capitalize() pos = np.array([current_x, current_y]) - counter_class = self.SYMBOL_TO_CHARACTER_MAP[character] - if not isinstance(counter_class, str): - counter = counter_class(pos) - counters.append(counter) - grid_line.append(1) + assert self.counter_factory.can_map( character ), f"{character=} in layout file can not be mapped" @@ -316,14 +312,9 @@ class Environment: counters.append( self.counter_factory.get_counter_object(character, pos) ) + grid_line.append(1) else: grid_line.append(0) - if counter_class == "Agent": - designated_player_positions.append( - np.array([current_x, current_y]) - ) - elif counter_class == "Free": - free_positions.append(np.array([current_x, current_y])) match self.counter_factory.map_not_counter(character): case "Agent": designated_player_positions.append(pos) @@ -348,6 +339,9 @@ class Environment: return counters, designated_player_positions, free_positions def determine_counter_orientations(self, counters, grid, kitchen_center): + for l in grid: + print(l) + grid = np.array(grid).T grid_width = grid.shape[0] @@ -381,7 +375,6 @@ class Environment: c.set_orientation(nearest_vec) else: - print("HERE", c) c.set_orientation(np.array([0, 1])) # for c in counters: diff --git a/overcooked_simulator/state_representation.py b/overcooked_simulator/state_representation.py index e8ad5d17a79b4db29c2977934f0127c7a09c83f9..1912be8a9b530ac50b41c9648c9f50e16fd3fe31 100644 --- a/overcooked_simulator/state_representation.py +++ b/overcooked_simulator/state_representation.py @@ -30,6 +30,7 @@ class CounterState(TypedDict): category: Literal["Counter"] type: str pos: list[float] + orientation: list[float] occupied_by: None | list[ ItemState | CookingEquipmentState ] | ItemState | CookingEquipmentState