diff --git a/overcooked_simulator/gui_2d_vis/overcooked_gui.py b/overcooked_simulator/gui_2d_vis/overcooked_gui.py index 7922bc2fedf5de237a620e01ef0ad2496e942da9..1f5dc39c2a0cc50475e7b8ea098a1ddfd69959df 100644 --- a/overcooked_simulator/gui_2d_vis/overcooked_gui.py +++ b/overcooked_simulator/gui_2d_vis/overcooked_gui.py @@ -68,12 +68,12 @@ class PyGameGUI: """Visualisation of the overcooked environment and reading keyboard inputs using pygame.""" def __init__( - self, - player_names: list[str | int], - player_keys: list[pygame.key], - url: str, - port: int, - manager_ids: list[str], + self, + player_names: list[str | int], + player_keys: list[pygame.key], + url: str, + port: int, + manager_ids: list[str], ): self.game_screen: pygame.Surface = None self.FPS = 60 @@ -182,11 +182,41 @@ class PyGameGUI: if np.linalg.norm(move_vec) != 0: move_vec = move_vec / np.linalg.norm(move_vec) + print("move_vec keys", move_vec) action = Action( key_set.name, ActionType.MOVEMENT, move_vec, duration=1 / self.FPS ) self.send_action(action) + def handle_joy_stick_input(self, joysticks): + """MISSING + """ + # see control stuff here (at the end of the page): https://www.pygame.org/docs/ref/joystick.html + for joystick in joysticks.values(): + # Usually axis run in pairs, up/down for one, and left/right for + # the other. Triggers count as axes. + axes = joystick.get_numaxes() + move_vec = np.zeros(2) + for i in range(axes): + axis = joystick.get_axis(i) + print("axis key", axis) + # joy stick left --> left & right + if axes == 0: + move_vec[0] += axis + # joy stick right --> up & down + elif axes == 1: + move_vec[1] += axis + + print("move_vec joystick before ", move_vec) + if np.linalg.norm(move_vec) != 0: + move_vec = move_vec / np.linalg.norm(move_vec) + + print("move_vec joystick", move_vec) + action = Action( + "0", ActionType.MOVEMENT, move_vec, duration=1 / self.FPS + ) + self.send_action(action) + 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 @@ -212,6 +242,37 @@ class PyGameGUI: ) self.send_action(action) + def handle_joy_stick_event(self, event): + """Handles joy stick events for the pickup and interaction keys. Pickup is a single action, + for interaction buttondown and buttonup is necessary, because the player has to be able to hold + the button down. + + Args: + event: Pygame event for extracting the button action. + """ + + if event.type == pygame.JOYBUTTONDOWN: + # pickup = Button A <-> 0 + if event.button == 0: + # FIXME: Name missing + action = Action("0", ActionType.PUT, "pickup") + self.send_action(action) + + # interact = Button X <-> 2 + if event.button == 2: + if event.type == pygame.JOYBUTTONDOWN: + # FIXME: Name missing + action = Action( + "0", ActionType.INTERACT, InterActionData.START + ) + self.send_action(action) + elif event.type == pygame.JOYBUTTONUP: + # FIXME: Name missing + action = Action( + "0", ActionType.INTERACT, InterActionData.STOP + ) + self.send_action(action) + 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") @@ -608,6 +669,11 @@ class PyGameGUI: # Game loop self.running = True + # This dict can be left as-is, since pygame will generate a + # pygame.JOYDEVICEADDED event for every joystick connected + # at the start of the program. + joysticks = {} + while self.running: try: time_delta = clock.tick(self.FPS) / 1000.0 @@ -616,6 +682,14 @@ class PyGameGUI: if event.type == pygame.QUIT: self.running = False + # connect joystick + if pygame.joystick.get_count() > 0 and event.type == pygame.JOYDEVICEADDED: + # This event will be generated when the program starts for every + # joystick, filling up the list without needing to create them manually. + joy = pygame.joystick.Joystick(event.device_index) + joysticks[joy.get_instance_id()] = joy + print(f"Joystick {joy.get_instance_id()} connencted") + # UI Buttons: if event.type == pygame_gui.UI_BUTTON_PRESSED: match event.ui_element: @@ -639,12 +713,14 @@ class PyGameGUI: self.manage_button_visibility() if ( - event.type in [pygame.KEYDOWN, pygame.KEYUP] - and self.menu_state == MenuStates.Game + event.type in [pygame.KEYDOWN, pygame.KEYUP] + and self.menu_state == MenuStates.Game ): - pass self.handle_key_event(event) + if event.type in [pygame.JOYBUTTONDOWN, pygame.JOYBUTTONUP] and self.menu_state == MenuStates.Game: + self.handle_joy_stick_event(event) + self.manager.process_events(event) # drawing: @@ -661,6 +737,7 @@ class PyGameGUI: state = self.request_state() self.handle_keys() + self.handle_joy_stick_input(joysticks=joysticks) if state["ended"]: self.finished_button_press() @@ -694,6 +771,9 @@ class PyGameGUI: def main(url: str, port: int, manager_ids: list[str]): # TODO maybe read the player names and keyboard keys from config file? + # First four keys are for movement. Order: Down, Up, Left, Right. + # 5th key is for interacting with counters. + # 6th key ist for picking up things or dropping them. keys1 = [ pygame.K_LEFT, pygame.K_RIGHT, @@ -703,6 +783,7 @@ def main(url: str, port: int, manager_ids: list[str]): pygame.K_i, ] keys2 = [pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s, pygame.K_f, pygame.K_e] + # FIXME: add buttons of joystick here number_players = 2 gui = PyGameGUI(