Sprite is a term from computer graphics meaning a two-dimensional visible object, that has been optimized for rendering. Pygame offers the Sprite
class that deals with sprites. It can draw sprites on a Surface
object. It also has collision functions. For complex games, we can group sprites together for easy management. Sprites are not thread safe, so you should take care when using multiple threads.
We will redo the animation demo, but this time with sprites and using Rect
objects, which represent rectangles. A Rect
object has left
, top
, width
, and height
attributes. We will use these and other attributes throughout the example. Also we will let the avatar spin when the mouse button is clicked. However, we will not care for now where we click exactly.
We will create a class that extends the Sprite
class. Sprite classes have an update
method which fires for each frame. All logic involving the movement of the sprite should be placed here.
class Head(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image, self.rect = load_image('head.jpg', -1) screen = pygame.display.get_surface() self.area = screen.get_rect() self.STEP = 9 self.MARGIN = 12 self.xstep = self.STEP self.ystep = 0 self.dizzy = 0 self.direction = 'right'
update
method calls helper methods that either cause the head to spin or move it in clockwise direction. The movement is achieved with this line:newpos = self.rect.move((self.xstep, self.ystep))
The following line take care of the rotation:
self.image = pygame.transform.rotate(self.original, self.degrees)
You can find a short clip of the game on YouTube (https://www.youtube.com/watch?v=EFQlc_siPrI). A screenshot of the game is shown as follows:
The complete code of the Sprite demo is listed as follows:
import os, pygame from pygame.locals import * def load_image(name, colorkey=None): try: image = pygame.image.load(name) except pygame.error, message: print 'Cannot load image:', name image = image.convert() return image, image.get_rect() class Head(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image, self.rect = load_image('head.jpg', -1) screen = pygame.display.get_surface() self.area = screen.get_rect() self.STEP = 9 self.MARGIN = 12 self.xstep = self.STEP self.ystep = 0 self.degrees = 0 self.direction = 'right' def update(self): if self.degrees: self._spin() else: self._move() def _move(self): newpos = self.rect.move((self.xstep, self.ystep)) if self.direction == 'right' and self.rect.right > self.area.right - self.MARGIN: self.xstep = 0 self.ystep = self.STEP self.direction = 'down' if self.direction == 'down' and self.rect.bottom > self.area.bottom - self.MARGIN: self.xstep = -self.STEP self.ystep = 0 self.direction = 'left' if self.direction == 'left' and self.rect.left < self.area.left + self.MARGIN: self.xstep = 0 self.ystep = -self.STEP self.direction = 'up' if self.direction == 'up' and self.rect.top < self.area.top + self.MARGIN: self.xstep = self.STEP self.ystep = 0 self.direction = 'right' self.rect = newpos def _spin(self): center = self.rect.center self.degrees = self.degrees + 12 if self.degrees >= 360: self.degrees = 0 self.image = self.original else: self.image = pygame.transform.rotate(self.original, self.degrees) self.rect = self.image.get_rect(center=center) def hit(self): if not self.degrees: self.degrees = 1 self.original = self.image def main(): pygame.init() screen = pygame.display.set_mode((400, 400)) pygame.display.set_caption('Sprite Demo') background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((250, 250, 250)) if pygame.font: font = pygame.font.Font(None, 36) text = font.render("Hit the avatar!", 1, (0, 0, 200)) textpos = text.get_rect(centerx = background.get_width()/2, centery = background.get_height()/2) background.blit(text, textpos) screen.blit(background, (0, 0)) pygame.display.flip() clock = pygame.time.Clock() head = Head() sprite = pygame.sprite.RenderPlain(head) while True: clock.tick(60) for event in pygame.event.get(): if event.type == QUIT: return elif event.type == MOUSEBUTTONDOWN: head.hit() sprite.update() screen.blit(background, (0, 0)) sprite.draw(screen) pygame.display.flip() if __name__ == '__main__': main()
A more in-depth description of the various functions used in this demo is given as follows:
Function |
Description |
---|---|
|
This creates sprites. |
|
This gets a |
|
This gets a |
|
This moves a rectangle given a |
|
This rotates an image given a |
|
This gets the rectangle for the image given its center coordinates. |
|
This renders the sprite. |