Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3254 sprite group support source rect #3256

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 3 additions & 3 deletions buildconfig/stubs/pygame/sprite.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ _Group = AbstractGroup[_SpriteSupportsGroup]

# protocol helps with structural subtyping for typevars in sprite group generics
class _SupportsSprite(Protocol):
source_rect: Union[FRect, Rect]
@property
def image(self) -> Optional[Surface]: ...
@image.setter
Expand All @@ -47,14 +48,14 @@ class _SupportsSprite(Protocol):
class _SupportsDirtySprite(_SupportsSprite, Protocol):
dirty: int
blendmode: int
source_rect: Union[FRect, Rect]
visible: int
_layer: int
def _set_visible(self, val: int) -> None: ...
def _get_visible(self) -> int: ...

# concrete sprite implementation class
class Sprite(_SupportsSprite):
source_rect: Union[FRect, Rect]
@property
def image(self) -> Optional[Surface]: ...
@image.setter
Expand All @@ -78,10 +79,9 @@ class Sprite(_SupportsSprite):
def groups(self) -> list[_Group]: ...

# concrete dirty sprite implementation class
class DirtySprite(_SupportsDirtySprite):
class DirtySprite(Sprite, _SupportsDirtySprite):
dirty: int
blendmode: int
source_rect: Union[FRect, Rect]
visible: int
_layer: int
def _set_visible(self, val: int) -> None: ...
Expand Down
18 changes: 8 additions & 10 deletions docs/reST/ref/sprite.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ Sprites are not thread safe. So lock them yourself if using threads.
| :sg:`Sprite(*groups) -> Sprite`

The base class for visible game objects. Derived classes will want to
override the ``Sprite.update()`` and assign a ``Sprite.image`` and
``Sprite.rect`` attributes. The initializer can accept any number of Group
instances to be added to.
override the ``Sprite.update()`` and assign ``Sprite.image`` and
``Sprite.rect`` attributes. Optionally, they can assign a
``Sprite.source_rect`` attribute. The initializer can accept any number of
Group instances to be added to.

When subclassing the Sprite, be sure to call the base initializer before
adding the Sprite to Groups. For example:
Expand All @@ -82,6 +83,10 @@ Sprites are not thread safe. So lock them yourself if using threads.
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()

# source rect to use, remember that it is relative to
# topleft (0,0) of self.image
#self.source_rect = pygame.rect.Rect((0, 0), (width, height))

.. method:: update

| :sl:`method to control sprite behavior`
Expand Down Expand Up @@ -170,13 +175,6 @@ Sprites are not thread safe. So lock them yourself if using threads.

its the special_flags argument of blit, blendmodes

source_rect = None

::

source rect to use, remember that it is relative to
topleft (0,0) of self.image

visible = 1

::
Expand Down
24 changes: 15 additions & 9 deletions src_py/sprite.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ class Sprite:
When subclassing the Sprite class, be sure to call the base initializer
before adding the Sprite to Groups.

source_rect = None
This is the source rect to use. Remember that it is relative to the top
left corner (0, 0) of self.image.
"""

def __init__(self, *groups):
self.__g = {} # The groups the sprite is in
self.__image: Optional[pygame.surface.Surface] = None
self.__rect: Optional[pygame.rect.Rect] = None
self.source_rect = None
if groups:
self.add(*groups)

Expand Down Expand Up @@ -281,10 +285,6 @@ class DirtySprite(Sprite):
It's the special_flags argument of Surface.blit; see the blendmodes in
the Surface.blit documentation

source_rect = None
This is the source rect to use. Remember that it is relative to the top
left corner (0, 0) of self.image.

visible = 1
Normally this is 1. If set to 0, it will not be repainted. (If you
change visible to 1, you must set dirty to 1 for it to be erased from
Expand All @@ -305,7 +305,6 @@ def __init__(self, *groups):

# Default 0 unless initialized differently.
self._layer = getattr(self, "_layer", 0)
self.source_rect = None
Sprite.__init__(self, *groups)

def _set_visible(self, val):
Expand Down Expand Up @@ -564,11 +563,18 @@ def draw(self, surface):
sprites = self.sprites()
if hasattr(surface, "blits"):
self.spritedict.update(
zip(sprites, surface.blits((spr.image, spr.rect) for spr in sprites))
zip(
sprites,
surface.blits(
(spr.image, spr.rect, spr.source_rect) for spr in sprites
),
)
)
else:
for spr in sprites:
self.spritedict[spr] = surface.blit(spr.image, spr.rect)
self.spritedict[spr] = surface.blit(
spr.image, spr.rect, spr.source_rect
)
self.lostsprites = []
dirty = self.lostsprites

Expand Down Expand Up @@ -690,7 +696,7 @@ def draw(self, surface):
dirty_append = dirty.append
for sprite in self.sprites():
old_rect = self.spritedict[sprite]
new_rect = surface_blit(sprite.image, sprite.rect)
new_rect = surface_blit(sprite.image, sprite.rect, sprite.source_rect)
if old_rect:
if new_rect.colliderect(old_rect):
dirty_append(new_rect.union(old_rect))
Expand Down Expand Up @@ -866,7 +872,7 @@ def draw(self, surface):
init_rect = self._init_rect
for spr in self.sprites():
rec = spritedict[spr]
newrect = surface_blit(spr.image, spr.rect)
newrect = surface_blit(spr.image, spr.rect, spr.source_rect)
if rec is init_rect:
dirty_append(newrect)
else:
Expand Down
Loading