I have an animation I need to play every time the mouse button is clicked.
I have the frames stored in a list, for every frame that Pygame renders, one frame in the list is blit
to the screen.
My issue is that because this happens every frame, the animation is played at 1000fps, even though there are only 8 frames, so the animation is unnoticeable. Is there any way to run the animation at 16fps while still allowing Pygame to run through the game loop at normal speeds? I have a game that needs to be run at Pygame's normal render speed but the animations should be played slower.
Here is an example of what I am currently doing:
pygame.init()
screen = pygame.display.set_mode((800, 600))
running = True
while running:
screen.fill('#000000')
mouse_pos = pygame.mouse.get_pos()
explosion = (pygame.image.load('assets/Explosion/E_1.png'), pygame.image.load('assets/Explosion/E_2.png'),
pygame.image.load('assets/Explosion/E_3.png'), pygame.image.load('assets/Explosion/E_4.png'),
pygame.image.load('assets/Explosion/E_5.png'), pygame.image.load('assets/Explosion/E_6.png'),
pygame.image.load('assets/Explosion/E_7.png'), pygame.image.load('assets/Explosion/E_8.png'))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
for frame in explosion:
framerect = frame.get_rect(center=mouse_pos)
screen.blit(frame, framerect)
pygame.display.update()
pygame.quit()
Actually, the animation is rendered in 1 frame because you render the animations in a for loop inside the application loop. You need to use the application loop. Limit the number of frames with pygame.time.Clock.tick
and load the frames once before the application loop to improve performance.
In the following example, clock.tick(100)
sets the frames per second, and animate_frames = 10
defines how many frames of animation will be displayed:
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
try:
explosion = (pygame.image.load('assets/Explosion/E_1.png'), pygame.image.load('assets/Explosion/E_2.png'),
pygame.image.load('assets/Explosion/E_3.png'), pygame.image.load('assets/Explosion/E_4.png'),
pygame.image.load('assets/Explosion/E_5.png'), pygame.image.load('assets/Explosion/E_6.png'),
pygame.image.load('assets/Explosion/E_7.png'), pygame.image.load('assets/Explosion/E_8.png'))
except:
explosion = []
for i in range(10):
e = pygame.Surface((100, 100), pygame.SRCALPHA)
pygame.draw.circle(e, (200 - i * 10, 200 - i * 20, 0), (50, 50), i*5)
explosion.append(e)
clock = pygame.time.Clock()
animate_frames = 10
animations = []
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
animations.append([event.pos, 0])
screen.fill('#000000')
for animation in animations[:]:
animation[1] += 1
frame_index = animation[1] // animate_frames
if frame_index < len(explosion):
frame = explosion[frame_index]
framerect = frame.get_rect(center=animation[0])
screen.blit(frame, framerect)
else:
animations.remove(animation)
pygame.display.update()
clock.tick(100)
pygame.quit()
Also see How can I show explosion image when collision happens?