Sprite Game Programming

Manage Many Sprites on Game Window

In the “sprite_move_mouse_event.py” program, we saw how to move one sprite on the game window using mouse motion. In any game, several sprites are moving on the game window.

Let us write a sprite game program that manages several sprites.

Program’s Description

The program is very similar to the program “sprite_display_move_bounce.py” in the previous section.

It displays several sprites on the game window. The sprites move on their own on the screen. They bounce off the game window boundaries. A soccer ball image is used as the sprite.

The randint() function of the Python random module places the sprites randomly on the screen window when the program is started.

Thus the sprites appear on the game window at random locations. 

Knowing how to display and manage many sprites on the game window will prepare us for writing games involving a “player” sprite (controlled by the user keyboard) and many “alien” sprites moving randomly on the screen.

PROGRAM EXAMPLE: MANAGE MANY SPRITES

Program Name: C:\Users\ YourUserName \Python_scripts\sprite_move_many_sprites_bounce.py

Image Name: C:\Users\YourUserName\Python_scripts\sprite_images\ball.png

1  ############### PROGRAM TO DISPLAY AND MOVE MANY SPRITEs ################
2  # Program Name: sprite_many_sprites_bounce.py
3  # Image Name: ball.png
4  import pygame
5  from pygame.locals import *
6  import random
7  import os 
8  # os Module provides a portable way of using operating system dependent functionality.
9  ################  VARIABLES  ################
10  WIDTH = 640  # Width of game window (called 'screen')
11  HEIGHT = 480 # Height of the game window.
12  FPS = 60
13  # Set number of times per second the MAIN LOOP repeats. 
14  #
15  # define colors 
16  WHITE = (255, 255, 255)
17  BLACK = (0, 0, 0)
18  RED = (255, 0, 0)
19  GREEN = (0, 255, 0)
20  BLUE = (0, 0, 255)
21  #
22  ################  SETUP  ################
23  # initialize pygame and create game window and name it "screen".
24  pygame.init() # Start up pygame and initialize it. 
25  screen = pygame.display.set_mode((WIDTH, HEIGHT)) 
26  # "screen" is the game window of size defined in VARIABLES section.
27  pygame.display.set_caption("Many_Sprite Boundary Bounce") 
28  # Title that appears at the top of the game window
29  clock = pygame.time.Clock() 
30  # Call "Clock" method to create new ‘clock’ object.
31  # The clock object is the MAIN LOOP's clock.
32  # pygame.time.clock()is used in association with clock.tick() in step 15)
33  #
34  ################  OBJECTS  ################
35  ################  class ballSprite(pygame.sprite.Sprite):  ################
36  class My_sprite(pygame.sprite.Sprite): 
37      def __init__(self, step):
38          # "step" argument specifies how many pixels to move in each frame.
39          pygame.sprite.Sprite.__init__(self)
40          # set up asset folders
41          sprite_program_folder = os.path.dirname(__file__) 
42          sprite_img_folder = os.path.join(sprite_program_folder, 'sprite_images')
43          ball_img = pygame.image.load(os.path.join(sprite_img_folder, 'ball.png')).convert() 
44  #
45          self.image = ball_img 
46          self.image.set_colorkey(WHITE)  
47          self.rect = self.image.get_rect() 
48          self.step = [step, step] 
49  #        
50      def update(self):
51          self.rect = self.rect.move(self.step) 
52  #
53          if self.rect.right > WIDTH or self.rect.left < 0: # 
54              self.step[0] = -self.step[0]
55  #
56          if self.rect.bottom > HEIGHT or self.rect.top < 0: # 
57              self.step[1] = -self.step[1]
58  #    
59  step = 2 # means ballSprite moves 2 pixels each frame.
60  #
61  # Create a Group called all_sprites
62  all_sprites = pygame.sprite.Group()  # 
63  #
64  # Create (spawn) five instances of "My_Sprite" clsss.
65  # and name the instances "ballSprite".
66  for i in range(5):
67      ballSprite = My_sprite(step)  # 
68      ballSprite.rect.x = random.randrange(WIDTH - 50)
69      ballSprite.rect.y = random.randrange(HEIGHT - 100)
70      all_sprites.add(ballSprite) # Step 10b)
71  # Add all the sprite instances to all_sprite group.
72  #
73  ################  MAIN LOOP  ################
74  running = True
75  while running:
76     # This section of code checks the events queue for events initiated by the user.
77      for event in pygame.event.get():   
78          # Check if the user clicked the "X" on the window to exit the program.
79          # if "X" is clicked, set "running" = False and end the MAIN LOOP.
80          if event.type == pygame.QUIT: 
81              running = False
82          # Monitor events queue to check if the user presses the "q" key on the keyboard.
83          # If "q" key is pressed, set "running" to False and end the MAIN LOOP.
84          elif event.type == pygame.KEYDOWN: 
85              if event.key == ord('q'):
86                  running = False
87  #
88      # Call procedure "Update" to update the screen.
89      all_sprites.update()  
90  #
91      # Draw and render
92      screen.fill(BLUE) 
93      all_sprites.draw(screen)  
94  #    
95      # After drawing the screen Surface, call the pygame.display.flip() method.
96      # flip() method makes everything we have drawn on the screen Surface become visible    
97      pygame.display.flip() 
98  #    
99      clock.tick(FPS) 
100      # tick() method runs the loop at "step" defined in step 3) by statement FPS = 60. 
101  #
102  pygame.quit() 
103  # When the MAIN LOOP ends, pygame.quit() statement closes the window.
104  

