Ok so for animation you need a bunch of images, and a timer.
I'm presenting some code snippets based around a pygame sprite. Maybe this doesn't exactly fit the question, but it seems like a better solution then painting/blitting images manually.
So first the code starts with a sprite class:
class AlienSprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.base_image = pygame.image.load('alien.png').convert_alpha()
self.image = self.base_image
self.rect = self.image.get_rect()
self.rect.center = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
# Load warp animation
self.warp_at_time = 0
self.warp_images = []
for filename in [ "warp1.png", "warp2.png", "warp3.png" ]:
self.warp_images.append( pygame.image.load(filename).convert_alpha() )
So the idea is the Alien Sprite has a "normal" image, but then when it "warps" (teleports) an animation plays. The way this is implemented is to have a list of animation images. When the animation starts, the sprite's image
is changed from base_image
to the first of the warp_images[]
. As time elapses, the sprites image is changed to the next frame, and then the next, before finally reverting back to the base image. By embedding all this into the sprite update()
function, the normal updating mechanism for sprites handles the current "state" of the alien sprite, normal or "warp". Once the "warp"-state is triggered, it runs without any extra involvement of the pygame main loop.
def update(self):
# Get the current time in milliseconds (normally I keep this in a global)
NOW_MS = int(time.time() * 1000.0)
# Did the alien warp? (and at what time)
if (self.warp_at_time > 0):
# 3 Frames of warp animation, show each for 200m
ms_since_warp_start = NOW_MS - self.warp_at_time
if ( ms_since_warp > 600 ):
# Warp complete
self.warp_at_time = 0
self.image = self.base_image # return to original bitmap
# Move to random location
self.rect.center = ( random.randrange( 0, WINDOW_WIDTH ), random.randrange( 0, WINDOW_HEIGHT ) )
else:
image_number = ms_since_warp // 200 # select the frame for this 200ms period
self.image = self.warp_images[image_number] # show that image
def startWarp(self):
# Get the current time in milliseconds (normally I keep this in a global)
NOW_MS = int(time.time() * 1000.0)
# if not warping already ...
if (self.warp_at_time == 0):
self.warp_at_time = NOW_MS
So the first thing to notice, is that the update()
uses the clock to know the number of elapsed milliseconds since the animation started. To keep track of the time I typically set a global NOW_MS
in the game loop.
In the sprite, we have 3 frames of animation, with 200 milliseconds between each frame. To start a sprite animating, simply call startWarp()
which obviously just kicks-off the timer.
SPRITES = pygame.sprite.Group()
alien_sprite = AlienSprite()
SPRITES.add(alien_sprite)
...
# Game Loop
done = False
while not done:
SPRITES.update()
# redraw window
screen.fill(BLACK)
SPRITES.draw(screen)
pygame.display.update()
pygame.display.flip()
if (<some condition>):
alien_sprite.startWarp() # do it
Obviously all those frame timings & what-not should be member variables of the sprite class, but I didn't do that to keep the example simple.