Sprite Game Programming

Developing A Sprite Game

The basic steps to write a Sprite game are 1) write the game objects by creating a class for each type of object in your game 2) write a function update().

The programs on this page explain these steps in great detail.

Before we start, you should be familiar with the basic structure of a Pygame program. Refer to the Pygame page for a review of the basic Pygame program structure.

The section below explains the Program Structure of a Sprite Game.

Sprite Game Program Structure

All sprite games use the program structure described below.

Import modules:

  • Import Pygame module.
  • Import pygame locals constants variables using statement from pygame.locals import *
  • Import os module.

Define Program Variables:

Define program variables such as

  • width and height of the screen
  • color tuples
  • FPS, which is the speed at which your game runs (frames per second).

Game Set-up:

  • Make a function call to pygame.init function that initializes all pygame modules that we imported.
  • Create a screen object of the width (w) and height (h) defined in the Variable definition section of the program by calling pygame.display.set_mode((w, h)) function.
  • Define the title of the game window by calling pygame.display.set_caption() function. 
  • Create a new Clock object by calling pygame.time.Clock() function.  This function creates a new Clock object that can be used to track an amount of time. The clock also provides several functions to help control a game’s frame rate. One of the Clock objects function is clock.tick() method that defines the frame rate, which is the number of times the Event Loop (Main Loop) iterates per second. The Clock object is the EVENT LOOP’s clock.

Game Objects (Create a Class)

After you have created the basic Pygame program structure, the first step is to write the game objects

You do this by creating a class for each type of object in your game. You create a class by using the statement below.

Class classname(pygame.sprite.Sprite):

Where classname is any name of your choosing.

We will use the soccer ball image in one of the programs in a later section. So, our class definition statement will be:

Class ball(pygame.sprite.Sprite):

The ball class gets all of the functions that come with the Sprite class. 

Later in the program, when you will create instances of the ball class, the instantiated objects will be sprite objects.

Functions in Class Definition

In the class definition, you write all the functions for your object.

  • __init__

The first function you write is  __init__, which defines the object’s attributes such as size or any other attribute of the class.  The statement is as follows:

def __init__(self, attribute1, attribute2, …):
               pygame.sprirte.Sprite.__init__(self)

Notice the first parameter in the def __init__ statement is “self”. This is required.

Then, you instantiate an object of the class. In our example, the instantiated object will be a ball object. It will be a Sprite object and will inherit the Sprite class.  This is referred to as class inheritance.  This will then enable you to use that class’s methods for these objects. The object instantiation statement is as below.

Ball = Ball()
  • update() Function

The second function you write is the update() function.  The update() function moves the object to a new location in each iteration of the Main Loop’s frame update.

You may also include logic in the update() function to provide interactivity for the user’s keypresses, mouse clicks, and custom USEREVENT.

The update() function is called by the Main Loop once in each frame.

Note: the USEREVENT is described in a later section.

  • Your game may require more functions.  You will create these as needed.

Create More Classes As Needed:

If your game has more objects such as aliens, baseball bats, rockets, etc., you will create a class for each of these types of objects, create an instance of the class, and write the __init__ function and the update() function for each of these objects as described above.

Blitting:

After creating the game objects, the next step is to display the objects on the display screen. Blitting copies the pixels from the object to the screen.  Without blitting, the screen will appear blank.

The Event Loop (also called Game Loop or Main Loop):

Note: The words Main Loop, Event Loop, and Game Loop have the same meaning and are used interchangeably.  

The Event Loop runs the program continuously at the frame rate (fps) that you specified in the Program Variable Definition section of the program. 

The Event Loop starts with a while True: statement. 

The Event Loop‘s function is to update the position of the sprite in each successive frame based on the position of the sprite in the previous frame.

The Event Loop also monitors the Event Queue, which contains the list of events created by the player using the keyboard or mouse. The program accesses the Event Queue by using the method below:

pygame.event.get()

and checks if the user has created any events through keypresses, mouse motions, or mouse clicks. If any event is detected, the Event Handler takes appropriate action. The program loops through the event list in the Event Queue every frame checks each event type, and responds accordingly.

The Event Handler:

If there are any events in the Event Queue, the Event Handler processes those event requests.  For example, if the user clicks on the ‘X’ on the game window (QUIT constant variable), the Event Handler will terminate and close the game window. Or if the user presses the LEFT arrow key on the keyboard, the sprite image will move left. 

Based on the user-initiated events, the Event Loop updates the position of the sprite, creates a sound, or something else as per the code in the Event Handler that you write.  This happens on a per-frame basis at a frame rate defined by the FPS variable in the Program Variable definition section of the program.

Each cycle of the Event Loop is called a frame. 

The higher the FPS value, the faster the game plays and the faster the sprites move.

Sprite Game Roadmap For The Rest of The Page

The next sections develop simple sprite game programs to learn about sprite game programming.

We will gradually increase the program complexity to reach the goal of finally developing a sprite game.

We will develop the following programs.

  1. First, we develop a program to display a sprite.
  2. Next, we will develop a program to move a sprite on its own.
  3. Develop a program to move a sprite using keyboard events.
  4. Develop a program to move a sprite using mouse events
  5. Develop a program to display multiple sprites on the screen.
  6. Develop a program to create a “Player” Sprite and an “Enemy” sprite, and collision detection. The person playing the game (user) moves the “player” sprite using the keyboard or mouse. The user tries to move the “player” sprite to collide with the “alien” sprites.  In this program, we will make use of the collision detection function of sprites.
  7. Add sound effects to the game

Let us now write our first Sprite program. This program will display a sprite (with no motion).

Display a Sprite

The program below uses the image of the space shuttle as the sprite. The Pygame’s sprite module is used to display the space shuttle.

PROGRAM EXAMPLE: DISPLAY A SPRITE IMAGE

Program Folder: C:\Users\YourUserName\Python_scripts\Sprite_Space_Shuttle_Display.py

Image Folder: C:\Users\YourUserName\Python_scripts\sprite_images\SpaceShuttle.png

1  ################ PROGRAM HOW TO DISPLAY A SPRITE ################
2  # Program Name: sprite_Space_Shuttle_Display.py
3  # Image Name: SpaceShuttle.png
4  import pygame
5  from pygame.locals import *
6  import os
7  #os Module provides a portable way of using operating system dependent functionality.
8  
9  ################  VARIABLES  ################
10  w = 200 # Width of window called "screen".
11  h = 200  # Height of screen
12  #  fps = Number of times the MAIN LOOP repeats every second. #3
13  fps = 60
14  #
15  # Define Colors 
16  BLACK = (0, 0, 0)
17  WHITE = (255, 255, 255)
18  RED = (255, 0, 0)
19  BLUE = (0, 0, 255)
20  CYAN = (0, 255, 255)
21  GRAY = (128, 128, 128)
22  
23  ################  SETUP  ################
24  # Initialize pygame and create window and name it "screen".
25  pygame.init()  # Intialize Pygame.
26  screen = pygame.display.set_mode((w, h)) 
27  # "screen" is display window of specified width (w) and height (h).
28  pygame.display.set_caption('SpriteshuttleDisplay') # Step 6a)
29  # Title of Display Window that appears on top of the screen window.
30  clock = pygame.time.Clock() 
31  # Call "Clock" method to create new ‘clock’ object.
32  # The clock object is the MAIN LOOP's clock.
33  # pygame.time.clock()is used in association with clock.tick() in step 15.
34  #
35  x = 25  # Initialize (x,y) coordinate of shuttle position to (25, 40)
36  y = 40
37  #
38  ################  OBJECTS  ################
39  class My_sprite(pygame.sprite.Sprite):  
40      def __init__ (self):
41          pygame.sprite.Sprite.__init__(self)
42          self.image = Shuttle_img
43          self.image.set_colorkey(WHITE) 
44          self.rect = self.image.get_rect() 
45  
46  ##### Set up asset folders  ######
47  sprite_program_folder = os.path.dirname(__file__) # Step 8a)
48  sprite_img_folder = os.path.join(sprite_program_folder, 'sprite_images') 
49  Shuttle_img1 = pygame.image.load(os.path.join(sprite_img_folder, 'SpaceShuttle.png')) # Step 8b)
50  Shuttle_img = Shuttle_img1.convert() 
51  # SpaceShuttle.png image is in "sprite_images" folder.    
52  #
53  #####  DEFINES  #####
54  # This procedure sets the position of space shuttle on the screen.
55  # The blit() method copies shuttle Surface object data
56  # onto "screen" Surface object.  
57  def shuttlePosition(x, y):
58      screen.blit(Shuttle_img, (x, y))
59  
60  # Create an instance of class "My_sprite"
61  # and call this instance (object) "spaceShuttle".
62  spaceShuttle = My_sprite()  # Step 10)
63   
64  ################  MAIN LOOP  ################
65  running = True
66  while running:
67          # This section of code listens for events initiated by the user.
68      for event in pygame.event.get(): 
69          # Check if the user clicks the "X" on window.
70          # If "X" is clicked, set "running" to False and end the MAIN LOOP.
71          if event.type == pygame.QUIT:  
72              running = False
73          # Monitor the event queue to check if the user presses the "q" key on the keyboard.
74          # If "q" key is pressed, set "running" to False and end the MAIN LOOP.        
75          elif event.type == pygame.KEYDOWN: 
76              if event.key == ord('q'):
77                  running = False
78        #      
79      screen.fill(CYAN) 
80      shuttlePosition(x, y)  #  Call procedure shuttlePosition(x,y). Step 13
81      pygame.display.update() 
82      clock.tick(fps) 
83      # tick() command runs the MAIN LOOP at the speed defined in step 3) by statement FPS = 60.  
84      #
85  pygame.quit()  
87      # When the MAIN LOOP ends, pygame.quit() statement closes the screen window.
Sprite Game Display a Sprite
Display a Sprite Using Image of Space Shuttle

