diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index 77ab32f890e3c0a464b168f11b5739fca438978f..c51e40e3edadac99743e4cc96b74b3b4b983a657 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 0000000000000000000000000000000000000000..8dfb402a612f7490c1a75bc9468322b010289453 --- /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 a53e56731e0f3749f9aa3573e115afef660e9753..393255aa8756aabbeda18e8dfedfc2cb3c241754 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 8fe744c7667809e596b96ac759c9bbaffeab79f4..9bd0e9402099a396143871a93ed6c6ed6011a32f 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 c4b11115671a69b6df4a1526ef6d9cd7731ae9d4..4920f0dcbd52573b13a757af2101783ae7cc5578 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})"