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 `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)).
- GUI: Passing a single style such as `UIFlatButton.UIStyle()` as a widget's `style` raised a confusing `TypeError` about attribute names. It now raises a `TypeError` saying a dict of styles for each state is needed, and how to start from the widget's `DEFAULT_STYLE` ([#2817](https://github.com/pythonarcade/arcade/issues/2817)).
- GUI: Fixed `UITextArea`:
Expand Down
19 changes: 17 additions & 2 deletions arcade/future/background/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,25 @@ def add_from_file(
self.add(background)


def _check_depth(depth: float) -> float:
"""Raise a ValueError for a depth of 0, which ParallaxGroup can't divide by."""
if depth == 0:
raise ValueError(
"A ParallaxGroup depth can't be 0. For a layer that doesn't scroll, use float('inf')."
)
return depth


class ParallaxGroup:
"""
The ParallaxBackground holds a list of backgrounds and a list of depths.
When you change the offset through the ParallaxBackground
each Background's offset will be set inversely proportional to its depth.
This creates the effect of Backgrounds with greater depths appearing further away.
The depth does not affect the positioning of layers at all.

A depth can't be 0. For a layer that doesn't scroll, such as a distant sky,
use ``float("inf")``.
"""

def __init__(
Expand All @@ -108,6 +120,8 @@ def __init__(

if len(self._backgrounds) != len(self._depths):
raise ValueError("The number of backgrounds does not equal the number of depth values")
for depth in self._depths:
_check_depth(depth)

self._pos = (0.0, 0.0)
self._offset = (0.0, 0.0)
Expand Down Expand Up @@ -136,11 +150,12 @@ def __getitem__(self, item: int):

def __setitem__(self, key: int, value: Background | float):
if isinstance(value, float | int):
self._depths[key] = value
self._depths[key] = _check_depth(value)
else:
self._backgrounds[key] = value

def add(self, item: Background, depth: float = 1.0):
_check_depth(depth)
if item not in self._backgrounds:
self._backgrounds.append(item)
self._depths.append(depth)
Expand All @@ -153,7 +168,7 @@ def remove(self, item: Background):
self._depths.pop(index)

def change_depth(self, item: Background, new_depth: float):
self._depths[self._backgrounds.index(item)] = new_depth
self._depths[self._backgrounds.index(item)] = _check_depth(new_depth)

def extend(self, items: list[Background], depths: list[float]):
for index, item in enumerate(items):
Expand Down
49 changes: 49 additions & 0 deletions tests/unit/test_background_parallax_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""ParallaxGroup offsets each layer by the group offset divided by its depth (#1551)."""

import math

import pytest

from arcade.future.background import Background, ParallaxGroup

TEXTURE = ":resources:images/cybercity_background/far-buildings.png"


def _layer():
return Background.from_file(TEXTURE)


def test_offset_is_divided_by_depth(window):
near, far = _layer(), _layer()
group = ParallaxGroup([near, far], [1.0, 4.0])
group.offset = (100.0, 40.0)
assert near.texture.offset == pytest.approx((100.0, 40.0))
assert far.texture.offset == pytest.approx((25.0, 10.0))


def test_infinite_depth_doesnt_scroll(window):
sky = _layer()
group = ParallaxGroup()
group.add(sky, math.inf)
group.offset = (100.0, 40.0)
assert sky.texture.offset == pytest.approx((0.0, 0.0))


def test_depth_zero_is_rejected(window):
layer = _layer()
with pytest.raises(ValueError, match="can't be 0"):
ParallaxGroup([layer], [0.0])

group = ParallaxGroup()
with pytest.raises(ValueError, match="can't be 0"):
group.add(layer, 0)

group.add(layer, 2.0)
with pytest.raises(ValueError, match="can't be 0"):
group.change_depth(layer, 0.0)
with pytest.raises(ValueError, match="can't be 0"):
group[0] = 0.0
# The rejected depths weren't stored, so changing the offset still works
assert group[0] == (layer, 2.0)
group.offset = (10.0, 0.0)
assert layer.texture.offset == pytest.approx((5.0, 0.0))
Loading