diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 9fe8eee9fd3d50108ea1dfc9b2c15635e556434d..12b10e1720439361cb206f0bf334193054053227 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -368,6 +368,7 @@ class Sink(Counter): "result" ] plate = self.occupied_by.pop() + plate.clean = True self.sink_addon.add_clean_plate(plate) def start_progress(self): diff --git a/overcooked_simulator/game_content/environment_config.yaml b/overcooked_simulator/game_content/environment_config.yaml index a5b77f8b13f33361009a5aedab5d6c91da98c907..9643636f939aec5f9647655ceba2a682ad9a1469 100644 --- a/overcooked_simulator/game_content/environment_config.yaml +++ b/overcooked_simulator/game_content/environment_config.yaml @@ -1,7 +1,11 @@ plates: - clean_plates: 3 + clean_plates: 0 dirty_plates: 2 plate_delay: [ 5, 10 ] game: time_limit_seconds: 180 + +orders: + select_from: [ TomatoSoup, OnionSoup ] + timing: [ ] diff --git a/overcooked_simulator/gui_2d_vis/overcooked_gui.py b/overcooked_simulator/gui_2d_vis/overcooked_gui.py index 6686fef3779a22611a20107720d41fb6e9aec38e..65c1b821fac0bd5a9aeb225eb054e2d5d7fefa67 100644 --- a/overcooked_simulator/gui_2d_vis/overcooked_gui.py +++ b/overcooked_simulator/gui_2d_vis/overcooked_gui.py @@ -119,6 +119,10 @@ class PyGameGUI: self.buttons_width = self.visualization_config["GameWindow"]["buttons_width"] self.buttons_height = self.visualization_config["GameWindow"]["buttons_height"] + self.order_bar_height = self.visualization_config["GameWindow"][ + "order_bar_height" + ] + self.window_width = self.min_width self.window_height = self.min_height @@ -259,7 +263,9 @@ class PyGameGUI: 1, ) - def draw_image(self, img_path, size, pos, rot_angle=0): + def draw_image( + self, img_path, size, pos, rot_angle=0, screen: pygame.Surface = None + ): cache_entry = f"{img_path}" if cache_entry in self.image_cache_dict.keys(): image = self.image_cache_dict[cache_entry] @@ -274,7 +280,11 @@ class PyGameGUI: image = pygame.transform.rotate(image, rot_angle) rect = image.get_rect() rect.center = pos - self.game_screen.blit(image, rect) + + if screen is None: + self.game_screen.blit(image, rect) + else: + screen.blit(image, rect) def draw_players(self, state): """Visualizes the players as circles with a triangle for the facing direction. @@ -362,7 +372,11 @@ class PyGameGUI: ) def draw_thing( - self, pos: npt.NDArray[float], parts: list[dict[str]], scale: float = 1.0 + self, + pos: npt.NDArray[float], + parts: list[dict[str]], + scale: float = 1.0, + screen: pygame.Surface = None, ): """Draws an item, based on its visual parts specified in the visualization config. @@ -372,6 +386,9 @@ class PyGameGUI: scale: Rescale the item by this factor. """ + if screen is None: + screen = self.game_screen + for part in parts: part_type = part["type"] match part_type: @@ -384,6 +401,7 @@ class PyGameGUI: parts[0]["path"], parts[0]["size"] * scale * self.grid_size, pos, + screen=screen, ) case "rect": height = part["height"] * self.grid_size @@ -392,7 +410,7 @@ class PyGameGUI: if "center_offset" in part: dx, dy = np.array(part["center_offset"]) * self.grid_size rect = pygame.Rect(pos[0] + dx, pos[1] + dy, height, width) - pygame.draw.rect(self.game_screen, color, rect) + pygame.draw.rect(screen, color, rect) else: rect = pygame.Rect( pos[0] - (height / 2), @@ -400,7 +418,7 @@ class PyGameGUI: height, width, ) - pygame.draw.rect(self.game_screen, color, rect) + pygame.draw.rect(screen, color, rect) case "circle": radius = part["radius"] * self.grid_size color = colors[part["color"]] @@ -412,7 +430,7 @@ class PyGameGUI: radius, ) else: - pygame.draw.circle(self.game_screen, color, pos, radius) + pygame.draw.circle(screen, color, pos, radius) def draw_item( self, pos: npt.NDArray[float], item: Item, scale: float = 1.0, plate=False @@ -525,6 +543,65 @@ class PyGameGUI: display_time = f"{minutes}:{'%02d' % seconds}" self.timer_label.set_text(f"Time remaining: {display_time}") + def draw_orders(self, state): + orders = [ + "Tomato", + "TomatoSoupPlate", + "OnionSoupPlate", + "OnionSoupPlate", + "OnionSoupPlate", + "OnionSoupPlate", + ] + + orders_width = self.game_width - 100 + orders_height = self.screen_margin + self.orders_screen = pygame.Surface( + (orders_width, orders_height), + ) + + pygame.draw.rect( + self.orders_screen, colors["green"], self.orders_screen.get_rect() + ) + + order_rects_start = (orders_height // 2) - (self.grid_size // 2) + + for idx, order in enumerate(orders): + order_upper_left = [ + order_rects_start + idx * self.grid_size * 1.5, + order_rects_start, + ] + pygame.draw.rect( + self.orders_screen, + colors["red"], + pygame.Rect( + order_upper_left[0], + order_upper_left[1], + self.grid_size, + self.grid_size, + ), + width=2, + ) + center = np.array(order_upper_left) + np.array( + [self.grid_size / 2, self.grid_size / 2] + ) + self.draw_thing( + center, + self.visualization_config["Plate"]["parts"], + screen=self.orders_screen, + ) + self.draw_thing( + center, + self.visualization_config[order]["parts"], + screen=self.orders_screen, + ) + + orders_rect = self.orders_screen.get_rect() + orders_rect.center = [ + self.screen_margin + (orders_width // 2), + orders_height // 2, + ] + self.main_window.blit(self.orders_screen, orders_rect) + def draw(self, state): """Main visualization function. @@ -539,6 +616,8 @@ class PyGameGUI: self.manager.draw_ui(self.main_window) self.update_remaining_time(state["remaining_time"]) + self.draw_orders(state) + def init_ui_elements(self): self.manager = pygame_gui.UIManager((self.window_width, self.window_height)) self.manager.get_theme().load_theme(ROOT_DIR / "gui_2d_vis" / "gui_theme.json") @@ -629,12 +708,11 @@ class PyGameGUI: options_list=layout_file_paths, starting_option=layout_file_paths[-1], ) - self.timer_label = pygame_gui.elements.UILabel( text="GAMETIME", relative_rect=pygame.Rect( - (0, 0), - (self.buttons_width * 1.5, self.buttons_height), + (self.screen_margin, self.window_height - self.screen_margin), + (self.game_width, self.screen_margin), ), manager=self.manager, object_id="#timer_label", @@ -748,6 +826,7 @@ class PyGameGUI: clock = pygame.time.Clock() + self.reset_window_size() self.init_ui_elements() self.manage_button_visibility() diff --git a/overcooked_simulator/gui_2d_vis/visualization.yaml b/overcooked_simulator/gui_2d_vis/visualization.yaml index 0bec00301f5212459e5c34d4b29048b02e813234..d0557b828d7380299cdee0f398ce7676bce3413f 100644 --- a/overcooked_simulator/gui_2d_vis/visualization.yaml +++ b/overcooked_simulator/gui_2d_vis/visualization.yaml @@ -9,6 +9,8 @@ GameWindow: buttons_width: 180 buttons_height: 60 + order_bar_height: 100 + order_size: 50 Kitchen: ground_tiles_color: sgigray76 diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py index 4f85046ff9a100c8b0b95a43246a9acccaff4b04..dc70d32c84a483213a7167e1cae67f9d59be7311 100644 --- a/overcooked_simulator/player.py +++ b/overcooked_simulator/player.py @@ -9,7 +9,7 @@ import yaml from overcooked_simulator import ROOT_DIR from overcooked_simulator.counters import Counter -from overcooked_simulator.game_items import Item +from overcooked_simulator.game_items import Item, Plate log = logging.getLogger(__name__) @@ -120,6 +120,8 @@ class Player: log.debug( f"Self: {self.holding}, {counter.__class__.__name__}: {counter.occupied_by}" ) + if isinstance(self.holding, Plate): + log.debug(self.holding.clean) def perform_interact_hold_start(self, counter: Counter): """Starts an interaction with the counter. Should be called for a