Below is the output image of the program.

Sprite Game Manage Many Sprites in Sprite Group "all_sprites".
Output of sprite_move_many_sprites_bounce.py Program

Detailed Line-by-line Explanation of the Sprite Game Program Managing Many Sprites:

Most of the code in this program is the same as in the “sprite_display_move_bounce” program in the previous section. There is one change – import the Python random module.  The random module is discussed on Python Modules page.

Line 6: import random

The random module enables the program to start each sprite at a random location on the screen at the start of the game.

Lines 36 – 39:

36  class My_sprite(pygame.sprite.Sprite): 
37      def __init__(self, step):
38          # "step" argument specifies how many pixels to move in each frame.
39          pygame.sprite.Sprite.__init__(self)

Lines 36 – 39 define a parameter named “step”. The variable “step” defines the number of pixels the sprite will move in each frame (each loop of the Event Loop).

The variable “step” is initialized to “2” in line 59. Therefore the sprite will move 2 pixels in each frame.

Define update() Function

Lines 50 – 57:

50      def update(self):
51          self.rect = self.rect.move(self.step) 
52  #
53          if self.rect.right > WIDTH or self.rect.left < 0: # Step 9a)
54              self.step[0] = -self.step[0]
55  #
56          if self.rect.bottom > HEIGHT or self.rect.top < 0: # Step 9b)
57              self.step[1] = -self.step[1]

