Drawing sprites (Intermediate)

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.

How to do it...

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.

  1. Constructor: First, we need to create the sprite and perform subclassing. All the initialization logic goes here. Further details for the functions can be found in the next section. We define an image, rectangle, and variables tracking the movement of the avatar:
    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'
  2. The update method: The 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)
    

    Note

    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:

    How to do it...

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

How it works...

A more in-depth description of the various functions used in this demo is given as follows:

Function

Description

pygame.sprite.Sprite.__init__(self)

This creates sprites.

screen.get_rect()

This gets a Rect object.

pygame.display.get_surface()

This gets a Surface object.

self.rect.move((self.xstep, self.ystep))

This moves a rectangle given a x and y coordinate.

pygame.transform.rotate(self.original, self.degrees)

This rotates an image given a Surface object and angle in degrees. Positive values correspond with counter clockwise rotation, negative with clockwise rotation.

self.image.get_rect(center=center)

This gets the rectangle for the image given its center coordinates.

pygame.sprite.RenderPlain(head)

This renders the sprite.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset