 How's it going everybody? Welcome back to another Python programming tutorial. In the last video we were checking out collision detection and resolution with the mouse. I'll show you this little example. We've been moving our character or player thing around the screen at the mouse and we can have it collide with other things and it'll actually stay in that position and that works well for us. But in this video we're actually going to prepare ourselves for some upcoming more in-depth tutorials and other ways to do things. So this video is actually just kind of preparing for that. We are going to organize our code. Now I'm not going to use this mouse example that I have. I'm actually going to switch back to Current which was the file that I've been using beforehand. Hopefully you had that saved and you created a different one for this mouse control because I'm going to go back to this. This one has arrow key movements. So if I use the keyboard and I press up and down on my arrow keys we have gravity working. I can jump left and right and so collide with other things. So that's the code that we're going to be starting to work with and actually organizing. We wanted to have a bit more of a game like structure and logic flow. So the way we're actually going to do this is by going ahead to create a player object and a class to keep track of all that. It's of course going to have the same sort of sprites back end that we had before and the way this is going to work is we're actually going to copy just about everything from the class block itself. So I'm going to copy all of this. Experience gravity. We're going to go down to experience gravity and stop there. Control X to cut that. And we can go bring that over to our player object right over here. Awesome. Now because we've done that keep in mind we do have to change the constructor. It's calling the parent object which in this case is the pygame sprite sprite but we're not using the block class anymore. We are using the player class so we have to change that argument. And we're not going to bother with sound anymore. I will admit I'm stepping away from that and we don't really need this play sound image either. That function. So we can kill that as well. Okay now let's go back to our block class. We are actually going to keep this class. We're going to fill it though at least for an instructor. That's all we're going to worry about. We're going to have a pretty similar constructor that we do with the player. So I'm going to copy that and bring that down to our block class. And now that that's all done let's fix the indentation there. Remember to change the constructor call for the parent class back to block. We can keep the image. We can keep the image fill. We don't want to bother with properties anymore. We don't want to bother with HB and VSpeed. But that properties function did something nice for us so let's go grab that actually. And copy that code. Keep the image rect. Kept the origin X. And it's actually set up. It's positioning with self dot rex. Rect X. And we do the same for Y. There. Okay now that we're done with that we're actually going to want to create another class. And this one is going to be a bit more broad. This is going to be a larger class. Let's call it level. And as you can guess, I suppose I don't really need those parentheses. We're not inheriting anything just yet. So yeah, we have a class level and that's going to be the map or the world that the player actually lives in. So we want our constructor. Of course that uses the self keyword. And like I said, the player lives in this level. It lives in this world. So we actually want another argument so we can keep track of our player object. And inside the constructor, we're going to set up a variable or I'm going to call this object list. And I figure you can guess this is going to be a group of sprites that actually keeps track of everything that we have in the level. Every platform, everything that we can interact and work with, those are objects or instances. You can obviously call this whatever you want. You can even call a platform list for now. I'm going to keep it vague and call mine object list. And that's all we need to do other than set the player object. Okay, cool. Let's see. Now we want to go ahead and create a new function in our level object called update. And that's of course is going to need the self keyword because it's inside an object. And it doesn't actually take any other arguments. But what it will do is it will call an update to that object list. Sorry, don't need the parentheses there object list dot update. And that will update everything in this group. And that group of things that we have in our level. Okay, that's pretty simple. Now we're actually going to create a new class. And this is going to be level one. So we set up a framework of levels and the way that we want things to actually work in the code by having a level list and the things that are running in there. So now we actually want to have other levels that are that are built around that same framework and that same kind of blueprint for how it works. And of course, it's going to inherit the level, because we've already set up the control for all of these things with this function with this with this class. Sorry. Now note that because we're actually inheriting from level, we have to have a different kind of functionality in this class itself. Python creates objects in funky ways. Something's called old style objects and new style objects. So whenever we actually have a constructor in a child class, in this case level 001, if I have my constructor and I run this, what's going to happen is if I were to actually try and grab from it, you know, with our with our super function that we've been using in all these other classes like the player class for pygamesprite.sprite and the block class for pygamesprite.sprite, we always inherit from the level name, self, and then we call the constructor of the parent object. Well, keep in mind, we have to be able to have that functionality with old style classes in Python. Yeah, we'll inherit everything, but we won't really be able to call the functions that this parent object has with new style classes. We are able to do that. So we can call the class levels constructor from within the subclass level 001. I'm sorry, level 01. So the way that we make this class the class of level and new style class is by actually inheriting from a special type in Python. And that special type is simply object. And you'll see my syntax highlighting in sublime text just changed to purple. So you know that this isn't any special class like level or anything else that we've already created. It is in fact a type that Python supports. It is an object. And it's going to be a new style object. So we can of course call from it when we have a subclass or a child with inheritance, which in this case is our level 01. Now in the constructor, the constructor, the constructor in the level class, we actually use self and the player object, we're going to do the same for the subclass player object. And of course, since we need that in the subclass, we are going to have to pass it to the actual parent class player object. There we go. Okay, now looking onward, trying to take a look at my notes here, see what we have to be ready. This will be the first level, level 01 is obviously going to be the first level, have it inherit level, we did that. Okay, next, we're going to want a variable that keeps track of everything that's actually in the level. And I'm just going to call this simply variable level. And it's going to be a list. In this case, it's going to be a list of things that we would need to create the block object. Now, the block object takes in a few things, color, width and height. Now, I'm actually going to want a few more variables like x and y. And I'm going to rearrange these right here, x, y, width, height, and color can be blue. I'm going to make these mandatory not optional. And that way, I know that we've added these x and y variables that call down here to self.rect.x. That'll work just fine because we're using these variables x and y. You know, looking back, I actually don't want to use these origin things. I'll just use the x and y variable. I think that's kind of a better setup at the moment. Okay, now let's go back down to our level over here. Like I was saying, this level variable will take in the information for each block to use. So we just set it up. We're going to use x, y, width and height, and we'll actually pass in a color just as an option. So now I will have one, I think that's, let's see, let's have one that's two pixels in, whatever. 104, 124 pixels down. Width can be pretty wide. Let's go 365. I don't care. Number of days in a year. Good enough for me. And let's say that's black. Okay. And we can of course add as many of these as we would like. But for now, let's just keep one of them. And the way that these actually all stay together is that we're going to create a for loop. And that for loop will look at each block in the level. And then we will go ahead and create that. That block can equal a block with block zero. Because we want to get the x. I'm going to copy and paste that. Block one, so we can get the y variable. Two for width and three for height. And of course, let's use block four, if it has that. Now we always have to supply color, but whatever. And then we'll add that to the object by adding it to our object list. Add it to the level. Object list dot add. I was going to say append, but then I realized I was supposed to say add. So I sounded funny. Object list dot add block. Okay. That's good. Now we've got a level done. So level zero one is complete. And we're actually going to keep track of the level that we're on by keeping track of it in the player object. So over here in the constructor at the very top of our player, let's add a new variable. And let's call that self dot level. And that's going to equal none for now. But next, we're going to move down to the actual main function, where all of this really happens. So that we don't need to any of these block dot group or block underscore group, any of these any of this group code. So you know, I'm going to do that disastrous thing, start from scratch and remove all of that. Okay. Now we're going to go ahead and add these player and all these other things in here. Let's create an active object list. I don't know why I stutter with that one too. Active object list. And that is of course going to be a pygame. Wow, I cannot talk anymore. Pygame dot sprite dot group. And that's where we're going to keep track of our player. Now, the reason we don't keep track of the player itself just as an object, because we can of course run player equals player. The reason I'm not going to do that is because if I were to add that in the main loop, if we were to keep track of it all, we would just end up writing like, I think window dot blitz player dot image or something. And then we'd have to use the destination like player dot rec dot x on player dot rec dot y. And that's a little bit more explicit than I really want it to be. Instead, we're going to take advantage of the pygame dot sprite dot groups draw function. We could very easily in the in the game loop just say active object list dot draw. And then we'll add our player and of course anything else that we want to have in there if we were to add anything more. Right now, though, I'm just going to leave it. And I'm going to go ahead and say player dot set position. Ah, where do I want it? That's the problem. Well, we said that we should have our our block way over it to 124. I'll put mine at 40 and 40. No, wait, it's got to be it's got to be it's got to be above the two is fine. As long as it's above 124 in the y direction, it should be just fine. Okay, so now that we've set the position, now let's go ahead and add it to the active object list dot add player. Now, let's actually go ahead and create a list for all the possible levels that we might have. Right now, we only have one. So let's go let's append onto that level list, level 01. And of course that needs a handle to the player object. So we'll pass in players, we just created that. Now, let's keep track of the level that we're actually on the way we do that is by keeping track of an index for this for this list out here. And that's going to be current level number in our case. You can call it index, you can call it whatever you want. But for now, the value is actually going to be zero since this is the first level that we're looking at. And we can set a current level variable, which is actually going to redirect to an object, because we're going to say level list with the index of the current level number. And that works just fine for us now player level player dot level is going to equal current level. Because we went ahead and actually added that variable up at the top of our player. That is what we know what level the player is in and what level the game is actually on that sort of thing. Okay, so now that that's all done font this message stuff works just fine for us. I'm not too worried about that. Running equals true, we don't really need this collidable objects right now, because we're actually going to pass that in for our, I believe do we need that? No, we don't because we're actually using the list of objects in the current level. I'll just comment that out right now. In fact, we don't need it because it's using more block and another block and we just deleted those we don't need that whatsoever. Sorry for the confusion guys. But now we're going to move down to our actual game loop, the event loop. And I'm going to do that drastic thing again, and delete damn near everything. The only thing we're going to keep right now is the event test. Okay, now I want to introduce this idea in this notion to you guys that in the event loop in our constantly running while loop, there is a certain setup of the way we need to actually run things. We have to update functions first. We have to run all of our update functions. So things are up to date. And then we do some logic testing. If a player is in any position, that sort of thing. And then we draw everything. And then we delay the frame rate. And then we update the screen. There is a specific order that typically run things are run in game. And earlier when we had the loop that we were using, it was kind of all over the place. So now I wanted to at least organize in certain categories what should be running where. Now, because you know, we created a player, that player has an update function we've been using in many, many tutorials ago. And that takes in the list of things that can collide against and it uses the event that we're currently on. So in our while loop, we're going to run player dot update with the current levels, object list. Because everything in the level we want to actually collide with. And of course, we'll use the event. And right after we handle the event, let's not bother with it anymore. Okay, now that we've updated the player, we do of course need to update the entire level, which will in turn update everything inside the level. That's why we're using this current level variable. Current level will update. Awesome. We don't have any logic testing just yet. We'll get into some fancy stuff with that in the next tutorial. I'm very, very excited for that. We do, however, have some drawing functions. We have the current level dot draw. At least I believe I created that function, didn't I? Level, level, level. Oh, we created update. We do however want draw. Sorry about that. Let's create that function define draw. And of course, that needs to know where everything is being drawn to, which will in our case be the window. And we'll get into backgrounds very, very soon. But right now, we're going to keep the background just plain old white, because we have that color included. We imported the very top of our program. And we're actually going to draw everything in our object list. That will all be drawn into a specific location because we passed in the window. And that's really all that we need to do for the draw function. I guess it's just unfortunate that I forgot that. But of course, because the level has to be handled in the event loop, it needs to be able to update itself and it needs to be able to draw itself onto the screen. So now that we have both of those functionality things done, we can draw the current level at the window, because that is the screen that we've created. And I believe we have to do it for our player, which as you know, is in the active object list. And I told you earlier, we're going to be using its draw function. And that's exactly what we're going to do. We're going to draw to the window. Awesome. Now we can delay the frame rate. And you know that's clock.tick with the frames per second we've set up at the top of our main function. And then we update the screen with our pygame.display.update. Cool. So now we've gotten back down to the very end of the program where we actually quit. And I think we're good. I mean, I think we've organized it all into a level, kind of oriented world and map and the player controls all of itself. The object just kind of stay there, which works just fine. And we can add them very, very easily with just a level, level 01 setup with any blocks and platforms we add to it. So let's try it. Let's run the code. I'm going to control B and slime text sublime text sorry. And of course we have a problem player to update current dot level objects. I wanted an underscore. Let's get down to the bottom here. Current level dot object list. I don't know why I type something wrong there. Current level dot object list. And now I've got my player, which is a little block here. And he's working on this small little thing on this black platform that I just made. Cool. Let's add another platform in here. We know we can easily do that just by adding to the level variable. Let's say x can be, let's bring it over 200. And width can be 280. And the y can be 324. Height can be 47. That's just fine. The player object we set automatically would be width and height 30, width 64 and height 64. I'm going to shrink that down. Width can be 32. So he's a little bit skinnier than that. All right. Now he looks, now he's a little too skinny. And we've got our world is just out of the levels. We can move our player down because of gravity. Let's say 48. And I'll bring the block down to 424. Cool. Now I've got our world. You can't really see the top of my player right now, but okay. Or the rest of the block, whatever. But there it is. There is our simple, simple world. We can easily, easily add blocks and add things and that sort of setup. It's just right now a matter of organizing the code so that we focus on a level object. And that's where everything works. This will make things easier when we actually get into platforming and more game oriented stuff. We just wanted to have the code in this structure and setup. So that's why we organize things. Thanks for watching everybody. I hope you enjoyed this. And I hope you have your brain firing for lots of cool new things we've been doing in the upcoming tutorials. Thanks!