Adding Collision Detection to Your Bullets
00:00 In the previous lesson, you added shooting capabilities to your spaceship. In this lesson, I’ll show you how to make those bullets do more than pass harmlessly through the rocks.
00:10 You’ve seen basic collision detection already and used it to see if game objects passed off the screen. Now, just a little tidying up and some consequences when things get shot. You’re interested in two kinds of collisions: Bullets can collide with rocks, and in that case, the rock should go away. And rocks can collide with ships, wherein the ship should go away.
00:35
Here I am inside of game.py
. Let me scroll down a bit. This is inside of the ._game_logic()
method just after the code that figures out if the bullets left the screen. Using very similar logic for removing the bullet, I’m going to loop through the bullets and the rocks and see if any of them are colliding.
00:54
I’m using the same trick as before, iterating through a copy of the list so the original can be modified. For each bullet, iterate through all of the rocks. For each rock-bullet pair, check if they collide using the method in the GameObject
base class that was written many lessons ago.
01:13 If there is a rock-bullet collision, you need to remove the rock, then remove the bullet. You can also short circuit the rocks iteration as the bullet has done its job and won’t collide with anything else.
01:26
This break
statement here also ensures that if two rocks were perfectly overlapped when a bullet struck, only the first one would be destroyed.
01:36 That’s the code for colliding rocks and bullets, and here is the code for rock-ship collisions. Similar concept here, but now I’m iterating through a copy of the list of rocks.
01:47
For each rock, check if there’s a ship collision. If there is, set the .ship
to None
. For our simple version of the game, there’s only one life. If you had multiple lives, this would be where you adjusted the life counter. Setting the .ship
to None
here has some deep complications in the code.
02:05 What happens if the user presses the acceleration button after the ship is gone? Well, if you don’t modify the code a bit, a program crash will be what happens.
02:15 Line 75 is the first of several places where you can no longer assume that the ship exists. If the ship was wiped out before, you can’t check it for rock collisions.
02:25
rock
collides with None
will bring your code to a rather abrupt ending. This problem extends into the ._handle_input()
method as well. Let me show you.
02:36 If the user moves a ship that isn’t there, you’ll get a crash, so lines 40 and 41 exit the input handling method early. There’s a bug in here. You can decide for yourself whether I was too lazy to fix it or left it as an exercise for you. This check isn’t sufficient.
02:52 There are other things that can cause the same problem. See if you can find it.
02:57
This highlights the .ship
being set to None
being used as an indicator for game over. It isn’t an elegant solution. A smarter choice might be to have the aliveness of the ship be a part of the ship’s state, and then with any of the ship’s methods, do nothing if a method is called but the ship is not alive.
03:17 With the clever use of a decorator or a bit of meta-programming, you could have the ship object handle the dead state without having to change the interface.
03:25
Both of these are concepts outside the scope of this course. For now, None
is good enough, but there’s work that could be done here if you wanted to. Let’s go shoot some rocks.
03:41 Now that was kind of satisfying, wasn’t it?
03:47 I told you I wasn’t very good at these things. In the original Asteroids game, the rocks didn’t just disappear. They split into smaller chunks. In the next lesson, you’ll add that capability to your game.
Become a Member to join the conversation.