Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Arcade [PyPi Release History](https://pypi.org/project/arcade/#history) page.
## Unreleased

### Fixes
- Fixed `Sprite.remove_from_sprite_lists()` raising `AttributeError` for a sprite registered with `register_physics_engine()` on an engine without a `remove_sprite()` method, such as `PhysicsEngineSimple` or `PhysicsEnginePlatformer`. It now only calls `remove_sprite()` on engines that have it.
- Fixed a window sized with `arcade.get_display_size()` being bigger than the screen with display scaling, such as Windows set to 125% or 150%. Arcade scales windows up by the display scale, but `get_display_size()` returned the screen's size in pixels, so the window was scaled up twice. It now returns the size in window units on Windows and Linux: at 125%, a 1920x1200 screen gives 1536x960, which fills it exactly. On macOS and the web it's unchanged, as they don't scale windows ([#2791](https://github.com/pythonarcade/arcade/issues/2791)).
- Fixed `arcade.future.background.ParallaxGroup` raising `ZeroDivisionError` the first time its offset changed after a layer was given a depth of 0. Setting a depth of 0 now raises a `ValueError` right away, which says to use `float("inf")` for a layer that doesn't scroll ([#1551](https://github.com/pythonarcade/arcade/issues/1551)).
- GUI: Fixed a gap between `UIFlatButton`'s border and the edge of the button, half the border's width, which also showed on `UIDropdown` ([#2868](https://github.com/pythonarcade/arcade/issues/2868)).
Expand Down
6 changes: 5 additions & 1 deletion arcade/sprite/sprite.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ def remove_from_sprite_lists(self) -> None:
"""
super().remove_from_sprite_lists()
for engine in self.physics_engines:
engine.remove_sprite(self)
# Only some engines, such as PymunkPhysicsEngine, keep their own
# reference to the sprite. The others only use sprite lists.
remove_sprite = getattr(engine, "remove_sprite", None)
if remove_sprite is not None:
remove_sprite(self)

self.physics_engines.clear()

Expand Down
35 changes: 35 additions & 0 deletions tests/unit/sprite/test_sprite.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,3 +520,38 @@ def test_sprite_list_rescale_scales_hit_boxes(window):
assert sprite.hit_box.scale == (2.0, 2.0)
left, right, bottom, top = sprite.hit_box.get_adjusted_bounds()
assert right - left == top - bottom == 40.0


@pytest.mark.parametrize(
"engine_class", [arcade.PhysicsEngineSimple, arcade.PhysicsEnginePlatformer]
)
def test_remove_from_sprite_lists_with_registered_engine(engine_class):
# These engines have no remove_sprite, which used to raise AttributeError
player = arcade.SpriteSolidColor(10, 10)
sprites = arcade.SpriteList()
sprites.append(player)
engine = engine_class(player, walls=arcade.SpriteList())
player.register_physics_engine(engine)

player.remove_from_sprite_lists()

assert player not in sprites
assert player.physics_engines == []


def test_remove_from_sprite_lists_calls_engine_remove_sprite():
class Engine:
def __init__(self):
self.removed = []

def remove_sprite(self, sprite):
self.removed.append(sprite)

sprite = arcade.SpriteSolidColor(10, 10)
engine = Engine()
sprite.register_physics_engine(engine)

sprite.remove_from_sprite_lists()

assert engine.removed == [sprite]
assert sprite.physics_engines == []
Loading