From 25328145cc28fb5f98c8af3214174ee6b9231d34 Mon Sep 17 00:00:00 2001
From: fheinrich <fheinrich@techfak.uni-bielefeld.de>
Date: Mon, 4 Dec 2023 16:17:40 +0100
Subject: [PATCH] Added actual player movement, added collision with world
 bounds

---
 .../overcooked_environment.py                 | 56 +++++++++++++++++--
 1 file changed, 51 insertions(+), 5 deletions(-)

diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py
index 16986f61..e260cfad 100644
--- a/overcooked_simulator/overcooked_environment.py
+++ b/overcooked_simulator/overcooked_environment.py
@@ -30,6 +30,8 @@ class Environment:
         self.layout_path = Path("overcooked_simulator/layouts/basic.layout")
         self.counters = self.create_counters(self.layout_path)
         self.score = 0
+        self.world_width = 800
+        self.world_height = 600
 
     def create_counters(self, layout_file: Path):
         """Creates layout of kitchen counters in the environment based on layout file.
@@ -55,7 +57,8 @@ class Environment:
                     counters.append(counter)
                     current_x += self.counter_side_length
                 elif character == "E":
-                    pass
+                    current_x += self.counter_side_length
+
 
             current_y += self.counter_side_length
         return counters
@@ -126,15 +129,45 @@ class Environment:
         """
         pass
 
-    def perform_movement(self, player: Player, action):
+    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.
+        (The extended code with the two ifs is for sliding movement at the counters, which feels a bit smoother.
+        This happens, when the player moves diagonally against the counters or world boundary.
+        This just checks if the single axis party of the movement could move the player and does so at a lower rate.)
+
+        The movement action is a unit 2d vector.
 
         Args:
             player: The player to move.
-            action: The Action which now contains a unit-2d-vector of the movement direction
+            move_vector: The movement vector which is a unit-2d-vector of the movement direction
         """
-        pass
+        old_pos = player.pos.copy()
+
+        step = move_vector * player.move_dist
+        player.move(step)
+        if self.detect_collision(player):
+            player.move_abs(old_pos)
+
+            old_pos = player.pos.copy()
+
+            step_sliding = step.copy()
+            step_sliding[0] = 0
+            player.move(step_sliding * 0.5)
+            player.turn(step)
+
+            if self.detect_collision(player):
+                player.move_abs(old_pos)
+
+                old_pos = player.pos.copy()
+
+                step_sliding = step.copy()
+                step_sliding[1] = 0
+                player.move(step_sliding * 0.5)
+                player.turn(step)
+
+                if self.detect_collision(player):
+                    player.move_abs(old_pos)
 
     def detect_collision(self, player: Player):
         """Detect collisions between the player and other players or counters.
@@ -144,7 +177,8 @@ class Environment:
 
         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)
+        return (self.detect_player_collision(player) or self.detect_collision_counters(player) or
+                self.detect_collision_world_bounds(player))
 
     def detect_player_collision(self, player: Player):
         """Detects collisions between the queried player and other players.
@@ -196,6 +230,18 @@ class Environment:
         distance = np.linalg.norm([dx, dy])
         return distance < player.radius
 
+    def detect_collision_world_bounds(self, player: Player):
+        """Checks for detections of the player and the world bounds.
+
+        Args:
+            player: The player which to not let escape the world.
+
+        Returns: True if the player touches the world bounds, False if not.
+        """
+        collisions_lower = any((player.pos - player.radius) < 0)
+        collisions_upper = any((player.pos + player.radius) > [self.world_width, self.world_height])
+        return collisions_lower or collisions_upper
+
     def step(self):
         """Performs a step of the environment. Affects time based events such as cooking or cutting things, orders
         and timelimits.
-- 
GitLab