Detailed Line-by_line Explanation of the Sprite Game Program to Display a Sprite:

We start with importing the modules.

Import Modules

Line 4: import pygame

Before you can use pygame, you need to import the pygame module.

Line 5: from pygame.locals import *

The pygame.locals module contains 280 constants. One of them QUIT. This step imports all these constants. The QUIT constant is used in line 71 to shut down the game window when the “X” on the window is clicked.

Line 6: import os

 The os module provides a portable way of using operating system-dependent functionality. Refer to the Python os Module page for details on os module.

Next, we define the program variable.

Define Program Variables:

Lines 10 – 11:  w = 200   

          h = 200

Set the width (w) and height (h) of game window (“screen”) defined in step 2.

Line 13:      fps = 60

fps means frames per second. When we set fps = 60, the MAIN LOOP repeats 60 times per second. fps is used in line 82) below.

For details on fps and frame rate, refer to the section Enrichment: More About Colors.

Line 15 – 21:    This step defines color tuples.

Refer to Enrichment: Colors in Computers for more details.

Game Set-up

Line 25: pygame.init()

pygame.init function initializes all pygame modules that we imported in lines 4). pygame.init() must be called after importing the pygame module.

Line 26: screen = Pygame.display.set_mode(w,h))

When we call the set_mode() method, it returns a pygame.surface object window (screen) with dimensions (w, h) with its width = w and height = h.  The display.set_mode() method sets the screen width and height as defined in lines 10 and 11.

Line 28: pygame.display.set_caption('SpriteshuttleDisplay')

The pygame.display.set_caption() method sets the current window’s caption that appears on the window border. The title of the screen window is “SpriteShuttleDisplay” in this program.

Line 30: clock = pygame.time.Clock()

This line calls pygame.time.clock() method to create a new “Clockobject. This method sets the MAIN LOOP’s clock. This clock object is the MAIN LOOP’s clock. 

The pygame.time.clock() is used in association with the clock.tick() method in line 82).

Create Game Objects (Class Definition)

#39   class My_sprite(pygame.sprite.Sprite):

Generate a new class and name it “My_sprite” based on the Pygame base class pygame.sprite.

Line 40: def __init__ (self):

In the class definition, we first use a method (__init__) method. It is called the class constructor. The __init__ method specifies what code is run when we define a new object based on this class. When the object belonging to the class is created, the constructor initializes the properties of the object (such as x-position, y-position, color, etc.).

Lines 41 – 44:

        pygame.sprite.Sprite.__init__(self)
        self.image = Shuttle_img
        self.image.set_colorkey(WHITE)
        self.rect = self.image.get_rect()

Line 41: pygame.sprite.Sprite.__init__(self)

In all programs, the statement below is required by Pygame. This statement runs the Sprite class initializer.

pygame.sprite.Sprite.__init__(self) 

Set the Sprite Image

Line 42: self.image = Shuttle_img

Sets the sprite image (Shuttle_img). 

Line 43: self.image.set_colorkey(WHITE)

Sets the colorkey to make the pixels transparent in the rectangle that contains the image.  Refer to the Python os Module page for details on colorkey operation.

Line 44: self.rect = self.image.get_rect()

Calls get_rect() method to create the rectangle that contains the Shuttle_img. The get_rect() method returns a Rect object, which is a rectangle that provides the bounds of the image.

Refer to the Pygame page for more details on the get_rect method.

Set-up Asset Folders

Lines 47 – 48:  The code in these lines sets up the asset folders indicating the directory where our Python program is stored and the directory where the sprite image is stored.

Sprite Program Folder (Use os.path-dirname command)

