Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Adding Obstacles to Your Game

00:00 In the previous lesson, I showed you how to get your ship moving. In this lesson, you’ll add some asteroids to your asteroid game. Games usually aren’t much fun unless there is a chance you can die.

00:13 In the last lesson, I removed the rocks to make it easier to play with the ship. Now it’s time to add them back in. Like you did with the ship, let’s extend GameObject to write some rock-specific code.

00:25 The rocks shouldn’t appear in the same place each time. You want them to show up randomly. The problem with random is they could appear randomly on top of your ship.

00:34 That doesn’t really give the player a fighting chance. To compensate for that, the rock generation code will leave a buffer of space around the ship. Anything less wouldn’t be sporting. Here, I’m inside of models.py. Before I make the changes to the GameObject, I need to import random so that I can use it. Let me just scroll down.

00:58 The first step for the Rock class is to extend from GameObject. Rocks are going to appear randomly except with a buffer zone around the center where the player’s ship starts.

01:10 This class constant specifies the minimum distance between the ship and the randomly generated rocks. There are several different techniques you can use when you need to generate something randomly, but with constraints.

01:22 You can do math on the constraints themselves and make sure the ranges are legal, or you can do what I’ve done here and just keep trying until it works.

01:30 This is a brute-force mechanism, which with the wrong constraints would be very expensive, but it’s good enough for the purposes here. I randomly choose a position that’s inside of the screen.

01:42 Then I check if the rock is within the minimum gap. If it isn’t, then you can break out of the loop. The position is done. If it is within the gap, the loop iterates again and a new position is randomly generated until a valid one is found.

01:58 With the position decided, you can call the parent’s initialization method using the random position, the asteroid image, and, for now, a velocity of 0.

02:12 Now, inside of game.py, it is time to add some rocks. First, the Rock object needs to be added to the import, and then the GameObject needs to be turned into a Rock object.

02:25 As there will be more than one, let’s use a list. The for loop here inside of the list comprehension will call the Rock() constructor six times. A better programmer would have a constant here instead of a magic number.

02:38 As soon as one shows up, I’ll make sure they get on that. I’m going to scroll down. Inside of the game logic and the drawing sequences, the code is going to have to do something to every object in the game. To help this out, I’ve created a property here called .game_objects() that returns a list of all the objects in the game. By using the star operator (*) inside of this list, it deconstructs the rock list, so the result returned here is a single list with all the rocks plus the ship.

03:11 The ._game_logic() method handles the motion of anything that has a velocity. With the new .game_objects() property, this method can be simplified to iterate over every object in the game and calling each object’s .move() method. Let me scroll down.

03:28 And here’s that same .game_objects() property once again, this time, used to draw each of the objects in the game.

03:36 Let’s go take a look at our rocks.

03:40 I’m going to make one quick little change to the game offscreen here, increasing the number of rocks. How does 600 sound? I’m doing that to demonstrate that the minimum gap property is working properly.

03:52 And there you go. Lots of rocks and a space of safety around the ship.

03:59 I apologize to those of you of a certain age. Well, two certain ages, actually: those who lived through the song the first time and those who lived through it when it was adopted by animated singing lemurs.

04:10 If you have no idea what I’m talking about, be grateful that nineties dance tunes aren’t now stuck in your head. Anyhow, our rocks aren’t much fun. Sure, they appear randomly, but they’re rather still at the moment.

04:24 It’s time to get the rocks to move around.

04:28 I’m back inside of models.py now. Let me just scroll down to the rocks. And I’ve added two more constants. To keep things interesting, let’s allow the rocks to move at multiple speeds.

04:40 These constants specify the range. Here, inside of initialize, the speed is randomly chosen, and random angle for direction as well. These two values are combined in a vector, and you have a velocity.

04:57 The line below here, the call to the parent’s .__init__() method, has been updated to take the new random velocity. Let’s see our masterpiece in action.

05:11 Look at that! Random, floaty rocks. They appear to be magic rocks that have no mass and don’t crush our ship, but that just gives us something to do in a future lesson. Bang!

05:23 You’re dead. “No I’m not, you missed!” “Did not.” “Okay, but I had a shield.” Next up, let’s add some rock destroying firepower.

Become a Member to join the conversation.