Lines 50 – 57 define a procedure named update(self). This procedure is called by the Event Loop in each repeat of the loop to update the position of the sprite. This procedure uses pygame’s rect.move(x,ymethod.  This method returns a new rectangle moved by a displacement (x,y) in each frame of the Event Loop.  For example, if (x,y) = (2,3), the sprite will move by 2 pixels in the x-direction and 3 pixels in the y-direction in each successive frame.

Create Sprite Group “all_sprites” to Include All Five Balls

Lines 66 – 70:

66  for i in range(5):
67      ballSprite = My_sprite(step)  
68      ballSprite.rect.x = random.randrange(WIDTH - 50)
69      ballSprite.rect.y = random.randrange(HEIGHT - 100)
70      all_sprites.add(ballSprite)

The code in these lines is different from the “sprite_display_move_bounce” program, which had only one sprite.   Since we are going to have five sprites instead of one, we first create a sprite group called “all_sprites” by calling Pygame.sprite.Group() method, which is the same as in “sprite_display_move_bounce” program.  

To get multiple sprites added to the Group, the program uses a for-range loop to instantiate five sprites of class My_sprite. This statement creates (spawns) an instance of “My_Sprite” class.  This instance is named “ballSprite”.

Initialize Position of Each Five Balls at Random Position Uisnf random.randrange() Function

Notice the program uses randrange function of random module in lines 68 -69.  The randrange function makes the position of each of the five sprites are initialized at random coordinates (x,y).  The x-coordinates of the five instantiated sprites are randomly selected between 0 and (WIDTH – 50) and the y-coordinate of the instantiated sprites are randomly selected between 0 and (HEIGHT – 100).

The last line (line 70) all_sprites.add(ballSprite is the same as in “sprite_display_move_bounce” program. It adds the five instantiated sprites to the “all_sprites” Group.

Rest of the lines of the code are same as “sprite_display_move_bounce” program.

Pygame Custom USEREVENT and time.set_timer() Function

We will use two additional pygame functions we have not used.  These are USEREVENT and pygame.time.set_timer().

User Events:

The programs so far have been using the events such as QUIT, keyboard events, mouse events, etc. These events are processed by the event handlers that are part of the Event Loop.

The Event Loop continues to check for any new events in the events queue in each frame. If the check finds any events in the events queue, the appropriate event handler processes the event.

How to Define Custom Events

Apart from the Pygame-defined internal events, Pygame provides a feature that lets the programmers define their custom events. You can name your custom event with a name of your choice.

The statement pygame.event.custom_type() makes a custom user event type and reserves a pygame.USEREVENT for custom use.

The statement below creates a custom user event type, and names it “eventID_a”.

eventID_a = USEREVENT + 1

This statement calls the pygame.USEREVENT method. To provide this event a unique ID, we add the number “1” to the keyword “USEREVENT”. Note that USEREVENT is a Pygame reserved word.

Now the custom event typeeventID_a” will appear in the Event Queue, whenever this custom event occurs.

But how does our program create custom events? And how does the program respond to the custom events? 

The answer is that the Pygame time module’s method can be used to create custom events repeatedly.

The programmer will write an Event Handler to process this custom event.

The section below discusses Pygame’s time module and its method set_timer().

Pygame time Module

Normally, in a game, you would like the custom events to occur at regular intervals.  As an example, in an aliens game, an alien may fire a trajectory every 100 milliseconds.

To make the custom events happen at regular time intervals, we use pygame.time module.

Note: The time in pygame is represented in milliseconds (1/1000th of a second).

pygame.time-set_timer() Method

Pygame.time module has a method called set_timer()

The pygame.time.set_timer() method creates an event on the event queue a specified number of milliseconds on the event type name specified in the custom event definition as below. The following statements will create an event of event type “eventID_a” every “x_milliseconds” on the Event Queue.

eventID_a = USEREVENT + 1
Pygame.time.set_timer(eventID_a, x_milliseconds)

If There Are More Custom User Events…..

If you have another custom event type (let us call it “eventID_b”) in your game that you would like to occur every “y”_milliseconds, you would write the following statements.

eventID_b = USEREVENT + 2
pygame.time.set_timer(eventID_b, y_milliseconds)

If you have more custom event types in your game, a code similar to the above example will be written.

Then Create The Event Handlers For the Custom User Event Types

Finally, you will write event handlers for each of the custom event types you have defined so that when any of these custom event types occur, the corresponding event handler will process the event appropriately. These event handlers will be part of the event loop.

An Example of An Event Handler for A Custom User Event Type

Below is a brief example of an event handler for event type named “FASTER”.

Let us assume your program requires that you increase the speed of the sprites by 5 every 500 milliseconds.  We will define a custom event type and name it “FASTER” by calling the pygame.USEREVENT method.  We add “1” to the keyword USEREVENT to make the event unique.

FASTER = pygame.USEREVENT + 1
Pygame.set_timer(FASTER, 500)

The event handler code will look like below: In the event loop, the code below continues to check the event queue using statement for event in pygame.event.get(): in each loop of the while statement. If the event type “FASTER” is present in the event queue, the set_timer() function calls “FASTER” every 500 milliseconds to increase the speed by 5.

The event handler code continues to check the event queue using the statement below in each loop of the while statement. Refer to the Program Example below.

for event in pygame.event.get(): 

If the event type “FASTER” is present in the event queue, the set_timer() function calls “FASTER” every 500 milliseconds to increase the speed by 5.

The following small excerpt of the program illustrate how to write an Event Handler for event type named “FASTER”.

PROGRAM EXAMPLE: CUSTOM USEREVENT and time.set_timer() FUNCTION

# Code Example on how to use USEREVENT
import pygame
from pygame.locals import *
pygame.init()
FASTER = USEREVENT + 1
pygame.time.set_timer(FASTER, 500)
running = True
move = 20
while running:
    for event in pygame.event.get():
        if event.type == FASTER:
            move = move + 5

This code calls pygame.USEREVENT to create the custom event type and name it “FASTER”. The statement adds the number “1” to the keyword USEREVENT to make the event type unique.  The code in the while loop checks for event type “FASTER” in the event queue. If the event type “FASTER” is present in the event queue, the time.set_timer() function calls “FASTER” every 500 milliseconds to increase the speed by 5.

Copyright © 2019 – 2024 softwareprogramming4kids.com

All Rights Reserved

Verified by MonsterInsights