Pygame Tutorial Part#3 – Wrapping up our Game

Welcome to our Pygame Tutorial Part 3.

Game Creation Tutorial in Pygame – Part 3

This is a bit of an additional, and also optional section in our Python Pygame tutorial. In this section, we’re going to cover backgrounds, sound, fonts and a scoring system. These are all important features one needs in a game, to make it a complete product.

As usual, take a good look at the code below before proceeding to the block by block explanations.

#Imports
import pygame, sys
from pygame.locals import *
import random, time

#Initialzing 
pygame.init()

#Setting up FPS 
FPS = 60
FramePerSec = pygame.time.Clock()

#Creating colors
BLUE  = (0, 0, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

#Other Variables for use in the program
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
SPEED = 5
SCORE = 0

#Setting up Fonts
font = pygame.font.SysFont("Verdana", 60)
font_small = pygame.font.SysFont("Verdana", 20)
game_over = font.render("Game Over", True, BLACK)

background = pygame.image.load("AnimatedStreet.png")

#Create a white screen 
DISPLAYSURF = pygame.display.set_mode((400,600))
DISPLAYSURF.fill(WHITE)
pygame.display.set_caption("Game")

class Enemy(pygame.sprite.Sprite):
      def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("Enemy.png")
        self.rect = self.image.get_rect()
        self.rect.center = (random.randint(40, SCREEN_WIDTH-40), 0)  

      def move(self):
        global SCORE
        self.rect.move_ip(0,SPEED)
        if (self.rect.top > 600):
            SCORE += 1
            self.rect.top = 0
            self.rect.center = (random.randint(40, SCREEN_WIDTH - 40), 0)


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("Player.png")
        self.rect = self.image.get_rect()
        self.rect.center = (160, 520)
       
    def move(self):
        pressed_keys = pygame.key.get_pressed()
       #if pressed_keys[K_UP]:
            #self.rect.move_ip(0, -5)
       #if pressed_keys[K_DOWN]:
            #self.rect.move_ip(0,5)
        
        if self.rect.left > 0:
              if pressed_keys[K_LEFT]:
                  self.rect.move_ip(-5, 0)
        if self.rect.right < SCREEN_WIDTH:        
              if pressed_keys[K_RIGHT]:
                  self.rect.move_ip(5, 0)
                  
#Setting up Sprites        
P1 = Player()
E1 = Enemy()

#Creating Sprites Groups
enemies = pygame.sprite.Group()
enemies.add(E1)
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
all_sprites.add(E1)

#Adding a new User event 
INC_SPEED = pygame.USEREVENT + 1
pygame.time.set_timer(INC_SPEED, 1000)

#Game Loop
while True:
      
    #Cycles through all events occurring  
    for event in pygame.event.get():
        if event.type == INC_SPEED:
              SPEED += 0.5      
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    DISPLAYSURF.blit(background, (0,0))
    scores = font_small.render(str(SCORE), True, BLACK)
    DISPLAYSURF.blit(scores, (10,10))

    #Moves and Re-draws all Sprites
    for entity in all_sprites:
        DISPLAYSURF.blit(entity.image, entity.rect)
        entity.move()

    #To be run if collision occurs between Player and Enemy
    if pygame.sprite.spritecollideany(P1, enemies):
          pygame.mixer.Sound('crash.wav').play()
          time.sleep(0.5)
                   
          DISPLAYSURF.fill(RED)
          DISPLAYSURF.blit(game_over, (30,250))
          
          pygame.display.update()
          for entity in all_sprites:
                entity.kill() 
          time.sleep(2)
          pygame.quit()
          sys.exit()        
        
    pygame.display.update()
    FramePerSec.tick(FPS)

Explanation

#Setting up Fonts
font = pygame.font.SysFont("Verdana", 60)
font_small = pygame.font.SysFont("Verdana", 20)
game_over = font.render("Game Over", True, BLACK)

First up is the fonts. In the code above, we’re setting the fonts to be used later on in our program. We create two different fonts, font and font_small which both have the same font family, but different font sizes.

Next we use the render() function to actually create the graphics for the Font of our choice. We also have to pass in the text we wish to be displayed and the color we want it to be in. In this case, “Game Over” and BLACK respectively.

(You can learn more about Pygame fonts here, if you don’t understand the above code)

#Game Loop
while True:

     scores = font_small.render(str(SCORE), True, BLACK)
     DISPLAYSURF.blit(scores, (10,10))
     ...
     ...
     ...

     if pygame.sprite.spritecollideany(P1, enemies):
          ...
          ...
          DISPLAYSURF.blit(game_over, (30,250))

This is the second part of our fonts. You can see us rendering another font called scores. We didn’t do this earlier because this font is meant to be rendered inside Game loop as it has a continuously changing value. We moved the game_over font rendering out of the loop to avoid unnecessary performance loss.

Finally, we display both fonts using the blit() function. In it’s first parameter we pass the rendered font and in the second we pass a pair of co-ordinates which mark the origin point of the font.

background = pygame.image.load("AnimatedStreet.png")

...
...
...
...

while True:
     ...
     ...
     DISPLAYSURF.blit(background, (0,0))

     ...
     ...
     
     #Moves and Re-draws all Sprites
     for entity in all_sprites:
        DISPLAYSURF.blit(entity.image, entity.rect)
        entity.move()

There are two steps to creating a background. First you load the image (outside the game loop for performance) and then proceed to draw the image using the blit() function. The blit() function must be in the game loop as it needs to re draw itself as the other objects move.

What’s also important, is that the background is the first thing that’s drawn. Pygame has a layer system, where if you aren’t careful, you will draw the background over all the other sprites. Basically it’s like painting. If you draw the Player on the street, it’s ok. But if you draw the street over the player, it’s a problem.

    #To be run if collision occurs between Player and Enemy
    if pygame.sprite.spritecollideany(P1, enemies):
          pygame.mixer.Sound('crash.wav').play()
          time.sleep(0.5)
                   
          DISPLAYSURF.fill(RED)
          DISPLAYSURF.blit(game_over, (30,250))

Here we are using a simple one line function from the Pygame Mixer library to play a crash sound once collision has occurred. Pygame.mixer.Sound() is used to load the sound into Pygame, while play() is used to actually “play” it.

(For longer music tracks, there is a separate function. Be sure to check out the Pygame Mixer Tutorial if you want to learn how to do that)


Pygame Tutorial – Final Output

Finally, here’s the result of all our hard work and code. We’ve uploaded a short video of our code running for you people to see. Of course, we recommend that you actually try running the code for yourself and playing the game.

As promised, here’s a download link to the images and the code used for this tutorial.

Pygame Tutorial Materials Download (14047 downloads)

Other Areas of Improvement

Now obviously, we could have gone alot further with this game. But we’ll stop here and just leave some ideas for you guys to practice and implement on your own.

  • Multiple enemies spawning after set periods of time. (Similar to how we increased speed after a set period of time)
  • Adding some additional audio to the game, such as background music and movement sounds (audio that plays when you move the character)
  • Adding the concept of multiple Lives or a Health bar.
  • Variations in the shape and size of the “enemies”.

Other Pygame Resources

Some of the things we didn’t cover (fully) in this Tutorial are listed below, where we’ve covered them properly in other articles. If you’re interested in learning more about Python Pygame and making your games look better, make sure you read them.

  1. Pygame Font and Text
  2. Pygame Audio Mixer
  3. Pygame UserEvents
  4. Pygame Platformer Series
  5. Pygame RPG Tutorial Series

If you’re into reading books, we have a compilation of best books on Game Development, which you can read. Its a great choice for Pygame programmers looking to take things to next level.


This marks the end of the Python Pygame Tutorial, Part 3. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the Tutorial can be asked in the comments section below.

Subscribe
Notify of
guest
11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments