PyGameExamplesAndAnswers

StackOverflow            reply.it reply.it

“It is not enough for code to work.”
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship


Sprite, Group and Sprite mask

Sprite

Related Stack Overflow questions:

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.Sprites — 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.Sprites to draw the objects — you have to ensure that the pygame.sprite.Sprites 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, and Sprite.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))

Text spritewhot

Related Stack Overflow questions:

📁 Minimal example - Text sprite

Sprite Groups

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]

Extend 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)

Layers and layered Group

Related Stack Overflow questions:

Render update Group

Related Stack Overflow questions:

Destroy (kill) Sprite objects

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))

Sprite collide

Related Stack Overflow questions:

📁 Minimal example - Minimal sprite collide

📁 Minimal example - Minimal sprite collide (class)

Sprite collide with Sprite

Related Stack Overflow questions:

User defined collide function

Related Stack Overflow questions:

Sprite collide with Group

Related Stack Overflow questions:

Group collide with Group

Related Stack Overflow questions:

Circular sprite collision

Related Stack Overflow questions:

Sprite collide with frame, window border and restrict to rectangle

Related Stack Overflow questions:

Bounding rectangle

Related Stack Overflow questions:

Sprite mask

Related Stack Overflow questions:

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.

Sprite chang color of area

Related Stack Overflow questions:

Animation, timing and Sprite sheet

Related Stack Overflow questions:

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

Animated sprite from few images

Rotate Sprite

Related Stack Overflow questions:

Follow mouse

Related Stack Overflow questions:

Click Sprite

Related Stack Overflow questions:

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)

    # [...]

Sprite on mouse hover

Related Stack Overflow questions:

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)

    # [...]

Drag Sprite

Related Stack Overflow questions:

Circular sprite

Related Stack Overflow questions:

Health Bar

Related Stack Overflow questions:

Copy (duplicate) sprites

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()

Text input

Related Stack Overflow questions:

Radio button

Related Stack Overflow questions:

📁 Minimal example - Radio button

repl.it/@Rabbid76/PyGame-RadioButton