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
87 changes: 50 additions & 37 deletions arcade/sprite/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import TYPE_CHECKING, Iterable, List, TypeVar, Any

import arcade
from arcade.types import Point, Color, RGBA255, PointList
from arcade.types import Point, Color, RGBA255, RGBOrA255, PointList
from arcade.color import BLACK
from arcade.hitbox import HitBox
from arcade.texture import Texture
Expand Down Expand Up @@ -38,6 +38,7 @@ class BasicSprite:
"_color",
"_texture",
"_hit_box",
"_visible",
"sprite_lists",
"_angle",
"__weakref__",
Expand All @@ -49,6 +50,7 @@ def __init__(
scale: float = 1.0,
center_x: float = 0,
center_y: float = 0,
visible: bool = True,
**kwargs: Any,
) -> None:
self._position = (center_x, center_y)
Expand All @@ -57,6 +59,7 @@ def __init__(
self._width = texture.width * scale
self._height = texture.height * scale
self._scale = scale, scale
self._visible = bool(visible)
self._color: Color = Color(255, 255, 255, 255)
self.sprite_lists: List["SpriteList"] = []

Expand Down Expand Up @@ -293,29 +296,44 @@ def top(self, amount: float):

@property
def visible(self) -> bool:
"""
Get or set the visibility of this sprite.
This is a shortcut for changing the alpha value of a sprite
to 0 or 255::
"""Get or set the visibility of this sprite.

When set to ``False``, each :py:class:`~arcade.SpriteList` and
its attached shaders will treat the sprite as if has an
:py:attr:`.alpha` of 0. However, the sprite's actual values for
:py:attr:`.alpha` and :py:attr:`.color` will not change.

.. code-block:: python

# The initial color of the sprite
>>> sprite.color
Color(255, 255, 255, 255)

# Make the sprite invisible
sprite.visible = False
# Change back to visible
sprite.visible = True
# Toggle visible
sprite.visible = not sprite.visible
>>> sprite.visible = False
# The sprite's color value has not changed
>>> sprite.color
Color(255, 255, 255, 255)
# The sprite's alpha value hasn't either
>>> sprite.alpha
255

# Restore visibility
>>> sprite.visible = True
# Shorthand to toggle visible
>>> sprite.visible = not sprite.visible

"""
return self._color[3] > 0
return self._visible

@visible.setter
def visible(self, value: bool):
self._color = Color(
self._color[0],
self._color[1],
self._color[2],
255 if value else 0,
)
value = bool(value)
if self._visible == value:
return

self._visible = value

for sprite_list in self.sprite_lists:
sprite_list._update_color(self)

Expand Down Expand Up @@ -345,27 +363,22 @@ def color(self) -> Color:
return self._color

@color.setter
def color(self, color: RGBA255):
if len(color) == 4:
if (
self._color[0] == color[0]
and self._color[1] == color[1]
and self._color[2] == color[2]
and self._color[3] == color[3]
):
return
self._color = Color.from_iterable(color)

elif len(color) == 3:
if (
self._color[0] == color[0]
and self._color[1] == color[1]
and self._color[2] == color[2]
):
return
self._color = Color(color[0], color[1], color[2], self._color[3])
def color(self, color: RGBOrA255):
if color == self._color:
return

r, g, b, *_a = color

if _a:
if len(_a) > 1:
raise ValueError(f"iterable must unpack to 3 or 4 values not {len(color)}")
a = _a[0]
else:
raise ValueError("Color must be three or four ints from 0-255")
a = self._color.a

# We don't handle alpha and .visible interactions here
# because it's implemented in SpriteList._update_color
self._color = Color(r, g, b, a)

for sprite_list in self.sprite_lists:
sprite_list._update_color(self)
Expand Down
2 changes: 1 addition & 1 deletion arcade/sprite_list/sprite_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -1262,7 +1262,7 @@ def _update_color(self, sprite: SpriteType) -> None:
self._sprite_color_data[slot * 4] = int(sprite._color[0])
self._sprite_color_data[slot * 4 + 1] = int(sprite._color[1])
self._sprite_color_data[slot * 4 + 2] = int(sprite._color[2])
self._sprite_color_data[slot * 4 + 3] = int(sprite._color[3])
self._sprite_color_data[slot * 4 + 3] = int(sprite._color[3] * sprite._visible)
self._sprite_color_changed = True

def _update_size(self, sprite: SpriteType) -> None:
Expand Down
8 changes: 6 additions & 2 deletions tests/unit/sprite/test_sprite.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,19 @@ def test_visible():
assert sprite.alpha == 255
assert sprite.visible is True

# initialise alpha value
sprite.alpha = 100
assert sprite.alpha == 100

# Make invisible
sprite.visible = False
assert sprite.visible is False
assert sprite.alpha == 0
assert sprite.alpha == 100

# Make visible again
sprite.visible = True
assert sprite.visible is True
assert sprite.alpha == 255
assert sprite.alpha == 100


def test_sprite_scale_xy(window):
Expand Down