From c59e8b99dacd904c72d585258a136221d25232d5 Mon Sep 17 00:00:00 2001 From: The-PotatoKing Date: Fri, 17 Oct 2025 05:00:00 +0000 Subject: [PATCH 1/2] Fixed sliding sprite platformer collisions by correctly selecting the platform with the highest top edge. This prevents players from getting stuck when colliding with multiple platforms. --- arcade/physics_engines.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/arcade/physics_engines.py b/arcade/physics_engines.py index d68275d77..3ef8d1dc9 100644 --- a/arcade/physics_engines.py +++ b/arcade/physics_engines.py @@ -149,14 +149,37 @@ def _move_sprite( # f" {self.player_sprite.change_y}") elif moving_sprite.change_y < 0: # Reset number of jumps + # If we collided while moving down, we may be landing on one or more + # floor-like sprites. If multiple moving platforms overlap under + # the player, only apply the horizontal motion of a single + # platform (the one most directly under the player) to avoid + # accumulating motion from multiple platforms which can cause + # sliding/jitter when the player is between blocks. + + + # Prefer platforms (moving sprites) among the collisions. + platform_items = [ + item + for item in hit_list_x + if getattr(item, "change_x", 0.0) != 0 or getattr(item, "change_y", 0.0) != 0 + ] + + # Choose the platform with the highest top (closest to the player) + chosen_platform = None + if platform_items: + chosen_platform = max(platform_items, + key=lambda s: getattr(s, "top", + float("-inf"))) + + # Nudge the player up until no longer colliding with each collided item for item in hit_list_x: while check_for_collision(moving_sprite, item): # self.player_sprite.bottom = item.top <- Doesn't work for ramps moving_sprite.center_y += 0.25 - # NOTE: Not all sprites have velocity - if getattr(item, "change_x", 0.0) != 0: - moving_sprite.center_x += item.change_x # type: ignore + # Apply horizontal movement from the chosen platform (once) + if chosen_platform is not None and getattr(chosen_platform, "change_x", 0.0) != 0: + moving_sprite.center_x += chosen_platform.change_x # type: ignore # print(f"Spot Y ({self.player_sprite.center_x}, {self.player_sprite.center_y})") else: From a922a47fe10242b16868620aaf54be56904b3ccd Mon Sep 17 00:00:00 2001 From: The-PotatoKing Date: Fri, 17 Oct 2025 13:49:36 +0000 Subject: [PATCH 2/2] Fixed Formatting from previous commit modified: tests/test_physics_engines.py --- arcade/physics_engines.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arcade/physics_engines.py b/arcade/physics_engines.py index 3ef8d1dc9..deecd2748 100644 --- a/arcade/physics_engines.py +++ b/arcade/physics_engines.py @@ -156,7 +156,6 @@ def _move_sprite( # accumulating motion from multiple platforms which can cause # sliding/jitter when the player is between blocks. - # Prefer platforms (moving sprites) among the collisions. platform_items = [ item @@ -167,9 +166,9 @@ def _move_sprite( # Choose the platform with the highest top (closest to the player) chosen_platform = None if platform_items: - chosen_platform = max(platform_items, - key=lambda s: getattr(s, "top", - float("-inf"))) + chosen_platform = max( + platform_items, key=lambda s: getattr(s, "top", float("-inf")) + ) # Nudge the player up until no longer colliding with each collided item for item in hit_list_x: