[MUSIC] Welcome to week 7. I'm excited to see you here. For the last two weeks, we're going to spend our time reconstructing the classic 80s arcade game, Asteroids. The complexity of the game at first, when you saw the introduction, might look a little daunting, but it's not as hard as you think. We're going to provide you with lots of code that's going to help you in building your implementation. For week 7, the critical task that you have to do is you have to actually implement the control scheme for the spaceship in Asteroids. So in this lecture, I'm going to go through and play Asteroids a little bit, explain how the control scheme works. Then I'm going to spend most of the lecture in one note kind of going over some of the basic math used in building the control scheme. So let's go to it. So I'm going to give you a demonstration of the spaceship for our version of Asteroids. I'll just pop it up here so you can kind of see it running while I talk. So here we have the spaceship sitting on our nice background and I'll move it around in a second. Unfortunately, I can't give you this URL because that kind of defeats the purpose of the whole project, you'd automatically have the code. But I can recommend if you want to get a feel for the physics of how spaceship should fly, just simply Google Asteroids and arcade and you'll see lots of links that are kind of demo versions of Asteroids. Try it out. I think you'll get a good feel for how the game should play. Let me just demonstrate it real quick here on screen. So the controls for your spaceship have essentially a left arrow key rotates you counterclockwise, right arrow key rotates you clockwise. And then the main thing is you can hit the up arrow key and thrust forward. [SOUND] And so as you see, you move in a straight long line as long as you're pressing forward. Now, one thing you can do is, while you're thrusting forward you can change your direction. And you notice that you'll always accelerate in the direction of your forward vector, the forward direction for the ship, so that your velocity vector is independent of the direction you're accelerating in. So in fact, the control scheme for the ship, you're not actually controlling the velocity, now, you're actually controlling the acceleration. So I might need to walk you through a little bit of math to setup a second update that will update the velocity in terms of acceleration. Another thing to notice here is that as we accelerate, it should start to move and eventually its velocity kind of caps out and the ship slowly slows down and comes to a halt. Well in space, there's not supposed to be friction but you can just imagine we have a lot of debris here and the debris is slowing you down. So in fact in our version of our game, we're going to actually have friction. We're going to model the ship slowing down, this has two nice effects. First is, it allows you to stop easier, the second thing is it capture maximum velocity. So, I'll show you how to add friction to your model. So, with that, let's go off and then work on the mathematics of how to model acceleration and friction. Okay, now that we see the demo of the spaceship, let's talk about how to build some code that allows you to control the spaceship in the manner we just demonstrated. Now, I know doing this kind of of math I'm going to talk about here kind of makes some of you anxious so my suggestion is just bear with me. I'll go into a fair bit of detail. We'll get some Python code and I think you'll find that this is very tractable. So let's start off with kind of the easiest thing which is actually how to control the orientation of your spaceship. So there's actually two variables in the class definition for the spaceship. There are two fields. Here is self.angle. This controls the orientation of the spaceship. And then there's self.angular velocity, which is going to control how fast your spaceship will actually rotate whenever you hit the left and right arrow keys. So self.angle's probably the most important thing to understand, and it's the angle between the horizontal axis and the direction the ship is pointing. So for example, here's the horizontal axis. Let me position our ship right here, and the ship has a forward vector that's kind of pointing in the direction the ship is facing. Call that the forward vector. And this angle right here is self.angle, and note this is in radians. Okay, so if we want to go through and draw the ship, there's an option inside draw_image to actually specify an orientation for the image of your ship. I'm drawing it right down here at the bottom. We can provide a final perimeter which is a rotation and this will actually tell us kind of how to orient our image of the spaceship so it looks like it's pointing in a particular direction. So the other thing we have to do is we have to control how the ship rotates using the left and right arrow keys. And to do that you're going to do something very similar to what you did in Pong. We're going to have a velocity that we're going to control inside the key handler. So the key handler's going to actually control self.angle_vel. And then inside your update method, you're going to go through and update the angle by the angular velocity. That gives us kind of a quick overview about how we'll control the orientation of your spaceship All right, let's move on to understanding how the position, the velocity and the acceleration of a spaceship relate to each other. In particular, our goal is going to be to derive some code in Python that'll allow us to control and manipulate these three quantities. So the first thing to remember is that if we have our spaceship here. Draw this kind of skinny triangle here. It has some position, we kind of keep track of it maybe in the center of this triangle here and that's a point. The spaceship has a velocity, and one of the critical things we saw was that the velocity, the kind of direction that the ship is moving doesn't have to be in the direction it's facing. So the velocity can be something like this, maybe pointing off to the side. And then finally, we had the ability to make the ship accelerate, so we saw a little thrust triangle that got drawn down here, whenever our ship was accelerating. And it always kind of in this case, accelerated in a direction corresponding to the way the ship was facing. So we can model those as kind of three quantities over here. Each of these quantities is two dimensional. And so if you recall the relationship between position and velocity was really straightforward. In Pong, we did an update which looks something like this, new position was equal to the old position plus the velocity vector. Now notice I've done kind of updates for both the zero in the first coordinates here at the same time. So this is not Python code yet. If we want to update the velocity in terms of acceleration, turns out you can do the same thing. We can make the new velocity equal to the old velocity plus acceleration. So again, we have an equation. It looks something like this down here. Again, this is not Python because I'm kind of doing both components at once. But, let's move on and now I'll actually show you how to do this in Python. All right, let's build some Python code now to control the position, the velocity and the acceleration of our spaceship. So if you take a look at the ship class that we provided for you, there are four fields that are involved to what we're going to do. We have a position for the ship. We have a velocity for the ship. We have an angle for the ship, we just talked about that a few minutes ago. And then finally we have this flag called thrust that essentially keeps track of whether the ship is thrusting. If we're holding down the up arrow key, the ship is thrusting. If the arrow key is up, we're not holding it down, then it's false. So to build some Python code to kind of reflect kind of how our ship should behave, the first thing we observed is we can kind of use our kind of standard update for the positions. So we can just go through and do something very similar to what we did in Pong to update the position in terms of the velocity. So the second thing we have to do is we have to figure out what direction the ship is accelerating in. So whenever I hold down the up arrow key, the ship should accelerate. And we need to get the vector that corresponds to the direction the ship should accelerate in. So that's what this expression right here is doing. This expression right here is using a little trigonometry to get the forward vector for our ship. So let's go back here and I'll try to explain this a little bit better. So here we have, maybe this is the forward vector for our ship. And this is kind of the horizontal axis here and this is the vertical axis. And if you remember this angle right here, self.angle was the angle that the ship made with the horizontal axis. So if you haven't ever done trig, you just have to take on faith what I'm going to say here but if we have self.angle, we can compute the length of this piece of the vector, kind of the horizontal component. It's the cosine of self.angle. And likewise, this vertical component here is the sin of self.angle. So if we put those two pieces together over here, what we see is we actually get the corresponding forward vector. So we get math.cos.self.angle, and math.sin.self.angle. So, that's the acceleration vector. So, we're going to make the ship always accelerate in the direction it's facing, okay? So, what's the last thing we need to do? Well, last thing we need to do is we need to go through an update the velocity vector by the acceleration vector. In this case of the spaceship, that's the forward vector. So, we want to do something like this. So, remember this was kind of our update. The new velocity is the old velocity plus an acceleration. Now there are two things to remember here. Notice that I've conditioned this by self.thrust. So if we're holding down the up arrow key, we update the velocity according to this relation. If the up arrow key is not pressed then this conditional is false and we just leave things alone. So your key handler is going to have to go through and actually set self.thrust appropriately. The second thing to note here is I've kind of been a little quick here. This is always a unit velocity vector here. This has length 1 to get the acceleration just right, you may need to go through here and multiply the forward vector by a constant. So you need to multiply by a constant. So, you'll need to do a little bit of experimentation here to get the thrust just right for your spaceship. Okay, let's finish things off now, I'm going to talk about how to do friction. Okay, let's finish off our lecture and talk about how to add friction to our model of the motion of the spaceship. So the first thing you might ask is why do we bother putting friction in, I mean, it's a vacuum in space, there shouldn't be any friction. Well, there are a couple of reasons we're going to add in friction. One is it makes controlling the spaceship a little easier. If you take your finger off the up arrow key, the ship stops thrusting and eventually friction will bring the ship to a stop. Second thing is, if you don't have friction, you can make this ship leave as fast as you want by just continuing holding down the up arrow key. If there's friction, it actually caps the velocity of the spaceship. If you have a physical thought, you can think about there's a little bit of debris out there, and the debris is kind of slowing down the ship. So, how can we model friction in a way that fits in what we've done before? Well, the critical thing to observe here is that the friction basically induces a deceleration on this spaceship. And that deceleration is kind of in the opposite direction to the velocity of the spaceship. So here we have the velocity, and we multiply it by a small constant, negative of that. What that does, it takes the velocity back, scales it down a lot, points in the opposite direction, and that's going to be an acceleration. It's going to correspond to kind of how much the ship is going to decelerate on a particular step. So, now in our model, we're going to have two sources of acceleration for our ship. There's going to be thrust in the four direction and there's going to be friction in kind of the opposite of the direction of the velocity vector. So, if you go through and you do a little, do a little simple algebra here. You actually come up with a new update which says, the way we get the new velocity is we take a multiple of the old velocity but just a little bit less than one. So, we kind of scale the velocity down every time we do an update. And then if the ship is thrusting while we add in kind of an acceleration vector in the forward direction for the ship. So the change to our code is really simple, if you go over here, here's some Python code and what we see is that we have the old update we had before which is the new position is equal to the old position plus the velocity. Down here, we still have the corresponding acceleration and the forward direction if we're holding down the thrust key, the up arrow. And it'll all be done, here we kind of tucked in an update for the velocity vector that says take the whole velocity vector, scale by something that just a little less than one. That's what going to star equals 1- c does. This is going to be a number just less than one. We kind of scale it by that number. That's going to update the velocity. So what happen is we provide no acceleration. What's going to happen is friction is going to eventually make the velocity vector go to zero. So these three components here actually form our entire model for how the spaceship should behave. Take a look at the code, try to understand it, don't just cut and paste it in there. I think that you'll find the math is not as complicated as you might think. The only thing we're really using is kind of trig functions, for getting the forward vector and you can just kind of take us and our word on those. So play around with this, I think this will get you kind of a good start toward getting a good model for the motion of your spaceship. Okay, I'll see you back in a couple of lectures.