diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index c6e4970e3af8dfc6aaf79e533c33b18037891015..16986f619f77234b0d4d867d942a9d769067f679 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -143,9 +143,58 @@ class Environment: player: The player for which to check collisions. Returns: True if the player is intersecting with any object in the environment. + """ + return self.detect_player_collision(player) or self.detect_collision_counters(player) + + def detect_player_collision(self, player: Player): + """Detects collisions between the queried player and other players. + A player is modelled as a circle. Collision is detected if the distance between the players is smaller + than the sum of the radius's. + + Args: + player: The player to check collisions with other players for. + + Returns: True if the player collides with other players, False if not. """ - pass + other_players = filter(lambda p: p.name != player.name, self.players.values()) + + def collide(p): + return np.linalg.norm(player.pos - p.pos) <= (player.radius + p.radius) + + return any(map(collide, other_players)) + + def detect_collision_counters(self, player: Player): + """Checks for collisions of the queried player with each counter. + + Args: + player: The player to check collisions with counters for. + + Returns: True if the player collides with any counter, False if not. + + """ + return any(map(lambda counter: self.detect_collision_player_counter(player, counter), self.counters)) + + def detect_collision_player_counter(self, player: Player, counter: Counter): + """Checks if the player and counter collide (overlap). + A counter is modelled as a rectangle (square actually), a player is modelled as a circle. + The distance of the player position (circle center) and the counter rectangle is calculated, if it is + smaller than the player radius, a collision is detected. + TODO: Efficiency improvement by checking only nearest counters? Quadtree...? + + Args: + player: The player to check the collision for. + counter: The counter to check the collision for. + + Returns: True if player and counter overlap, False if not. + + """ + size = self.counter_side_length + cx, cy = player.pos + dx = max(np.abs(cx - counter.pos[0]) - size / 2, 0) + dy = max(np.abs(cy - counter.pos[1]) - size / 2, 0) + distance = np.linalg.norm([dx, dy]) + return distance < player.radius def step(self): """Performs a step of the environment. Affects time based events such as cooking or cutting things, orders diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py index b98df2d6efa5b0e73fea9362304572bee1091a22..bea1771a86f5bebd0f7bd6a4de75812011f0a7bb 100644 --- a/overcooked_simulator/player.py +++ b/overcooked_simulator/player.py @@ -13,6 +13,7 @@ class Player: self.pos = np.array(pos, dtype=float) self.holding = None + self.radius = 18 self.move_dist = 5 self.interaction_range = 50 self.facing_direction = np.array([0, 1])