Line 47: sprite_program_folder = os.path.dirname(__file__)

Python provides a variable called __file__ that refers to the directory where your python programs are stored. In this program example, our Python .py program is stored in the directory “sprite_program_folder”.

Tell the Program the Location of Image Folder (os.path.join command)

Line 48:  sprite_img_folder = os.path.join(sprite_program_folder, 'sprite_images')

The sprite image used in this program is stored in the directory “sprite_images”. The os.path.join method joins one or more path components. The return value is the concatenation of path components and exactly one directory separator  “\”.

Refer to the Python OS Module page for details of the usage of os.path.join method.  This code line joins the “sprite_program_folder” directory and “sprite_images” directories with a “\” in between the two. We use os.path.join method to join all the path components.

Line 49: Shuttle_img1 = pygame.image.load(os.path.join(sprite_img_folder, 'SpaceShuttle.png'))

Line 49 makes a function call to pygame.image.load() method with the image name (“SpaceShuttle.png”) that is stored in “sprite_img_folder” specified as an argument within the parenthesis. The load function takes a filename (SpaceShuttle.png) and returns a new Surface with the loaded image.  This Surface is named “Shuttle_img1”.

Line 50:  Shuttle_img = Shuttle_img1.convert()

After loading the image, this line makes a call to the Surface method, convert().

convert() returns us a new Surface of the image, but converted to the same pixel format as our display. Since the images will be in the same format as the screen, they will blit very quickly. The convert () method makes the blitting faster.

Define Function to Initialize Shuttle Position

Line 57 – 58:

def shuttlePosition(x, y):
     screen.blit(Shuttle_img, (x, y))

These lines of code define a procedure named shuttlePosition(x, y). This procedure initializes the space shuttle position on the screen. The blit() method copies the shuttle Surface object data onto the “screen” Surface object.

Object Instantiation

Line 62: spaceShuttle = My_sprite()

This statement creates an object instance of class “My_sprite” and names it “spaceShuttle”. This instantiated object “spaceShuttle” belongs to the My_sprite()class.

The Main Loop

Line 65 – 68:

running = True
while running:
      for event in pygame.event.get():

These lines of code create a while loop that continues to check the Event Queue for any events created by the user such as mouse clicks or keyboard presses.

Check for Events

Line 71 – 72:

if event.type == pygame.QUIT:
running = False

If the user clicks the “X” on the screen window, this statement sets the variable “running” to False and ends the MAIN LOOP. Here, we use the QUIT constant that we imported by the below statement (line 5).

from pygame.locals import *

Line 75 – 77:

elif event.type == pygame.KEYDOWN:
        if event.key == ord('q'):
            running = False

The above lines of code monitor the Event Queue to check if the user presses the “q” key on the keyboard. If the “q” key press event is detected, this statement sets the variable “running” to False, closes the game window, and ends the MAIN LOOP.

The code in lines 71-77 continuously monitors for the events initiated by the user such as clicking the “X” on the window or hitting the “q” key on the keyboard. If either of these events occurs, the program sets the variable “running” = False and the game ends.

Line 79: screen.fill(CYAN)

Apart from checking the Events Queue, the first step in the while loop is to fill the display screen with color by using the function screen.fill().

Call the Function shuttlePosition(x,y)

Line 80: shuttlePosition(x, y)

This is a call to procedure “shuttlePosition(x,y)” defined in lines 57 – 58. This procedure initializes the (x,y) coordinate of the shuttle to (25, 40).  Coordinates (x,y) = (25, 40) are defined in lines 35 and line 36.

Update the Screen Surface At Each Loop of the Program

Line 81: pygame.display.update()

This function allows the screen Surface to be updated at each iteration of the loop. Note that nothing is drawn to the display screen until this function pygame.display.update() is called.

Make a Call to Fumction clock.tick() to Make The LoopRun at 60 Frames per Second

Line 82: clock.tick(fps)

The call to tick() method makes the MAIN LOOP run at the speed defined in line 13 by the statement fps = 60. 

The tick() method tells Pygame to run the loop and after one loop is finished, pause until 1/60th second is over, before starting the next repeat of the loop, so that each loop finishes in 1/60th of a second.            

Line 85: pygame.quit()

This line un-initializes all pygame modules that had previously been initialized in line 25). When the MAIN LOOP ends, pygame.quit() statement destroys the game window. The pygame.quit() is the event that happens when the ‘X’ is clicked on the screen window.  When “X” is clicked, the program sets the variable “running” to False and the game loop will end.

Verified by MonsterInsights