“It is not enough for code to work.”
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship
Related Stack Overflow questions:
Making and using pygame sprites for donkey kong style game**
Why We Have to Use self.rect and self.image to Determine Rect and Surf on Sprites?
A pygame.sprite.Sprite
encapsulates an pygame.Surface
object and an pygame.Rect
object. It should have and an image
and a rect
attribute. image
stores the sprite and rect
stores the position and size of the sprite.
pygame.sprite.Group.draw()
and pygame.sprite.Group.update()
are methods which are provided by pygame.sprite.Group
.
The latter delegates to the update
method of the contained pygame.sprite.Sprite
s — you have to implement the method. See pygame.sprite.Group.update()
:
Calls the
update()
method on all Sprites in the Group. […]
The former uses the image
and rect
attributes of the contained pygame.sprite.Sprite
s to draw the objects — you have to ensure that the pygame.sprite.Sprite
s have the required attributes. See pygame.sprite.Group.draw()
:
Draws the contained Sprites to the Surface argument. This uses the
Sprite.image
attribute for the source surface, andSprite.rect
. […]
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill
. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won’t change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
If chased
is a pygame.sprite.Group
object, then you can get a list of pygame.sprite.Sprite
objects by the method sprites()
:
enemy = min([e for e in chased.sprites()],
key=lambda e: pow(e.x-entity.x, 2) + pow(e.y-entity.y, 2))
Related Stack Overflow questions:
📁 Minimal example - Text sprite
Related Stack Overflow questions:
A pygame.sprite.Group
is iterable. Hence you can go through the elements in a for
-loop:
for sprite in sprite_group:
# [...]
Alternatively, you can use the sprites()
method:
Return a list of all the Sprites this group contains.
Get a list of Sprites and access them by subscription:
sprite_list = sprite_group.sprites()
sprite_1 = sprite_list[0]
pygame.sprite.Group.draw
with special_flags
class MyGroup(pygame.sprite.Group):
def __init__(self, *args):
super().__init__(*args)
def draw(self, surface, special_flags=0):
for sprite in self:
surface.blit(sprite.image, sprite.rect, special_flags = special_flags)
Related Stack Overflow questions:
Related Stack Overflow questions:
You can get a list of pygame.sprite.Sprite
objects by the method sprites()
:
enemy = min([e for e in chased.sprites()], key=lambda e: pow(e.x-entity.x, 2) + pow(e.y-entity.y, 2))
Related Stack Overflow questions:
📁 Minimal example - Minimal sprite collide
📁 Minimal example - Minimal sprite collide (class)
Related Stack Overflow questions:
Related Stack Overflow questions:
How to make entities take damage with color collision in pygame?
![How to make entities take damage with color collision in pygame?
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
Can’t figure out how to check mask collision between two sprites
📁 Minimal example - Find the intersection of rotating sprites
Make a line as a sprite with its own collision in Pygame
📁 Minimal example - Find the intersection of sprites a nd line
pygame.sprite.collide_mask()
use the .rect
and .mask
attribute of the sprite object for the collision detection.
See the documentation of pygame.sprite.collide_mask()
:
Collision detection between two sprites, using masks.
collide_mask(SpriteLeft, SpriteRight) -> point
Tests for collision between two sprites, by testing if their bitmasks overlap. If the sprites have a “mask” attribute, that is used as the mask, otherwise a mask is created from the sprite image. Intended to be passed as a collided callback function to the *collide functions. Sprites must have a “rect” and an optional “mask” attribute.
Related Stack Overflow questions:
Changing colour of a surface without overwriting transparency
Related Stack Overflow questions:
Animated sprite from few images
c
For an animated Sprite a list of images (pygame.Surface
objects) must be generated. A different picture of the list is displayed in each frame, just like in the pictures of a movie. This gives the appearance of an animated object.
One way to get a list of images is to load an animated GIF (Graphics Interchange Format). Unfortunately, PyGame doesn’t offer a function to load the frames of an animated GIF. However, there are several Stack Overflow answers that address this issue:
One way is to use the popular Pillow library (pip install Pillow). The following function loads the frames of an animated GIF and generates a list of pygame.Surface
objects:
from PIL import Image, ImageSequence
def loadGIF(filename):
pilImage = Image.open(filename)
frames = []
for frame in ImageSequence.Iterator(pilImage):
frame = frame.convert('RGBA')
pygameImage = pygame.image.fromstring(
frame.tobytes(), frame.size, frame.mode).convert_alpha()
frames.append(pygameImage)
return frames
Create a pygame.sprite.Sprite
class that maintains a list of images. Implement an update method that selects a different image in each frame.
Pass the list of images to the class constructor. Add an index
attribute that indicates the index of the current image in the list. Increase the index in the Update
method. Reset the index if it is greater than or equal to the length of the image list (or use the modulo (%
) operator). Get the current image from the list by subscription:
class AnimatedSpriteObject(pygame.sprite.Sprite):
def __init__(self, x, bottom, images):
pygame.sprite.Sprite.__init__(self)
self.images = images
self.image = self.images[0]
self.rect = self.image.get_rect(midbottom = (x, bottom))
self.image_index = 0
def update(self):
self.image_index += 1
if self.image_index >= len(self.images):
self.image_index = 0
self.image = self.images[self.image_index]
📁 Minimal example - Animated sprites
repl.it/@Rabbid76/PyGame-SpriteAnimation
Related Stack Overflow questions:
How can you rotate an image around an off center pivot in PyGame
Related Stack Overflow questions:
How do I rotate a sprite towards the mouse and move it?
📁 Minimal example - Rotate Sprite to mouse
repl.it/@Rabbid76/PyGame-SpriteRotateToMouse
Related Stack Overflow questions:
Pygame mouse clicking detection
How can I add an image or icon to a button rectangle in Pygame?
Use the rect
attribute of the pygame.sprite.Sprite
object and the collidepoint
method to see if the Sprite was clicked.
Pass the list of events to the update
method of the pygame.sprite.Group
so that you can process the events in the Sprite class:
class SpriteObject(pygame.sprite.Sprite):
# [...]
def update(self, event_list):
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
# [...]
my_sprite = SpriteObject()
group = pygame.sprite.Group(my_sprite)
# [...]
run = True
while run:
event_list = pygame.event.get()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
group.update(event_list)
# [...]
Related Stack Overflow questions:
Pygame mouse clicking detection
How can I add an image or icon to a button rectangle in Pygame?
Detect evaluate the mouse states in the Update
method of the pygame.sprite.Sprite
object:
class SpriteObject(pygame.sprite.Sprite):
# [...]
def update(self, event_list):
mouse_pos = pygame.mouse.get_pos()
mouse_buttons = pygame.mouse.get_pressed()
if self.rect.collidepoint(mouse_pos) and any(mouse_buttons):
# [...]
my_sprite = SpriteObject()
group = pygame.sprite.Group(my_sprite)
# [...]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
group.update(event_list)
# [...]
Related Stack Overflow questions:
Drag multiple sprites with different “update ()” methods from the same Sprite class in Pygame
How to draw a chessboard with Pygame and move the pieces on the board??
Related Stack Overflow questions:
Related Stack Overflow questions:
Related Stack Overflow questions:
In general, you need to implement the duplicate
method and construct a new instance of the Sprite object in the method.
Another solution is to use the Python copy
module. deepcopy
can create a deep copy of an object. Unfortunately this cannot be used for pygame.sprite.Sprite
objects, as theimage
attribute is a pygame.Surface
, which cannot be copied deeply. Therefore, a deepcopy
of a Sprite will cause an error.
Unless you have nor any other attribute that needs to be copied deeply, you can make a shallow copy
of the Sprite. The rect
attribute is a pygame.Rect
object. The copy of the Sprite needs its own rectangle, so you have to generate a new rectangle instance. Fortunately a pygame.Rect
object can be copied by pygame.Rect.copy
:
import copy
new_d = copy.copy(d)
new_d.rect = d.rect.copy()
Related Stack Overflow questions:
Related Stack Overflow questions: