Warhost Warhost - 1 month ago 16
Python Question

Parallel display updates for Animations in pygame

I'm using pygame to create a game and it works so far.

However, I have included an animation of an explosion, by cycling through images I created from a spritesheet.
While this animation is running, everything else in the game stops, and only continues running after the animation is done:

class Explosion(Thread):
def __init__(self, coordinates):
Thread.__init__(self)
self.x, self.y = coordinates
self.explosionimgs = []
for i in range(0, 47):
self.explosionimgs.append(pygame.image.load("resources/explosion2/%d.png" % (i)))
self.explosionimg = self.explosionimgs[0]

def run(self):
for j in range (0,47):
screen.blit(self.explosionimgs[j], (self.x-80, self.y-80))
pygame.display.update()


Is there a way on how to make everything else in the game continue running while this is animation is taking place?

Answer

Is there a way on how to make everything else in the game continue running while this is animation is taking place?

Yes. Don't create another loop besides your game's main loop.

An easy way is to use pygame's Sprite class to represent a game object, because it nicely combines a Rect and a Surface and works easy with Groups.

Here's a silly simple runnable example. Note how everything keeps moving, while the Explosion class keeps chancing its image.

Just set your images from the spritesheet instead of using pygame.draw.circle:

import pygame
pygame.init()
screen = pygame.display.set_mode((600, 480))
clock = pygame.time.Clock()
run = True

class Explosion(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.surface.Surface((60, 60))
        self.rect = self.image.get_rect(center=pos)
        self.state = 0

    def update(self):
        self.state += 1
        self.image.fill((0, 0, 0))
        pygame.draw.circle(self.image, (200, 5 * self.state, 0), self.image.get_rect().center, self.state)
        if self.state > 30:
            self.kill()

class Ball(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.surface.Surface((40, 40))
        self.image.fill((60, 60, 200))
        self.rect = self.image.get_rect(center=pos)
        self.dir = 3

    def update(self):
        if not screen.get_rect().contains(self.rect):
            self.dir *= -1
        self.image.fill((self.rect.x % 255, 60, 200))
        self.rect.move_ip(self.dir, 0)

sprites = pygame.sprite.Group(Ball((200, 200)), Ball((100, 300)))
while run:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            run = False 
        if e.type == pygame.MOUSEBUTTONDOWN:
            sprites.add(Explosion(e.pos))

    screen.fill((0, 0, 0))
    sprites.draw(screen)
    sprites.update()
    pygame.display.flip()
    clock.tick(60)
Comments