From 0379e4f4b408d69d8b83aa80bf415211cb7e29f8 Mon Sep 17 00:00:00 2001 From: fheinrich <fheinrich@techfak.uni-bielefeld.de> Date: Wed, 6 Dec 2023 11:00:37 +0100 Subject: [PATCH] Added simple item Tomato to the environment. Added player pickup with items which lie on counters. --- overcooked_simulator/counters.py | 43 +++++++++++++++++++ overcooked_simulator/game_items.py | 6 +++ overcooked_simulator/main.py | 4 +- .../overcooked_environment.py | 41 ++++++------------ overcooked_simulator/player.py | 39 +++++++++++++++-- 5 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 overcooked_simulator/game_items.py diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 77ab32f8..c51e40e3 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -8,5 +8,48 @@ class Counter: self.pos = pos self.occupied_by = None + def pick_up(self): + """Gets called upon a player performing the pickup action. If the counter can give something to + the player, it does so. In the standard counter this is when an item is on the counter. + + Returns: The item which the counter is occupied by. None if nothing is there. + + """ + give_player = self.occupied_by + self.occupied_by = None + return give_player + + def drop_off(self, item): + """Takes the thing dropped of by the player. + + Args: + item: The item to be placed on the counter. + + Returns: TODO Return information, wether the score is affected (Serving Window?) + + """ + if self.occupied_by is None: + self.occupied_by = item + + def can_drop_off(self, item): + """Checks whether an item by the player can be dropped of. More relevant for example with + ingredient dispensers, which should always be occupied and cannot take an item. + + Args: + item: The item for which to check, if it can be placed on the counter. + + Returns: True if the item can be placed on the counter, False if not. + + """ + return self.occupied_by is None + + def interact_start(self): + """Starts an interaction by the player. Nothing happens for the standard counter.""" + pass + + def interact_stop(self): + """Stops an interaction by the player. Nothing happens for the standard counter.""" + pass + def __repr__(self): return f"Counter(pos:{str(self.pos)},holds:{self.occupied_by})" diff --git a/overcooked_simulator/game_items.py b/overcooked_simulator/game_items.py new file mode 100644 index 00000000..8dfb402a --- /dev/null +++ b/overcooked_simulator/game_items.py @@ -0,0 +1,6 @@ +class HoldableItem: + pass + + +class Tomato(HoldableItem): + pass diff --git a/overcooked_simulator/main.py b/overcooked_simulator/main.py index a53e5673..393255aa 100644 --- a/overcooked_simulator/main.py +++ b/overcooked_simulator/main.py @@ -1,7 +1,7 @@ -from overcooked_simulator.player import Player import sys from pathlib import Path +from overcooked_simulator.game_items import Tomato from overcooked_simulator.player import Player from overcooked_simulator.pygame_gui import PyGameGUI from overcooked_simulator.simulation_runner import Simulator @@ -12,6 +12,8 @@ def main(): simulator.register_player(Player("p1", [100, 200])) simulator.register_player(Player("p2", [200, 100])) + simulator.env.counters[4].occupied_by = Tomato() + gui = PyGameGUI(simulator) simulator.start() diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index 8fe744c7..9bd0e940 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -77,16 +77,24 @@ class Environment: action: The action to be performed """ assert action.player in self.players.keys(), "Unknown player." - player = self.players[action.player] + if action.act_type == "movement": self.perform_movement(player, action.action) - elif action.act_type == "pickup": - self.perform_pickup(player) - elif action.act_type == "interact": - self.perform_interact(player) - def get_closest_counter(self, point: np.array): + else: + counter = self.get_facing_counter(player) + if player.can_reach(counter): + if action.act_type == "pickup": + player.pick_action(counter) + + elif action.act_type == "interact": + if action.action == "keydown": + player.perform_interact_hold_start(counter) + elif action.action == "keyup": + player.perform_interact_hold_stop(counter) + + def get_closest_counter(self, point: np.ndarray): """Determines the closest counter for a given 2d-coordinate point in the env. Args: @@ -115,27 +123,6 @@ class Environment: facing_counter = self.get_closest_counter(facing_point) return facing_counter - def perform_pickup(self, player: Player): - """Performs the game action corresponding to picking up an item - - Args: - player: The player which performs the pickup action. - - Returns: TODO? - - """ - pass - - def perform_interact(self, player: Player): - """Performs the game action corresponding to interacting with a counter or other object. - - Args: - player: The player which performs the interaction. - - Returns: TODO? - """ - pass - def perform_movement(self, player: Player, move_vector: np.array): """Moves a player in the direction specified in the action.action. If the player collides with a counter or other player through this movement, then they are not moved. diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py index c4b11115..4920f0dc 100644 --- a/overcooked_simulator/player.py +++ b/overcooked_simulator/player.py @@ -17,7 +17,7 @@ class Player: self.radius = 18 self.move_dist = 5 - self.interaction_range = 50 + self.interaction_range = 60 self.facing_direction = np.array([0, 1]) def move(self, movement: np.array): @@ -50,6 +50,18 @@ class Player: if np.linalg.norm(direction) != 0: self.facing_direction = direction / np.linalg.norm(direction) + def can_reach(self, counter): + """Checks wether the player can reach the counter in question. Simple check if the distance is not larger + than the player interaction range. + + Args: + counter: The counter, can the player reach it? + + Returns: True if the counter is in range of the player, False if not. + + """ + return np.linalg.norm(counter.pos - self.pos) <= self.interaction_range + def pick_action(self, counter: Counter): """Performs the pickup-action with the counter. Handles the logic of what the player is currently holding, what is currently on the counter and what can be picked up or combined in hand. @@ -57,7 +69,11 @@ class Player: Args: counter: The counter to pick things up from or put things down. """ - pass + if self.holding is None: + self.holding = counter.pick_up() + elif counter.can_drop_off(self.holding): + counter.drop_off(self.holding) + self.holding = None def interact(self, counter: Counter): """Performs the interact-action with the counter. Handles logic of starting processes @@ -66,8 +82,25 @@ class Player: Args: counter: The counter to interact with. """ - pass + def perform_interact_hold_start(self, counter: Counter): + """Starts an interaction with the counter. Should be called for a + keydown event, for holding down a key on the keyboard. + + Args: + counter: The counter to start the interaction with. + """ + counter.interact_start() + + def perform_interact_hold_stop(self, counter: Counter): + """Stops an interaction with the counter. Should be called for a + keyup event, for letting go of a keyboard key. + + Args: + counter: The counter to stop the interaction with. + """ + counter.interact_stop() + def __repr__(self): return f"Player(name:{self.name},pos:{str(self.pos)},holds:{self.holding})" -- GitLab