Adding Background Images
00:00 In this lesson, you’ll start adding some background images. Up to this point, the images you’ve used have only been for the player and the enemies, so now it’s time to make some background images. Let’s make some clouds.
00:13 The clouds will add another level of difficulty in that they obscure the player, briefly.
00:22
The steps are going to look really familiar. You’re going to create a Cloud
class. You’re going to add an image of a cloud to it. You’ll create a method .update()
that moves the cloud
toward the left side of the screen, and then you’ll create a custom event and handler to create new cloud
objects at a set time interval.
00:43
Then, you add the newly created cloud
objects to a new Group
called clouds
. And the last step is to set it up so that it updates and draws the clouds
in your game loop.
00:54
And this should sound familiar, because it’s going to look really similar to the Enemy
class that you created. Let me have you start to code it. Again, you might remember what Enemy
looks like as a class. Again, loading the image, setting the color key, getting the rectangle, finding its center, setting the speed, and then its .update()
, which was moving it to the left. Well, it’s going to look really similar.
01:29
So again, you’re going to extend pygame.sprite.Sprite
and use an image.
01:42
To extend it, you’re also going to set up the .__init__()
…
01:52
and set up super()
. Okay. So, you’re going to create the Surface
based upon pygame.image.load()
. The directory is images/
and it’s cloud.png
. Then run the method .convert()
. Move this up a little bit.
02:12 Then you need to do the color key. One unique thing here is the clouds are white and the color key in this case is going to be black. Basically, that’s what should be transparent, is the black areas.
02:25
And you’re going to use that RLEACCEL
again—oh, I need a comma there. Okay. And not unlike the enemies, you’re going to have a starting position that’s randomly generated.
02:38
So the self.rect = self.surf.get_rect()
(get rectangle). The center
is going to be a random integer—so from random.randint()
—and then you’re going to take the SCREEN_WIDTH + 20
.
02:55
So between there and SCREEN_WIDTH + 100
, and then one more random for the height from 0
—that’s the top of the screen—to the bottom of the screen, which is the total SCREEN_HEIGHT
. So again, this is going to place it off the screen in a variety of positions between 20
to 100
off to the right of the screen, and then this is anywhere from the top to the bottom of the screen. Okay.
03:21
That closes center
. And then this is going to close the rectangle here. I need to move the cloud based on a constant speed, unlike the missiles, and remove it when it passes the left edge again.
03:36
So, this is the .update()
method you’re creating for the Cloud
. self.rect
, move in place, .move_ip()
, and it’s going to move at -5, 0
, not moving up and down, and then check if self.rect
—the rightmost edge of the rectangle, if that’s less than 0
, then kill the Cloud
. Nice.
04:00
And it looks really familiar—I hope—to you, to the Enemy
that you created earlier. So now, after having done that, you need to create a custom event.
04:11 So, you might remember creating events here for adding an enemy, and it’s going to be really similar.
04:20
Okay. So ADDCLOUD
will be equal to pygame.USEREVENT
—how could we make it unique? Well, let’s make it + 2
. pygame.time
, setting a timer.
04:33
This timer is going to pull the trigger on ADDCLOUD
, and how about every second? So, 1000
. Okay. 1000
milliseconds.
04:40
Then, you need to do your grouping. Okay. So here you have enemies
. Let’s add clouds
, and that is also a sprite.Group
.
04:52 Great. Looks good. So what’s next? Well, while your event loop is running, you’re going to look for the new event, which will be “Hey, should we add a new cloud?” This should look pretty similar.
05:06
So, if the event pops up—elif event.type == ADDCLOUD
,
05:14
that’ll not only create the new cloud, but add it to the sprite groups. So here’s new_cloud
, it is an instance of Cloud
. And clouds
, use that .add()
method to add a new_cloud
. Ope, not enemy
—cloud
.
05:32
And then all_sprites
—it’s a member of that group too, right? .add(new_cloud)
. Cool! All right, what’s left? Well, we’ve got to have it update. So, here’s enemies
updating.
05:45
We could do that in the same block here. # Update enemy position and clouds
. clouds.update()
will update all the clouds. One thing you’re going to change, though, is we’re going to change the color. Fill the screen with a blue, so it’s actually like a sky, and those white clouds will now stand out.
06:03
So (135, 206, 250)
. Okay. Change the color of the sky to sky blue. Oops, let’s add a space for the formatting there. You’re updating the clouds
. Going in reverse here, ha.
06:19
You create a new_cloud
right here, in this event, if this ADDCLOUD
event appears. Again, that should happen every second, right?
06:28
Just like this happens every quarter of a second. And then here, you created that new Group
, and then here you created the custom event ADDCLOUD
, USEREVENT
, pygame.time
, ADDCLOUD
—looks good. Okay.
06:43
And then again, your Cloud
class. Going to save. Okay. So python sky_dodge.py
. That’s blue! Looks good. I see a cloud. I don’t see it moving. Something must be wrong. It looks like we may need to update something.
07:11
Oh, .update()
is in the wrong spot, right? It needs to be back here.
07:18
All these lines should not be indented so much. Right? That’s why they’re not moving. Okay. So, lines 91 to 96 should be back here at this level like .__init__()
,
07:37
so the .update()
method should be here. That’s what I missed. Okay.
07:44 Again, you might notice that it’s the same here. Okay. So now let’s try again.
07:54 Yeah. There’s some moving clouds now. Looks good! And the clouds don’t cause collisions. They do obscure the jet though. Cool. Boom. Congratulations! You finished Section 3.
08:12 Now, you’re on to Section 4 where you’ll start enhancing the game in our first lesson, where you’ll learn how to control the game speed.
Chris Bailey RP Team on March 30, 2020
Hi @John Berliner, The simple way of working with layers is the order you add them to a sprite.Group(). If you were for example to flip the order of
cloudsand
enemies` the clouds would appear below the missiles. There are a few additions to PyGame to manage layers, beyond the order you add them to a group. Unfortunately today is a bad day to try to get at the documentation, it is down. Not sure why. Otherwise I would give you the exact link. But when its back up, there are a bunch of methods, and addition to sprites to control the layers and ordering.
John Berliner on April 15, 2020
Got it. Of course you can have multiple Sprite groups too, right? I’d assume Sprite groups added later appear “above” previously-added Sprite groups…I’ll experiment. Thanks—
harrisonstewart2004 on March 2, 2021
I’m still having issues with the speed of the enemies and clouds. I fixed the player but the enemies and clouds are just streaks across the screen. Any way to fix it?(:
Chris Bailey RP Team on March 4, 2021
Hi harrisonstewart2004, The next lesson covers the most common way to control the speed of the game and included in that the enemies. Adding a clock and setting the tick to a slower framerate should solve it.
Become a Member to join the conversation.
John Berliner on March 30, 2020
Really enjoyed this tutorial!
I didn’t see anything about setting or changing layer order, so is it just the case that sprites instantiated later automatically get drawn to a higher-ordered layer than sprites drawn earlier? (unless some call is made to change a sprite’s layer?)