Search this site
Embedded Files
Python Jedi
  • Chapters
    • Fork/Clone
    • 1 Version Control
    • 2 Python Console
    • 3 Input/Output
    • 4 Conditionals
    • 5 Looping
    • 6 Num. Systems
    • 7 Graphics
    • 8 Lists/Strings
    • 9 Functions
    • Prisoner's Dilemma
    • 10 Classes
    • 11 Animation
    • 12 User Control
    • 13 Libraries/Modules
    • 14 Game Design
      • 14 Sprites
      • 14 Shooting
      • 14 Explosions
      • 14 Levels
      • 14 Aiming Trig
      • 14 Walls
      • 14 View Port
      • 14 Grids
    • 15 Data Analysis
Python Jedi
  • Chapters
    • Fork/Clone
    • 1 Version Control
    • 2 Python Console
    • 3 Input/Output
    • 4 Conditionals
    • 5 Looping
    • 6 Num. Systems
    • 7 Graphics
    • 8 Lists/Strings
    • 9 Functions
    • Prisoner's Dilemma
    • 10 Classes
    • 11 Animation
    • 12 User Control
    • 13 Libraries/Modules
    • 14 Game Design
      • 14 Sprites
      • 14 Shooting
      • 14 Explosions
      • 14 Levels
      • 14 Aiming Trig
      • 14 Walls
      • 14 View Port
      • 14 Grids
    • 15 Data Analysis
  • More
    • Chapters
      • Fork/Clone
      • 1 Version Control
      • 2 Python Console
      • 3 Input/Output
      • 4 Conditionals
      • 5 Looping
      • 6 Num. Systems
      • 7 Graphics
      • 8 Lists/Strings
      • 9 Functions
      • Prisoner's Dilemma
      • 10 Classes
      • 11 Animation
      • 12 User Control
      • 13 Libraries/Modules
      • 14 Game Design
        • 14 Sprites
        • 14 Shooting
        • 14 Explosions
        • 14 Levels
        • 14 Aiming Trig
        • 14 Walls
        • 14 View Port
        • 14 Grids
      • 15 Data Analysis

Fork/Clone Ch.14 Game Design Jedi Training: Sprites

sprites and Collisions

This is a VERY important chapter because our games need support for handling objects that collide. Light sabers touching, bullets hitting a target, or some character collecting a coin are all examples that require collision detection.

The Arcade library has support for sprites. A sprite is a two-dimensional image that is part of the larger graphical scene. Typically a sprite will be some kind of object in the scene that will be interacted with like a car, frog, or bullet.

Originally, video game consoles had built-in hardware support for sprites. Now this specialized hardware support is no longer needed, but we still use the term “sprite.” The history of sprites is interesting, if you would like to read more about it.

sprite images

   There are several image formats that computers use:

  • .bmp - Bitmap. This is an uncompressed image that normally uses three bytes to represent each dot in the image. These files can be very large. Because there are so many better options, this format is not used often. It is, however, the simplest format to use.

  • .png - Great patent-free format for line art and clip art. Not great for photos. Can’t hold animations.

  • .gif - Great format for line art and clip art.  Can do animations.

  • .jpg - Great file format for photos. Terrible for clip-art. Don’t use for sprites.

  • .svg - File format for storing line-art images that can scale to any resolution. Not compatible with the “arcade” library.

If you use Google’s advanced image search you can find images that are “icon” sized, and either png or gif file format.

There’s also a great source for images from kenney.nl. He has a lot of free and cheap game image assets.

bb8.png

stormtrooper.png

When you downloaded the repository for this chapter, the above images were in a folder called Images. As we did with sounds, we need to reference the path to the image as Images/bb8.png.

Sprite/Collision Code

In this chapter we will introduce sprites and how to detect their collisions. We will build the following program below. You will find the starting code (Jedi Training) and images in the Github repository. We will add code throughout the chapter until you have the following program created. Your Jedi Training is simply to follow the directions and build this game.

     This example shows how to create a screen of sprites that are stormtroopers, and destroy them using a sprite that is a BB8 controlled by the mouse. The program keeps “score” on how many stormtroopers you have destroyed. Let's look at your starter code.

Starting Code

#1-2: We import two modules: random and arcade.

#5-9: We set some global constants that we will use later in our program.

#11-22: We are going to set up our MyGame() Class inheriting from the arcade.Window Class. 

#14-16: In the __init__ section we will set our background color. 

#18-19: In the on_draw function we will eventually put our drawing commands so we will use arcade.start_render() as our first line.

#21-22: We will eventually use the on_update function but for right now we will use the placeholder pass.

#25-28: Finally, we have the main() function where we call the MyGame() Class and establish the game window.

#31-32: Finally we run the main() function.

#17-18: In the __init__ section of the MyGame( ) Class let's make the mouse cursor invisible.

Sprite Class

In our games we will need to create sprites. The name of the class that represents sprites is called Sprite. You can read more about it by looking at the Sprite documentation. The Sprite constructor takes two parameters. A path to the image we will be using, and how big to scale it. We will make two classes Player() and Trooper() which will both inherit the Sprite() Class. We will put both of these classes right after our global variables and before our MyGame() Class.

#11-16: Create a Player() Class inheriting the arcade.Sprite() Class. Initialize it by referencing the path to the image and the scaling variable of 0.3. We will use the pass placeholder in the update function for now.

#18-25: Create a Trooper() Class 

We initialize it by referencing the path to the image and the scaling variable of 0.1. You can adjust these scaling factors if you would like to see what it looks like eventually.

All sprites have instance variables that we can use. These can be found in the Sprite Documentation. Some of the ones we'll be using as we build this program are width, height, center_x, center_y, change_x, change_y, top, right, bottom and left.

#21-22: Get the .width and .height attributes of the Sprite. These are float numbers and we will convert them to integers and then assign them to the variables, self.w and self.h. We will use these later.

#24: We will again use the pass placeholder in the update function for now until we want the Trooper objects to move.

RESET function

Next, we will create a reset() method in our MyGame() Class after the __init__ section. This will create our sprites and get our game set up. Why don't we just do this in the __init__ method? Because if we want to restart the game, we can just call reset() again.

When working with sprites, we normally put them into lists. Other game engines might call these sprite groups, or sprite layers. Our game will have one list for the player (BB8), and one list for the troopers. Even if there is only one sprite, like our Player sprite, we should still put it in a list because there is a lot of code in the SpriteList() Class to optimize drawing.

#43-44: Create a player_list and a trooper_list from the arcade.SpriteList() Class.

#47: Initialize the score variable to 0. 

#50: Instantiate an object of the Player() Class.

#51-52: Set the .center_x and .center_y Sprite parameters to the center of the window.

#53: Append the BB8 object to the player_list even though there is just one player.

#56: Create a for loop that will allow us to create as many trooper objects as we want. Our trooper_count variable is currently set at 40.

#57: In the loop, instantiate an object of the Trooper() Class.

#58-59: Set the .center_x and .center_y Sprite attributes to random values somewhere within the window. For example, for the random .center_x we will choose from the trooper width up to the Screen Width - trooper width. This way there won't be any troopers right on the edges of the screen.

#60: Finally, add the trooper object to the trooper_list.

#72: In the main() function we now need to call the window.reset() function since it is not called automatically when the window object was created.

on_draw( )

If you go ahead and run our program at this point nothing much happens. A blue screen opens up with a window title. Also the mouse cursor disappears over the screen. But where is our BB8 character and where are the 40 troopers? Well, in the reset( ) function all we did was create the objects and put them in their respective lists. They are just sitting in there waiting to get printed to the screen. We will do that in the on_draw method of our MyGame() Class. This is easy to do.

#64-65: Call a .draw method on both the trooper_list and the player_list.

Now if you run the program you will see all of the objects drawn to the window.

#68-69: Here we will print the score variable to the screen. Click here if you forgot how to format text.

Move Player

#74-77: Add the on_mouse_motion( ) method at the bottom of your MyGame( ) Class. Set the .center_x and .center_y positions of your player object to the x and y positions of the mouse.

!!! WHEN WE ARE DONE, CHANGE THIS TO USE ARROW KEYS !!!

on_update( )

If you run the game now, you will see that the BB8 player follows the mouse around the screen. How do we detect when the BB8 sprite hits a Trooper sprite so we can delete the Trooper sprite and add 1 to the score. We will do all of the Collision Detections in the on_update( ) method of our MyGame( ) Class.

Each sprite has its own update method. This allows sprites to move and animate its images. Right now, both of our sprites have pass as a placeholder in their update( ) methods. Later you will need to animate the trooper sprites or control the player sprite with the keyboard so you will eventually put code in their update( ) methods. Therefore we want to go ahead and call the update( ) method on each of our sprites. Rather than call the update( ) method of each sprite we have, there is an update( ) method in each sprite list that will call update( ) on each sprite in the list. Therefore, just calling update( ) with our trooper_list and player_list will cause all sprites in those lists to update.

#72-73: Call .update( ) on both sprite lists.

Now, how do we detect what troopers are touching BB8? We call the check_for_collision_with_list( ) method. The first parameter is your player sprite. The second parameter is a list of sprites that your player sprite is trying to collide with, trooper_list. The check_for_collision_with_list( ) function will return a list of all colliding sprites. If no sprites collide, the list will be empty.

#75: Call the returned list variable, trooper_hit_list

What do we do with this trooper_hit_list we get back? We loop through it and add one to the score for each sprite hit. We also need to get rid of the sprite. The sprite class has a method called kill( ). This method will remove the sprite from existence.

#76-78: Loop through trooper_hit_list, erase the trooper and add 1 to the score.

Try to run the program. It should now work.

#80-81: Once the score equals the trooper_count variable, we can call the reset( ) function and start over.

If your game worked, modify it to use the arrow keys and then demonstrate it to your instructor.

 Next, you will duplicate this code and modify it to start your own game. The criteria/constraints for this beginning game are in the repository. Throughout the next several chapters as you learn more game design methods you will continually build on your game project.

Quick Lookup:How to download and turn in Jedi Tasks
Syllabus
Marc C. Hermon - Python Jedi InstructorUrbandale High School, Urbandale, Iowahermonm@urbandaleschools.comWebsite: EngineeringU.com
Google Sites
Report abuse
Google Sites
Report abuse