diff --git a/overcooked_simulator/images/tomato.png b/overcooked_simulator/images/tomato.png new file mode 100644 index 0000000000000000000000000000000000000000..84e063976d58e8a4aa194124409223e3c67c6834 Binary files /dev/null and b/overcooked_simulator/images/tomato.png differ diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index 9bd0e9402099a396143871a93ed6c6ed6011a32f..4b3d48e2d9e18ff232f52d908bf2895a1613d694 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -23,6 +23,9 @@ class Action: ], "Unknown action type" self.action = action + def __repr__(self): + return f"Action({self.player},{self.act_type},{self.action})" + class Environment: """Environment class which handles the game logic for the overcooked-inspired environment. @@ -76,6 +79,9 @@ class Environment: Args: action: The action to be performed """ + + # print("RECEIVED ACTION:", action) + assert action.player in self.players.keys(), "Unknown player." player = self.players[action.player] diff --git a/overcooked_simulator/pygame_gui.py b/overcooked_simulator/pygame_gui.py index a1c655ef4bee18860ae1efd2a1ffe0b9fd61c8af..fbff09f918cb27a1e0f4fdb6e9a6e0b9fbba318b 100644 --- a/overcooked_simulator/pygame_gui.py +++ b/overcooked_simulator/pygame_gui.py @@ -1,6 +1,7 @@ import numpy as np import pygame +from overcooked_simulator.game_items import Tomato from overcooked_simulator.overcooked_environment import Action from overcooked_simulator.simulation_runner import Simulator @@ -24,7 +25,8 @@ class PlayerKeyset: 6th key ist for picking up things or dropping them. """ - def __init__(self, keys: list[pygame.key]): + def __init__(self, player_name: str, keys: list[pygame.key]): + self.name = player_name self.player_keys = keys self.move_vectors = [[-1, 0], [1, 0], [0, -1], [0, 1]] self.key_to_movement = { @@ -58,8 +60,8 @@ class PyGameGUI: ] keys2 = [pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s, pygame.K_f, pygame.K_e] self.player_keysets: list[PlayerKeyset] = [ - PlayerKeyset(keys1), - PlayerKeyset(keys2), + PlayerKeyset("p1", keys1), + PlayerKeyset("p2", keys2), ] def send_action(self, action: Action): @@ -95,20 +97,25 @@ class PyGameGUI: action = Action(f"p{player_idx + 1}", "pickup", "pickup") self.send_action(action) - def handle_interact_single_send(self, event): - """Handles key events. Here when a key is held down, only one action is sent. (This can be - switched by the GET_CONTINOUS_INTERACT_AND_PICKUP flag) + def handle_key_event(self, event): + """Handles key events for the pickup and interaction keys. Pickup is a single action, + for interaction keydown and keyup is necessary, because the player has to be able to hold + the key down. Args: - event: Pygame event for extracting the key. + event: Pygame event for extracting the key action. """ - for player_idx, keyset in enumerate(self.player_keysets): - if event.key == keyset.pickup_key: - action = Action(f"p{player_idx + 1}", "pickup", "pickup") - self.send_action(action) - elif event.key == keyset.interact_key: - action = Action(f"p{player_idx + 1}", "interact", "interact") + for keyset in self.player_keysets: + if event.key == keyset.pickup_key and event.type == pygame.KEYDOWN: + action = Action(keyset.name, "pickup", "pickup") self.send_action(action) + if event.key == keyset.interact_key: + if event.type == pygame.KEYDOWN: + action = Action(keyset.name, "interact", "keydown") + self.send_action(action) + elif event.type == pygame.KEYUP: + action = Action(keyset.name, "interact", "keyup") + self.send_action(action) def draw_background(self): """Visualizes a game background.""" @@ -120,6 +127,7 @@ class PyGameGUI: def draw_players(self, state): """Visualizes the players as circles with a triangle for the facing diretion. + If the player holds something in their hands, it is displayed Args: state: The game state returned by the environment. @@ -145,6 +153,36 @@ class PyGameGUI: player.pos + (facing * 20), ), ) + if player.holding is not None: + holding_item_pos = player.pos + (20 * player.facing_direction) + self.draw_item(holding_item_pos, player.holding) + + def draw_item(self, pos, item): + """Visualisation of an item at the specified position. On a counter or in the hands of the player.""" + if isinstance(item, Tomato): + IMAGE = pygame.image.load( + "overcooked_simulator/images/tomato.png" + ).convert_alpha() # or .convert_alpha() + rect = IMAGE.get_rect() + rect.center = pos + self.screen.blit(IMAGE, rect) + + def draw_counter(self, counter): + """Visualisation of a counter at its position. If it is occupied by an item, it is also shown. + + Args: + counter: The counter to visualize. + """ + counter_rect_outline = pygame.Rect( + counter.pos[0] - (self.counter_size / 2), + counter.pos[1] - (self.counter_size / 2), + self.counter_size, + self.counter_size, + ) + pygame.draw.rect(self.screen, COUNTERCOLOR, counter_rect_outline) + + if counter.occupied_by is not None: + self.draw_item(counter.pos, counter.occupied_by) def draw_counters(self, state): """Visualizes the counters in the environment. @@ -152,15 +190,8 @@ class PyGameGUI: Args: state: The game state returned by the environment. """ - for idx, counter in enumerate(state["counters"]): - counter_rect_outline = pygame.Rect( - counter.pos[0] - (self.counter_size / 2), - counter.pos[1] - (self.counter_size / 2), - self.counter_size, - self.counter_size, - ) - - pygame.draw.rect(self.screen, COUNTERCOLOR, counter_rect_outline) + for counter in state["counters"]: + self.draw_counter(counter) def draw(self, state): """Main visualization function. @@ -193,9 +224,8 @@ class PyGameGUI: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False - if not self.GET_CONTINOUS_INTERACT_AND_PICKUP: - if event.type == pygame.KEYDOWN: - self.handle_interact_single_send(event) + if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP: + self.handle_key_event(event) self.handle_keys() clock.tick(self.FPS)