Basic Sprite Concepts
Pygame has a module called sprite
, which allows the programmer to move the image of objects as a unit. The sprite module includes higher-level classes to manage and draw the game objects.
The sprite module comes with two main classes. The first is Sprite, which should be used as a base class for all your game objects. This class includes several functions to help manage the game objects.
The other type of class is Group. The Group class is a container for different Sprite objects. (Discussed below).
The Sprite Class
The Pygame
module provides a Sprite class
. The Sprite class can hold one or many images of different game objects that the programmer desires to display on the screen. The pygame sprite module has a base class called pygame.sprite.
The base class is not used as is. You create your own sub-class using pygame.sprite.Sprite function. Recall that the class definition is just a template. To use this class, you need to instantiate the objects based on this class definition. Once you instantiate the objects, you can use methods associated with the class.
What is the __init__ Function
Python has a built-in function called __init__() function. This section explains what the __init__() function is used for.
The __init__()
function is what are called constructors. The constructors have a set of statements that initialize (assign values) to the object’s properties when an object of a class is instantiated (created). That is, the __init__()
function is used to assign values to the object’s properties (attributes). The __init__()
function is always executed when an object of a class is instantiated.
The examples below illustrate how the __init__()
function is used to define a class, instantiate objects of the class, and assign objects’ properties (attributes).
PROGRAM EXAMPLE: __init__ FUNCTION FOR CLASS DEFINITION
Program Name: class.py
# __init__ function usage in class definition.
# The examples below instantiate the objects of a class,
# The example assigns values to object's properties.
# EXAMPLE 1:
class ball:
def __init__(self, color, diameter): # "color" and "diameter" are class properties.
self.color = color
self.diameter = diameter
# Instantiate an object of the class "ball" and name this object "myBall".
myBall = ball("RED", "6 inches") # Instantiate an object of the class "ball".
# “RED” and “6 inches” are passed as arguments to __init__ method
# to assign values to the objects' properties.
# Now print myBall's object's properties.
print(myBall.color, myBall.diameter, "\n")
# EXAMPLE 2:
class tree:
def __init__(self, name, height, width):
self.name = name
self.height = height
self.width = width
# Now instantiate an object of the class.
myTree1 = tree("Sequoia", "70 feet", "30 feet")
# Now instantiate another object of the class "tree"
myTree2 = tree("Pine", 100, 20)
# Now instantiate one more object of the class "tree".
myTree3 = tree("Redwood", 200, 27)
# Now print all three objects attributes
print(myTree1.name, myTree1.height, myTree1.width)
print(myTree2.name, myTree2.height, myTree2.width)
print(myTree3.name, myTree3.height, myTree3.width)
Below is the program output.
================ RESTART: C:\Users\YoiurUserName\Python_scripts\class.py ================
RED 6 inches
Sequoia 70 feet 30 feet
Pine 100 20
Redwood 200 27
>>>
Detailed Line-by-line Explanation of the Program
In EXAMPLE 1), an object of the class ball (named myBall) is created with class properties “color”, and “diameter”. While instantiating the object myBall, “RED” and “6 inches” are passed as arguments to the __init__
method to initialize the object’s properties.
How about the keyword “self” in the class definition? What is its purpose? The keyword self
binds the class attributes with the given arguments. In this example, the attribute “color” binds to the argument “RED” and the attribute “size” binds to the argument “6 inches”.
Example 2) illustrates the same concepts by creating a class named “tree” with tree class properties “name”, “height”, and “width”. Three objects “myTree1”, “myTree2”, and “myTree3” are instantiated passing different arguments to the __init__
method. Finally, we print each object’s properties.
The Class Definition (How to Create a Sprite)
Now that we understand the class and __init__
method, let us create a class. We will use this code in all our sprite game development programs. The below one-line code will generate a new class named “Player” based on the Pygame base class pygame.sprite.
Class Player(pygame.sprite.Sprite()
The above statement will create an object of type pygame.sprite.Sprite
, when you instantiate an object of this class.
The next line of code in the class definition is the class constructor (_
_init__
method) as described above. The __init__
method specifies what code is run when we define a new object based on the class.
def __init__(self):
Pygame.sprite.Sprite.__init__(self)
This code runs Pygame’s Sprite initializer and must be included in all class definitions.
Class Definition and Object Instantiation Template
The following is an example template for class definition and object instantiation for a class named “Player”. It creates a class called “Player” and then instantiates an object of the class “Player”. The instantiated object is named “player”. After you instantiate the object (“player”), you can use methods associated with the class (“Player”).
Here is the complete program for class definition and object instantiation.
PROGRAM EXAMPLE: CLASS DEFINITION AND OBJECT INSTANTIATION
Program Name: sprite_class_definition_and_object_instantiation.py
###### Class definition and object instantiation ######
# Import the pygame module
import pygame
pygame.init() # Intialize Pygame.
# Define the "Player" class to extend pygame.sprite.Sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
pygame.sprite.Sprite.__init__(self)
# Create instance of the "Player" class and name this instance "player".
player = Player()
Use the above code in all your class definitions and object instantiations.
The Group Class
Pygame provides a class called pygame.sprite.Group. The Sprite Group
is an object that holds a group of Sprite
objects. It is a
container class to hold and manage multiple Sprite objects.
The Group class is a container to hold the sprites in your game. When we use the Group
, it allows the programmer to use the Group’s methods. If your game has a “player” sprite and many “enemies” sprites, using these group’s methods helps the programmer to detect if any of the “enemies” sprites have collided with the “player” sprite. In the absence of Group
methods, the programmer will have to keep track of collisions between each of the dozens of “enemies” and the “player” sprites. Using the Group
methods makes the programmer’s job much easier in updating the screen.
How to Create a Group
So, how do we create a Group
?
Most games have many sprites on the screen. To hold all the sprites, most game programmers would define a group called “all_sprites” to hold all the sprites in their game by using pygame.sprite.Group method as in statement below.
all_sprites = pygame.sprite.Group()
The programs in the following pages explain how the Groups are created in a game and how to add sprites to a Group.
How to Add Sprites to a Group
Unless we add sprite objects to the Group we just defined, our Group will be empty. So, how do we add sprites to a Group?
Pygame provides add()
and remove()
methods, which can change which sprites belong to the group. Once we have created a group, we can add the sprites to the Group using the add()
method. To add a sprite to a Group, we use pygame.sprite.Sprite.add()
by specifying the sprite name as an argument.
Any number of group instances can be passed as arguments. The sprite will be added to the groups if it is already not part of the group.
The following statement adds a sprite named “player” to a Group named “all_sprites”.
“player” is the argument in the statement below.
all_sprites.add(player)
The following statement will add an “enemy” sprite to the “all_sprite” Group.
all_sprites.add(enemy)
How to Remove Sprites From a Group
If you need to remove a sprite from a Group, Pygame provides a method Pygame.sprite.Sprite.remove()
that will remove a sprite passed as an argument from the named Group.
The remove()
method removes the sprite from the Groups. Any number of group instances can be passed as arguments. The following statement will remove sprite “enemy” from the group named “all_sprite”.
all_sprites.remove(enemy)
super().__init__()
The Python super()
built-in returns a temporary object of the superclass that allows us to access methods of the base class without having to explicitly use the base class name. The usage of the super keyword allows the child class to access the parent class’s init()
property. In other words, super()
allows you to build classes that easily extend the functionality of previously built classes without implementing their functionality again.
Use this statement in your class definitions as you will see in the program examples below.
Collision Detection Between Sprites
In your games, there are typically many sprite objects on the screen. As the user of the game moves the “player” sprite to collide with an “alien” sprite or another sprite object like a ball, the programmer needs to know when the collision occurred.
Based on the collision, the programmer might want to make a sound or play music. The sprite module has a few collision detection functions. In the games in the sections below, we will use the function named spritecollide()
.
Syntax: spritecollide(sprite, group, dokill) -> list
Example:
new_enemy in pygame.sprite.spritecollide(player, enemies, 1):
This function checks for collisions between a single sprite (the “player” sprite) and the sprites in a group (“enemies” group). It returns a list of all the sprites that overlap with the first sprite (“player” sprite in this case). The “dokill” argument is a Boolean argument. If it is true, the function will call the kill()
method.
The kill()
method will delete the sprites in the group, which collided with the sprite in the first argument. In our example, the “player” is the first argument. This function requires a “rect” attribute for all the sprites used.