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 @@ -26,6 +26,7 @@ Arcade [PyPi Release History](https://pypi.org/project/arcade/#history) page.
- Fixed `SpriteList.pop()` with a negative index other than `-1` (such as `pop(-2)`) drawing the wrong sprites: the removed sprite stayed on screen and another sprite disappeared.
- Fixed `SpriteList.rescale()` moving the list's center while rescaling, so sprites after the first were scaled around the wrong point.
- Fixed `SpriteList.preload_textures()` raising `AttributeError` on a lazy sprite list that hadn't been drawn yet. It now preloads into the atlas the list will use.
- Fixed GPU collision checks (`CollisionMethod.GPU`, also used automatically for sprite lists over 1500 sprites without a spatial hash) missing sprites flipped with a negative scale, whose negative width or height made them look smaller than they are.

### New Features
- Added `HitBox.get_adjusted_bounds()`, which returns the cached `(left, right, bottom, top)` bounds of the adjusted hit box points.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ void main() {

// Get the maximum x and y size
// max() works per component
vec2 size = max(size[0], check_size);
// Sizes are negative for sprites flipped with a negative scale
vec2 size = max(abs(size[0]), abs(check_size));

// Destroy the sprite if too far away
if (dist < max(size.x, size.y) * 1.42) {
Expand Down
3 changes: 2 additions & 1 deletion arcade/resources/system/shaders/collision/col_trans_gs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ void main() {

// Get the maximum x and y size
// max() works per component
vec2 size = max(size[0], check_size);
// Sizes are negative for sprites flipped with a negative scale
vec2 size = max(abs(size[0]), abs(check_size));

// Destroy the sprite if too far away
if (dist < max(size.x, size.y) * 1.42) {
Expand Down
35 changes: 35 additions & 0 deletions tests/unit/sprite/test_sprite_collision.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,41 @@ def test_check_for_collision_between_lists_type_errors(window):
arcade.check_for_collision_between_lists(arcade.SpriteList(), "moo")


@pytest.mark.parametrize(
"wall_scale, bullet_scale",
[
((1, 1), (1, 1)),
((-1, 1), (1, 1)),
((1, -1), (1, 1)),
((-1, -1), (1, 1)),
((1, 1), (-1, -1)),
((-1, -1), (-1, -1)),
],
)
def test_gpu_collision_flipped_sprites(window, wall_scale, bullet_scale):
"""The GPU path finds sprites flipped with a negative scale"""
if window.ctx._gl_api == "webgl":
pytest.skip("GPU collision isn't supported on WebGL")

# A long wall and a small bullet near its end, so only the wall's own
# size can bring them close enough
wall = arcade.SpriteSolidColor(200, 20)
wall.scale = wall_scale
walls = arcade.SpriteList()
walls.append(wall)
bullet = arcade.SpriteSolidColor(4, 4, center_x=80)
bullet.scale = bullet_scale

assert walls.get_nearby_sprites_gpu(bullet.position, bullet.size) == [wall]
gpu = arcade.CollisionMethod.GPU
assert arcade.check_for_collision_with_list(bullet, walls, method=gpu) == [wall]

# And still not when it's far away
bullet.position = 400, 0
assert walls.get_nearby_sprites_gpu(bullet.position, bullet.size) == []
assert arcade.check_for_collision_with_list(bullet, walls, method=gpu) == []


def test_check_for_collision_with_list(window):
# TODO: Check that the right collision function is called internally
a = arcade.SpriteSolidColor(50, 50, color=arcade.csscolor.RED)
Expand Down
Loading