 What is going on everybody? Welcome back to another Pygame Python programming tutorial. In the last video we were checking out rectangular kind of platform-based collision detection and collision resolution and that was kind of helpful for top-down games or at least where you were using the arrow keys to move rather than the mouse. Now in this video I'm going to kind of keep that platformer game type idea in mind and we're actually going to incorporate gravity into the block and the player that we've been using throughout our code. Okay, so if you run the program right now, the way it has been in the last video, like I said, the block starts at the top left of the screen and we move around by pressing the left and right arrow keys and up and down and that sort of thing. So we've got these two blocks here we can collide with but now let's actually go ahead and incorporate gravity. Now gravity works with the v-speed variable and property and kind of attribute that this block object has. So if I just wanted to test that in the code that we've been writing so far, let's say just for ease of ability's sake I certainly don't want the object to start at the top left of the screen because then you're just going to fall straight down off to the edge of the screen and that's not going to be good. I'm going to rearrange their positions right for the creation event of the program and just put the block kind of in between this red and blue block here. So down at the bottom of the program, just for setting these up, I'm going to set the block's position to window width divided by 2. Put it smack dab in the center and I'll do the same for height. I'm going to change this, the red block, back to its regular size and I'm just going to subtract let's say 80. So now if I run the program, I'll be right over here and let's actually bring it down a little bit more. Let's say plus 80 and then the block and the brick that we're controlling can be plus 100 and let's actually subtract just 150 from it or just plain old 50, how about that? So now when we run the program, okay we've got a collision, okay that's not going to help, let's go 150. Okay so now when we run the program, the block should, due to gravity, fall straight down to the blue block. We can move over here in between the red and the blue block and then when we add gravity and jumping, we can just go right over to the top of this red block. Okay that's good, that works just fine for us. Now let's actually get to adding gravity. Well like I said, gravity works with this v-speed property and attribute. And when we are actually testing for a collision, we're testing whether or not the h-speed and the v-speed are being pressed, like whether or not we're moving left or right or up and down, and then we're making changes correspondingly and setting the position of the object to be the opposite end of the other object that we're colliding with. Now v-speed, since we're using that to manipulate gravity, it actually has to be a constant value every time we're actually standing on top of a block, like the blue block on the bottom of the screen. When we're colliding with that, obviously there's no v-speed because we're just kind of stopped. We're colliding and gravity could be acting upon us. So since we're stopped, v-speed is essentially zero. But we aren't setting it to be that way in our collision object testing right here. So let's do that. v-speed can equal zero. Let's do that for the opposite direction as well. Now I'm not going to do that for the h-speed object. Now you might be wondering why, but if we were to collide with an object and h-speed can be zero, that's just fine. What if we were to actually jump at the object? And what if we jumped so high in fact that we jumped over the object? Well, since we had set h-speed equal zero, we're not going to continue to jump over it. We just stopped in mid-air at that strange position. We don't want that to happen, so we actually do want to jump over the object. We're not going to use that h-speed equal zero. We're just going to do it for the v-speed object. And that's going to help us v-speed variable in property, sorry. That's going to help us when we're actually adding in gravity. Now, this has to make a few changes to our movement however, because let's say we actually collided with an object right at the top here. Once I release this key, it's going to send me right back down. And the reason that that's happening is because, here I'll do it from the top of the object and you can see me fly upwards, is because in our motion we have, set up down at the bottom of the event loop here, we just add on the negative value for the other direction we were moving in. And we can't have that happen either. Also, notice that the control for the motion is outside of the block object. And that's just kind of strange programming. If the block is the thing that's moving, why isn't it in the block object? So let's go ahead and add that in. I'm going to copy and paste all of this code here, all the code that tests for the event keys and the things that we're pressing down or not. And, okay, now that I've copied that, let's look over here to where we run ablock.update. Notice we are calling it with the collidable objects parameter. Now we add another parameter that we're going to add into the function that's going to be the event that we're actually looking at in the event loop. If we go back up here, events can obviously be empty. It can be an optional parameter. And in fact, collidable could be an optional parameter. We could have an object that doesn't collide with things. So that, I'm just going to set to be pygame.sprite.group. Now when we go ahead and at the end of this function, after all the collision testing, well, let's paste the code that we had beforehand. ablock.changeSpeed. Let's change all of these ablock instances to self. So we know that it's happening to this specific object. Ctrl H, ablock can be replaced with self. That's just fine. And we actually need to test to make sure that the event does not equal none. Because if it is, then we haven't actually gotten an event. We're just using that optional parameter that we had up at the top here. Now, if I were to run this code, you might see something crazy happen. If I bring this up here, if I were to press any arrow, any arrow key and move, I'm going to be like flying off the screen, or flying in some crazy direction. Now notice that's happening because event is happening over and over and over again because of the event loop. We actually have to limit that. Once we run the ablock update with the event that we're using, let's actually reset event to equal none one more time. That way, we're not going to be flying off the screen. Now, actually, let's change our motion because we didn't want to kind of reset back in the opposite direction. Let's test whatever the speed will be horizontal or vertical, whatever button we press, and then reset it to be whatever it needs to be. If self.hspeed is not equal to zero, self.hspeed can equal zero. Now, let's do this for the right direction as well. And for up and down, this is obviously going to be vspeed. Now, let's test this out. Bring the program over. Still running just fine. And now there's no accidents that happen when I'm actually releasing the key after a collision. Great. Now we can finally go ahead and add gravity. Let's set the block to spawn just a little higher. Let's bring it subtract 80. So now the block that we're actually using... Oh, no, not that one, my bad. I didn't want the red one to go. The brick that we're actually controlling to start at a higher position. So that way we'll actually be able to watch it fall down. And now let's set up gravity. You notice that everything is happening with this update function that's called every frame because of the event loop. So that's where we want to test for gravity. I'm actually going to set up a function called experience gravity. And that'll have the same kind of operations, but it's just going to happen in a separate function. So let's go ahead and define that. You can obviously name the function whatever you want, but mine is just going to be called experience gravity. Keep in mind this is a function inside of an object, so it needs to self-cure as the first argument. And I'm going to pass in an optional parameter called gravity, and that's going to be the value of gravity. Now when I say value of gravity, I mean the something that is actually added to the v-speed over and over and over again. So it has the effect of constantly falling down. Now, because we've set up a test that tests whether or not we're actually hitting the ground, self-dot-v-speed, that's going to be what we actually test first. If self-dot-v-speed is equal to zero, normally, because let's say we're actually colliding with something, gravity is essentially off. There's nothing pushing you down anymore because you're being pushed up by the thing that's below you. But we still want gravity to be in effect. What happens if we were on a moving platform that was moving down? Well, we can't just float in the air, we have to actually move down with it. So gravity has to toggle back and forth between zero when it's colliding with the object and then one when gravity is still in effect. And then of course, it'll register that, oh, we're still colliding with the object. The object, sorry, it'll go back to zero, which will go back to one, which will go back to zero and over and over and over again. Gravity is still in effect, but we're not going to end up moving. Now, if it's anything else other than zero, that means that, okay, we're actually moving throughout the air. Now we want to experience gravity. We plus equal the gravity value that we have. Okay, great. Let's run this program. Oh, it looks like I have an error here. I got to test with two equal signs, sorry about that. Now let's run the code. I'll bring this up as fast as I can. And you can see it fall, awesome. If I jump, you can see I fall right back down. Now if I actually press the down key while I'm in midair, I fall down faster. And I don't really like that. I'm going to set it up so that down key is not going to do anything. We'll just pass. And I'm actually going to set up a speed, a speed variable for this object. I'll put it in the set properties function for the object itself. Let's say self.speed can equal five, which is the same value we've been using. But let's just change self.speed in all these cases here. Great. And since we're going to press up, we're essentially jumping. So I'm going to double the current value and watch this jump just a little bit higher. Now, okay, you see me jump down. I can move left and right. If I were to press the up button, I jump. And I'm still colliding with the red object. And because we didn't change eight speed in the collision test, we can continue to jump and get on top of it. Now, the moment we release the up key, we stop jumping, because V speed is actually being changed to there. That's a fascinating thing. But we can hold down the up button and jump as long as we'd like. You can change that if you'd like, but that's the functionality that I think is just kind of built in with this code, and it works very well for us. So there we go. Plain and simple, we have gravity. All it took is a simple function that repeatedly adds to V speed, and we kind of just changed up the way that we have motion within the player object. And this way, the motion is actually localized. It's not in the global scope inside of the event loop. So, hey, all in all, this is a successful code. This is a successful program, a successful tutorial. Thanks for watching, guys. I hope you enjoyed this, and I'll see you in the next tutorial. Whoa! Wait a second. Before I go, I just realized, I actually realized after I finished recording, that if... Let me just run the program one more time. Let me show you exactly what this is doing. I forgot, and I guess, I suppose we forgot, but more so myself, because I'm kind of the one doing all this here. I forgot to show you that if we were to keep pressing the up button even while we're in midair, we can continuously jump, which kind of allows us to fly. And that's not good. That's not what we wanted. So, the way we can fix that is just a simple extra condition in our key down test, at the top of our update function, at the bottom of our update function for our block class at the moment. For assessing if key is up, what we should do is we should test if self.vspeed is actually equal to zero, because if it is, that means that we know we are actually on top of something, or at least kind of at the moment. Because if I bring this up, I can jump repeatedly now only when I touch the bottom. If I keep pressing up, I will not do anything other than bring myself down. So, another way of doing this is actually testing whether we have more collisions or if we actually have a collision. And the way we can do this is we can test if the length of the collision list is greater than one, I think. Actually, let's try that. In this case, no, it has to be greater than zero. I should just use greater than or equal to one, but now I can press the up button. Okay. Greater than or equal to one. And we can also change some functionality down at the bottom and remove our key release buttons. Because if we wanted this functionality this way, even if I were to release the key, I'll still jump to the full height that I would beforehand. Rather than the functionality, we would just stop the jump once I release the button. Now we always jump to the full height. Okay, cool. Sorry, sorry, I forgot that, guys. Now you can know how to do it. And yeah, it's just a simple, a few if statements in your key handling test in your block update function. Okay. Sorry about that, and I'll see you in the next tutorial. Bye.