Transcripts
1. Trailer: Hello. Would you like to learn how to make video games in Python? If you do, you're in the right place because that is exactly what I am going to teach you. And here's what we are going to make. We're going to start with the pygame module, which is the most popular way to create gangs and Python bytes cell. And we will start with a very simplest shooting range game. And what a game is fairly simple. It is going to teach you all the basics of video game development. So we will talk about how to animate something on the screen. You would talk about how to create objects on the screen. We will talk about how to get user input and lots more. But once we're done with that, we're getting to a much better game, which is going to bend asteroid shooter game. And here things are getting much more interesting. We're going to have a spaceship with lives and the laser and some Shields. We have spawning meteors that can move around on the screen. We have different stages of the level and quite a bit more. So a much more developed game that will teach you so much more. And once we're finished with the pygame module, we are starting with the really cool stuff because then we are migrating 2D could DO gaming engine, which uses GD script, which is basically Python, optimized for video game development. And in here, we're going to create two more games. The first one is going to be a futuristic style for our game. And in here, things are going to look so much more interesting. We have really fancy graphics with player animations. We have different stages. We have so much more and the screen and district, if you're a really good foundation to create any kind of more complex game. And finally, we come to the really good part where we are going to create a 3D shooter, where you are going to shoot at vegetables just to keep things clean. But even with that, we have all the things you need to create a really cool shooter. We have particle effects and we have cool lighting. We have lots of different objects. We have weapon animations. We have other things for good-looking video game. Once you're done with these four games, you are going to have a solid foundation on video game development and feel this tutorial. I want to explain every single line of code. And if I'm introducing a new concept, I will use illustrations to make it more clear so that you won't have any problems understanding. Also, every single stage of the game will be uploaded. So you can constantly double-check and what stage you are. And if you find out off this interesting, I'm really looking forward to seeing you in the course. And if not, I'm wishing you all the best for whatever journey you like to take.
2. Requirements: Hello and welcome to the first video in this series. Before we are getting into the actual game development, I would like to talk about the requirements for this course and do let me stress this here, that this is not a course to teach you Python itself. Instead, we are going to use Python to create a video game. So we're expected to know at least a little bit of Python. So let me talk about what you should know before getting into this course. You have to know how to use variables and how to influence variables. So how to add or subtract values or multiply values. The really simple stuff you shouldn't have to use if statements as well as for and while loops. So all the really basic stuff of Python, you should also know how to create a function and how to call it. And the same for a class. So you should be able to create a class and to create an object from their class. And we're also going to use inheritance. So you should know at least a little bit about it. But don't worry about this part too much aisle. We'll talk about this in more detail and become to it. So if you now to create a basic class, you should be good to go. And besides that, you should also be able to use pip to install new modules. And that's really it. If you are completely new to pay from, I would recommend you check out if free video on YouTube. There are plenty that are going to teach you all of this in about an hour. So if the boring stuff out of the way, let's talk about video games in the next video.
3. How games work: Hello and welcome to the first major part of this tutorial series. And for now, we're going to talk in fury about how video games work, which I think is going to be really important to understand later on what we are doing. And fortunately, the fundamentals of video games are the same. It doesn't matter if you look at a video game from today or from a video game from the 19 eighties, the same principles still apply. So let's talk about them. And to understand this the best, I think it's good to use an example. So on the screen right now, you can see Super Mario World, which is a fairly old video game, but quite good to illustrate the basic elements. And so right now, you can see one image or one frame of our game. And this one image is composed out of several different elements. For example, we have Super Mario itself, we have a background, we have some UI elements, and we have a floor and quite a few more elements. And essentially what happens in the game is that these elements are slowly being put together to create one image. So out of these individual elements are individual pieces in the beginning and only inside of the game are they being put together. And none of them are anything special now, all just basic pictures. And he could literally go on the Internet right now and download all of the assets for this game and make it yourself. Obviously, if you were to publish it and tender would have very serious ward review, but you could just download them and use them yourself. There's nothing particular about these images. It's literally just basic pictures. They're just being put together in a certain way to create a game. So really nothing fancy. But the really important point for video games is that this image isn't just created once. Instead, it is being created multiple times per second. And for example, Super Mario World had a frame rate of 60, meaning that the game was creating this image 60 times per second. So roughly every 17 milliseconds that the game put all of these elements together and display them to the player. So while we are seeing a static image, the game is really busy putting off these images together and displaying them to us. But obviously right now, we are only showing a static image, which isn't particularly useful to make a video game. So what we have to do is to add interactivity to all of this. And this happens with code, and there are lots of different things that we can do. So for example, imagine right now in the game, you have to press right on the controller. In the game, we would get the update that Mario has to be moved to the right. And now what happens inside of the game is that instead of having married in the middle of the screen, we are moving him slightly to the right and changing the image we're displaying. And on off. This still happens at 60 frames per second. So what happens so fast that for us, it looks like a moving image. And all of this is called the game loop. And what happens in here is that we are running some kind of code that places different elements on the screen. So when a player has to be where enemies have to be, what you, i elements have to be displayed and so on. And then all of this is being displayed to the player at a certain frame rate. And we are going to create our own game loops very soon. But the fundamental thing you have to understand, instead we are just painting a picture on the screen and refreshing this picture of multiple times per second. And while we're refreshing it, we are changing the position of different elements on the screen. And this is really all the video game is, that you put an image on the screen and you refresh wettest image have to be depending on what the players pressing or maybe depending on some other code. But there's nothing inherently special about this process. And there are lots of different ways to create this kind of logic. What we are going to see in this tutorial is to use pygame and a good dog gaming engine. And I will talk about them in the next video. I will see you there.
4. Python game tools: Hello and welcome back. In this video, I will be talking about the tools you have to make video games. And there's one major problem I really want to talk about, that Python is not great for video game development. And if you are a new Python developer, you might have already noticed some parts of this. That, number one, you can't really display information in a pleasing way. All you really have is to console, which can only display text, which is not very good for video games. Also, if you wanted to make a video game, you couldn't really get player input. All you have is the input function, and this one stops to cold when it's being run. So you couldn't have real-time video game. It would always stop the code when you get input, which would break basically any kind of video game. So standard Python isn't good for video games. But to fix these problems, we have a couple of modules that can help you with that. And the one we're going to use and discourse is called pygame, which is one of the oldest and most popular modules to make video games. And this one has lots of tools to display information and also to get user input, which is basically all we need to make a video game. And PyGame very explicitly uses the logic I have talked about in the last video, that we are creating a game loop. And inside of this game loop, we are working with some code to place elements on the screen and work with them. But we're going to come to that later on. And just to mention it, PyGame is not the only module in Python to create video games. A couple of alternatives would be piglet and Python arcade. And there are just as good as pygame. And I would recommend you to check them out at the end of this video that can be quite nice. But ultimately, all they do is implemented logic I talked about earlier. And all you're going to see is that you're importing a Python module and then you are going to write some code. And this is actually bringing us to the next problem I would like to talk about. Looking at an editor to make a video game is not very efficient. So when you make a video game, you want to see what you are doing, right? When you're setting up the game. You don't want to look at lots of lines of code and somehow guess where elements are on the screen. And for that purpose, you have video game engines, and these allow you to make your game much more efficiently. So what those effectively are is a GUI editor where you can drag and drop different elements. You can give them cold very easily. And you can see on the screen immediately what we are doing. And for that, in the second half of this course, we are going to learn about the good dog gaming engine, which does exactly that. So you can't see any code. Instead, you can see all the different elements of the game, which makes it really easy to create a level and to see how different elements work together, which makes a video game development so much easier. And that's going to bring us to the final problem that I do want to talk about in this video, that Goodall does not use Python. Instead, it uses GD script and what it sounds like a different language. It isn't really. So let me put an example of GD script on the screen right now. If you know at least a bit of Python, you should be able to read this. And gt script is insanely similar to Python. And if you can use one language, you can use the other language. Some keywords might change and a bit of logic might be different. But fundamentally, you use the same principles. There's not much change going on. And the reason we are going to use GD script is because GD script is optimized for game development, which primarily means that it runs much faster than Python. And this is quite a common problem for Python itself, that Python is a very flexible language, but it is not a fast language. So while it can do lots of things very easily in Python, the consequence of that is that Python doesn't run as fast as other languages. But GD script alleviates that problem. That a removes some of the flexibility. But as a consequence, our code is going to run quite a bit faster, which is essential to create a video game loop. But don't worry about all of this too much just yet. We are going to talk about this in much more detail later on. For now, just be aware, we're going to start with pygame and create two games and there. And then we come to Goodall in much more detail later on. But with all of that done, let's actually start our first game.
5. Installing pygame: Hello and welcome to the first game we are going to make. And it's going to be this one. We are going to create a simpler shooting range game where you should add targets and then it is appear. And along with that, we have some animations and we have generally a couple of images on the screen that make the entire thing look quite nice. So nothing particularly fancy, but I think a good start for game development. And for all of this, we are going to use the pygame module, which is a very powerful module that is quite nice to develop in. However, it does not come with Python preinstalled, but we have to install it ourselves. And for that purpose, I'm going to use PIP. And installing it in that way is super easy. If you are using a Windows computer, open the PowerShell. If you're using Mac OS, open the terminal. And for both of them, you should be seeing something like this. And all you have to do in here is type pip installed PyGame. Then you should see a short piece of text. And then ideally you see PyGame successfully installed. And if that comes up, you are good to go. You should be having PyGame installed. And if you don't see this kind of message, something probably went wrong on your system somewhere. But let me know in the comments and I'm really happy to help. But none of with pygame installed that's first tested to see if it's working. So here you can see my code editor. I'm using Sublime, but any code editor is fine as long as it can run Python, which is basically all of them. And to check if we have installed PyGame, or we have to do is type import pygame and build or execute this code. And if I do that, I can see PyGame 1.9.6 and hello from the pagan community and a link to the website. And if you're getting to this stage, you have installed PyGame successfully. So if this one done, we can actually start working on it, which is going to happen in the next video, I will see you there.
6. Shooting Range 1: Intro to Pygame: And with that one done, let's actually talk about the game we're going to start making. And it's going to be this. It's a fairly simple shooting range game, and you just click on ducks and they disappear. You can keep on doing it to some animations. We have some background art. If you click on those, they don't disappear. And I can just keep on clicking it, eventually finish and we get a wind message. And that's pretty much the entire game. And it's not exactly a sophisticated game. However, it does teach you all the basics you need to create basically any kind of game and PyGame. So let's start building this thing up. And we first start by talking about getting a blank screen. And this will already cover quite a bit of theory on how to draw things and PyGame, The first thing we need is actually quite simple. That PyGame always needs to be initiated and uninitiated. And anything between these two states is where our game happens. And both of these can be achieved very easily. All leaders PyGame dot init to initiate a module and PyGame dot quit two ended. And for now you don't really have to know more about these commands. Does, do be aware that you have to include them. But for now, focus on what happens inside of them. And the most important thing that happens inside of it is that we create a display surface. And the display surfaces basically Window did play a perceives when the game is being played. And this one is done with a very simple command, it just this one line of code. And then this display services being continuously updated in the game loop. And this game loop isn't actually anything complicated. It's literally just a Python while loop that runs endlessly. So it's sad to wild true. And we only break it from the inside of that. And these two elements already are going to create our basic game window. But there's one more element we need and that is to get some player input, because right now our game just continuously updates. We literally counter anything. We cannot even close it, which is kind of a problem when you run the game right now. So what we have to do is to look for what's called events and PyGame. And polygamy events are mostly just player inputs. So it could be the move of a mouse or could be a click of a button. And it could also be the click off the little accident top of the window to close the gate. And if we didn't include this, we would not be able to close our game. But those are the four elements need to create the most basic kind of window. You need to initiate and quit pygame. And inside of that Ukraine, a display surface. And then you update this surface continuously in a game loop. And in this game loop you look for events that could, for example, be player input. There are two more elements that are kind of important, but for now they're not exactly necessary. So let's start talking about the basics. And then we covered these two elements at the end of this video. So here I have a completely empty sheet of code. And the first thing we need is to import pygame, which should be quite obvious line, if you want to use pi m, you have to import PyGame. This works like any other Python module. And now our very first line is to initiate pygame, which happens with pygame dot init. And this is all we need to do for now to initiate pygame. And later on we're gonna close PyGame. But for now, once it's initiated, that's basically all we need. And the next step is to create our display surface. And this one is to be stored in the variable. And this variable is usually called screen. You could literally give it any name. It doesn't really matter. Just make sure it's something that captures what you want to express and screen. In this case, it makes a lot of sense. And the line we need to create a display surface as PyGame like display, dot set mode. And inside of that, we need a tuple with two pieces of information, and that is the width and the height of the window we're going to create. And in my case, I want this to be 1280 by 720 pixels. So the window we're going to create is one hundred and two hundred eighty pixels wide and 720 pixels high. And with that, we have our display surface. And I could actually run the code right now already. So I run the code, we can see a window for a very short period of time. And basically what happened there is that Python creates this display surface. However, it doesn't know for how long it's supposed to be open. So it opens it for one frame. And since we don't tell it to keep it, open, it, close it after this frame again. And what we need to keep it open is the game loop. And the game loop is literally just a while loop. It is set to wild true. So usually in Python, a while loop just runs like something. While x is greater than, let's say four. And then once this condition is false, then this loop would stop running. But if you have well true and this loop, whatever happens in here, is going to be continuously updated. And as you break the while loop from the inside of it and in here are displaced surface is going to be continuously updated and as one line that need to update the display surface. And that is pygame, dot-dot-dot display, dot update. And basically what this one does is that it takes anything that came before it, this while loop and draws it on this display surface. So this one. And you could run this already, but you shouldn't because you would not be able to close it. And to close it, we need one more thing and that is the events. And this is just a for loop. And how does usually looks as for event in PyGame, dark, event dot get. So effectively what happens is that when this while loop starts to run, PyGame starts look for all the events. So this is all the different user inputs that are possible. This could, for example, be moving the mouse, or could be clicking a button, or could be clicking your mouse buttons, or it could be closing the window. And this is also something we have to actively check for. And to check for the closing button of the window we need if event dot type equal to PyGame thought, quit. So basically when we look for a different events, we can check whether different type of events at a type could, for example, be mouse button down, where you click your mouse button. And quit is just the X button at the top of the screen. And if that was being pressed, we want PyGame dot quit. And that is the line I talked about earlier that we have to appreciate PyGame at the end to close it. So in the beginning we have initiate and at the end we have quit. So these are the two lines would have program has to run in between. And that is literally the most basic setup you can have with pygame. If around again now, we can see a black screen. We can move it around and we're organic, close it. That's about it. And there is an error message. And that brings us to another part that you kind of need. If I'm PyGame is being closed. This PyGame dot quit doesn't fully close it. And what we need instead is says and sys dot exit. And we're gonna extend this in just a second for now, just follow my lead to horrendous game. Now again, we still see a black screen. If we close it now it kills us properly. And basically what happens is that says is another module that's inbuilt into Python so you don't have to install, you can just input it by itself. And Cisco to some access to system commands. And what happens is that PyGame dot quit only ends PyGame as a module. It doesn't enter code by itself. For that we need syst dot exit. So this one actually closes our program that we're running. This one doesn't close the program. They just closes PyGame, so doesn't close all of it. But with all of the up and down, we have our basic game and we have a black screen that we can move around and we can close. And even though discretize showing black red now, this black screen is being continuously updated in our game loop. So in our while loop here. But there's one more problem I do want to talk about. And that is that the speed of this update is very uncertain right now. So we wouldn't know if this screen is updated at 60 frames per second or a 120 frames per second, or 1000 frames per second, or let say one frame per second. And this can be a problem. And let me explain why. When we run our game, the framework determines how often the calculation is done. So let's say we want to move a picture from the left to the right. So we move the image to the right by five pixels on each frame. Now, if we do this a 100 times per second, or ten times a second really matters. Because if you do this operation a 100 times in 1 second, or ten times in 1 second gives you vastly different pixel measurements. So effectively, the game would run at different speeds depending on the speed of the computer to running on. So we basically have to make sure our game runs at the same frame rate no matter what happens. And we can do that. And to do that, let me close this. We need another variable that I'm going to call Clock. And clock leads PyGame, datetime dot clock. And make sure that this clock is capitalised, at least for the first letter. This is really important. And this line creates what's called a clock object. And a clock object can be used for lots of different things. One of them is that it determines the speed of the game or the frame rate more specifically. And all we need for this is clock in our game loop at the end, dot-dot-dot tick. And now, and to give our gamma frame rate, and I'm gonna give it a 120. And this line basically determines that our games is never going to run faster than a 120 frames per second. So effectively our clock stops to gain when it tries to run too fast. Still a possibility of the game running slower than a 120 frames per second. And this would happen if the game is too busy and at too many elements on the screen that the computer cannot keep up. But that is an issue with game design. That you have to design a game in such a way that never gets too busy and they're never too many elements on the screen. And we will talk about some strategies on how to achieve this later. But for now, let's run the game. And now we have our most basic setup for PyGame. It doesn't lead to anything, but that's going to come in the next video. I will see you then.
7. Shooting Range 2: Surfaces: So another way of a basic window, let's talk about how to put stuff on it. And to do that, we need one more concept and it is called a surface. And be aware here so far, we talked about a display surface. And this is kind of different from a regular surface, but they do have a lot of things in common. So let's talk about them. The display surface as what we have seen in the last video. And this is the windowed player sees at the end when the game is a rendering. And that can only be a single display surface. Now, irregular surface differs from this in two important ways. The first one is that you can have as many surfaces as you want. So what as only one display surface, you can have hundreds of normal surfaces. And the second one is that a surface is only displayed to the player if it is being directly put on display surface. So you could have a 100 surfaces. If they are not being placed on the display surface, they are not visible to the player. And if you want a simple analogy, think of it like making a poster. It really big poster you present to people in the end, that's a display surface, and each surface would be a posted note you put on this main poster. You could have hundreds of post-it notes. If they're not under post that a would not be seen in the end. And these surfaces are basically what you need to put images on your screen. There are some other ways by using surfaces is the primary one. And let's do an example for now. We want to important image and place it on our display surface. And importing an image is very easy. You just need one line of code and then you store this image in the variable. But the image you have inputted is automatically on a new surface and PyGame. So you have it available, but it is not visible to the player. And to make it visible, you have to place it on the screen for another command. So placing images on the screen takes two lines. You first import the image and then he put the image on the display surface. And with that one done, let's go back to the code and actually important image. So here I'm back in my code. And when we set up the game, I'm going to create a new variable and are going to call this one would underscore BG. And now when it aligned to import the background image. And this one is done with pygame si.umich.edu load. And in there we need a string with the name of the file we want to import. In my case, this is what underscore bg dot PNG and a file ending is really important. And another important thing, a script of this game and the image have to be in the same folder for this line to work. That if this image wasn't different folder, then your code, this would not be working at PyGame would give you an error. So make sure you have it on one folder. But with that bond, we have imported in image ever run again. Now, we couldn't be seeing anything because we first have to place this image on our display surface. And this happens again in our game loop. And the line we need is first screen. So we are referencing our display surface up here. And then we have to command blood. And blood takes two arguments. The first one is the service we're going to put on. So this in my case is what? Bg. And the second one is the coordinates where we want to put it. And the second argument is to position where we want to place this surface and be aware to coordinate what you place. It is the top left of the surface you are placing. So my case, this has to be 00. So we place the top-left of this surface on the top left of our screen. And if I run this now, here we have a wooden background. It doesn't look very good and it's a very repetitive. But we are going to improve this and just a bit. And I guess one thing you might have found weird that 00 is the top left. So before we go on for about, let's talk about the coordinate system of pagan. Because this one is a little bit weird. And to understand the coordinate system in PyGame, think back of your math classes in high school, that if you wanted to draw a graph, you needed a coordinate system that has x coordinates on the horizontal plane and y coordinates on the vertical plane. And the origin of this coordinate system is in the bottom left. So if you put a point on 0-0, you on the bottom left corner. In PyGame, this is slightly different. You will still have a coordinate system where x is on the horizontal plane. So if x gets larger, you move to the right. However, the y-coordinates are different. And what basically happens is that why is inverted? So at the origin is in the top left. And if you want to go down, you have to increase y. And if you want to go up, you have to decrease y. And admittedly, this does feel quite counter-intuitive that it just fits unnatural to increase a number and go down. But in most games, this is the default coordinate system that for some reason the standard became that the top left is the origin of the coordinate system. It is slightly confusing, but you are going to get used to it quite fast. But you are going to make some mistakes of it as well. And let's visualize in this coordinate system what I have done in our game just now, I've inputted an image and I've put the top-left of this image on the coordinate 00. So basically what I have done is to put the top left of the surface on the origin of our coordinate system. And since the dimensions of this image are the same dimensions as our display surface, this one covers the entire display surface. And what all it comes down to is that we have a background image and with step one done, let's import one more image and to import another image when you'd have a variable. And this one I have called land Vg and asked us before PyGame dot image dot load. And now I need another string of the name of the file I want to import. And this one I have named land underscore BG, and we still need PNG. So now we have another surface and we have to place it in our game loop. And here's something that's already quite a problem. And let me just use the same line as before and screened upload. And I want to place land BG and for now, let us pass it again at 00. So what we now expect us to see our land image and our wooden image. But if we run this, we can only see our Wouldn't image. And the reason is quite simple. And the problem is that this image covers this image. So this image, what it exists on the screen is behind our Wouldn't background. And basically what happens is that when Python goes through the while loop, it first draws this image that address this image. And then updates it all. So if this image covers the entire screen, then this one would never be seen because always covered by a wooden background. And all we need to fix this is move this one after our wood background. And if I run this now, we can see our land. So just be aware that the order of your code does matter in terms of how stuff is being drawn on the screen. But alright, we don't want our land despite how high up we wanted Rava fervor down at the bottom of the screen. And this one is very easily done. All we need is to change this 0 to, let's say, let's put it at 600 and let's see how that looks. And yeah, this one's getting better. Could almost be a little bit less. Let's go with 560. And yeah, that looks much better. And let me just explain what happened here. That when we place this land image, we place the x-coordinate on 0. So it starts at the point right on the left of the screen. But the y-coordinate is 560, which basically means that we have put 560 pixels from the top and place the image there. Which basically means we have moved it down. And that's basically it. Lets keep on going and add another one. And I have water, BG. And this one is also PyGame dot image dot load. And this one is water, BG and PNG still required. And this one is the water. And we want screenshot blood and water BG. And now again, we want to place this on the same x-axis, so at 0. But there's one needs to be a little bit further down than the land one. So this one I'm going to put, let's say 600. So if we run the code now, we have all water and this one right now feeds a little bit too high. So that's pull it down a little bit further down. So let's say 640. And Gim. There we go. Now we have free images drawn on top of each other. So we have effectively imported three different images and we have drawn on the screen after each other, sort of being put on top of each other in the game. And that is already quite a good start. And with depth and done, let's do our first exercise. And the exercise is going to be that you place a couple of clouds at the top of the screen. And this is going to need two steps. The first one is that you have to import clouds. And in the game folder, there are two files then Cloud one and cloud to import both of them. And in the game loop, you screened opted to put lots of clouds on the top of the screen. And for that, you will need to move both the x and the y coordinates. So far we haven't moved the x-coordinate. So try to experiment with this and see how far you get. And the end result should look something like this. But you can move the cloud so ever you want their specific position doesn't really matter. Pause the video now and see how far you get. Alright, now let's do together. The first one we need is to import both clouds. And I've caught them killed one enclosed tube. So I'm gonna call them the same and decode variables. So we have Cloud one and we input them in the same way as usual. So PyGame dot image dot load. And I called Cloud one dot PNG and cloud to play game dot image dot load and Cloud two dot PNG. So now we have the surfaces of the clouds. We have to put them on the screen now. And this one I'm going to do after all our background images. And all we need for this is screened dot. Then one of the clouds. So Cloud one. And now we need to coordinate and let us put one at the coordinates 150. So we move this surface 100 pixels to the right and 50 pixels down. So if we run this now, we can see one cloud in the top left of our screen, and that's all first cloud. So now we just need to repeat this process a couple of times. So I do again screenshot doublet. This I want to place clout to. And for the coordinates, I'm going with a 170. And AT. Let's run this now. We can't see both clouds on top of each other with cloud to being on top. So this covers using the x coordinates. But there's one thing I haven't specifically covered yet. And that is Teddy can reuse the surface as many times as you want. And let me demonstrate. So I can use screenshot bled and use Cloud one again and place it on the coordinates 60410, completely random numbers. They're just somewhere at the top. If I run this now, we have our first cloud twice. We have one cloud here and one cloud here. And they are the same image. We just put them twice on the screen, would just perfectly possible. You can reuse a surface as many times as you want. In fact, when we later put the targets on the screen, because it's all the same picture that's putting the screen multiple times. And let's do a couple more clouds. Let's say screenshot. Again. Let's use again ClO2. And I wanna place this one. Let's go quite a bit further to the right. So 1090, run this again. We can see another cloud. And let's do one McLeod a bit more in the middle, which would be screened. Choose Cloud one. And let's put this 412551 off that London. We have lots of clouds at the top. You couldn't move them wherever you want, but do make sure they're quite far up on the screen. So do you have placed in the middle 40 actual targets? But with aloft upon done, you have a basic idea of how to put images on your screen. And all you really need is to important image and then place it on the screen and the different coordinates. And always run by you place a top left of your image. How ever? Right now, all of this as entirely static, which is very boring to look at. So let's animate this and that's gonna be the next video. I will see you then.
8. Shooting Range 3: Animations: Hello and welcome back. And in this video, we are going to take this static image and add some animations towards it. And specifically, we're going to take the foreground land and water. And at some basic animations, which basically means we are slowly moving it up and down at certain intervals, which is actually really simple thing to do. So let's jump right in. And to understand how to animate something in PyGame, You have to have an understanding of the game loop and how PyGame draws within that game loop. And let me use the land background as an example. Right now, the background is being put under position 0560 on every single cycle of that loop, disposition is always the same. And as a consequence, when we see it on the screen, it looks static, but it doesn't have to be. We could give it a different position every time. And how we animate things and PyGame is that we incrementally changed as number so that it moves a couple of pixels fervor, up or down. And D small changes to us look like a moving picture. So all we basically do is instead of putting this one servers on the same position on every cycle of the loop, we add a slightly different position on every cycle of the loop, and as a consequence, we get an animation. So let's implement all of that right now. So here I'm back in my code, and here I have our land background that's being put on the screen. And what I want to do for now, instead of this 560, I want to have a slightly changing number on every single cycle off the loop. And to achieve that, I first have to declare a variable that I'm going to call land position. And this is going to be the y position. So let me add y and the end as well. And this is going to be 560. So exactly what we had here before. So let me replace this with the variable lamp position y. So this Das right now at the exact same thing. If I run the code, we still have static land. So no change there. How ever what we can do now, we can take this land position y and add plus equal to one on every single cycle of this while loop. So if I run the code now, we can see our land slowly going down. Obviously, it is never coming up again because this number is always increasing. So it never turns around. But by itself, this is the way to animate stuff and PyGame, obviously a very simple example, but it is the way to go. And here, it is also important to note that just as I've explained earlier, if you add numbers to it, you move downwards and PyGame. And if you subtract numbers so minus equal one, then we go upwards. So here we can see our land going upwards. And this is the coordinates of Smith explained earlier that if you want to go down and PyGame payoff to add numbers to the y axis. If you want to go up, you have to decrease the number on the y axis. So this is quite an important thing to remember and also quite an easy thing to get wrong. All right? What I want to do now is that this isn't continuously moving in one direction. Instead, I want to give it some boundaries so that if this lamp position y. Gets smarter than certain position, it should reverse the speed of this direction. And for that, we are going to need another variable that I'm going to call land speed. And for now it's going to be one. And this land speed is going to replace this variable here. So LAN speed. And right now, this is going to have the same result. But what we can do now is changed to speed of this, so that when the land position y exceeds a certain number, then we can reverse this land speed and multiply by minus one so that it is moving in a different direction. And all we need to do that is if land position y is smaller or equal to, let's say 520, then we want land speed multiplied by minus one. And let me run this not just to illustrate what happened. So we're going up and now were going down. And let me illustrate what happens here. When we start with lamp position y minus equal land speed on every single frame, lamp position y is going to be slightly smaller, so it won't be blood. The land background on the screen is gonna get slightly higher on the screen. But obviously by itself, this would go on continuously. We have to limit all of this. And how we do that is with the if condition that if land position y is smaller or equal to 520, then we want to reverse the speed, which we're going to if land speed minus equal one. So if this condition is met, then the land speed will increase the y position and the land is going to go downwards. And via Dad, we have one boundary. But obviously after this one, I will able to continuously go downwards. So we have to add a second boundary to it that if it exceeds a certain number, than want to go back negative again. And this we can also do very easily that or land position y is greater or equal and let's say 600. Then we also want to multiply the landscaper minus1. And if I run this now and it's going upwards, it's going downwards, and it's going to continue like this forever. And we have slightly moving image. So that's actually quite simple. And I hope the logic here makes sense. And you can actually try this for yourself. And that is going to be the exercise at what I've done with the land. I wanted you guys to do for the water to water moves slowly up and down. And you can play around with this quite a bit. You can give it a different speed, you can give it different parameters in terms of how far up it can go. It's entirely up to you. But what I want you to achieve is that this water is moving up and down continuously. Tried as now and see how far you get. And after you done, we're doing it together. Alright, How did it go if you achieved AS well done? If you didn't, then let me know why you couldn't achieve it into comments then I'm happy to help you. But let's turn it off this together. So here I'm back in my code. And the first one I'm going to need is two variables that mimic these two. Instead right now we're gonna do it for the water. So I'm going to call it water position y. And to what her position why we had so far is down here. And let me add some space is 640. So there's going to be 640. And also give it a water speed. And what is speed for now let's say this one is a little bit faster. Let's go with 1.5. But these numbers are entirely up to you. You can put in anything you want in here. Really just focus on what you think looks good. That's the only thing that really matters here. But alright, with that Pandan, back in our game loop, what I want to do is replace this x and at 40 with water position y. And then before that, I want to add water position y plus water speed. So if I run this now, we should already seen animation and we do. But obviously the water's just going downwards, which doesn't help us all to much. So again, we need to copy this kind of logic here that the water's moving up and down continuously. And let me add it right below. So if water position y is smaller equal, let's say in this case we go 600. Or water position y is greater or equal than, let's say 680. But again, these numbers entirely up to you, play around with them and see how it looks like. Well, okay, if that is true than water position speed minus equal one. And if I run this now, then it, Yeah, it's working. And I think the top water position is actually quite high. We could actually set this a little bit lower. So instead of 600, let's say we put us at 620, is might be looking better. Yeah, this doesn't look better. But okay, so I hope that was manageable. And as one important thing I do want to talk about, and that is that you have to use smaller equal, or greater equal when you do comparison operators and PyGame or in any video game for that matter. And what you absolutely want to avoid is equal to operators. So what you should not be doing is water position y is equal to 620 for example. And the reason for that is quite straightforward. That for our water speed, we are adding 1.5 pixels to the y position on every single frame. And because of that, it is quite unlikely that we're ever going to hit exactly 620. It is much more likely would hit something like 619.5. And if that is the case, this if condition would not trigger, so the water would continue to go upwards. And this is something you see all the time and video games that you are moving pixels quite fast on the screen. And it can happen really often that you don't hit pixels exactly. So if you missed them by one pixel and objects overlap just slightly. And if you use equal two operators, then you will really often miss the exact collision between objects and they don't make sense. And in the next video, we are going to add our mouse cursor to all of this. I'll see you then.
9. Shooting Range 4: Mouse and rect: Hello and welcome back. In this tutorial, we're going to add a cross a two hour game. So you can actually see the mouse in the game, which is already quite a big improvement to it. But to achieve all of that, we have to cover a new concept. And that is we rectangles and dead, two reasons why rectangles are becoming really important. So let me go through them. And this is also going to be a really good opportunity to explain what rectangles do and PyGame, so far, we always inputted an image and put it on the screen. And this worked fairly well. And we could import a crosshair and put this in a certain position. And this could even be the mouse position, at least roughly, and this would be a start. However, there's one problem with that. At when we place our image, we always place the top left of the image in a certain coordinate. And there's no other way for us to place the image. So if you wanted our crosshair to follow the mouse, this would have some slight and accuracy because there would always be a slight difference between the position of the mouse and dissenter of the crosshair. So that's the first problem that we need more control on where to place our surfaces. The second problem is that we cannot check collisions with surfaces. And here's what that means. What we basically going to do when to finish game is that if the mouse position overlaps with the position of a duck and we click the mouse. Then we check if these two objects are colliding with each other. So if the position of the mouse and the duck position are in the same position. So this would basically be shooting at the duck. But for that, we have to be able to check collisions and surfaces. We cannot do that. So the second problem is that we have to be able to check collisions and rectangles solve both of these problems. So they are incredibly useful for general game development. Let me explain what they are. A rectangle or rect, as it is called an PyGame is basically just the rectangle. It's not that complicated to be honest. And Allah rectangle really does, is that it draws a rectangle around the surface. And then this rectangle can be used to place the service in a specific position. And also to check collisions with other rectangles or specific points on the screen. So it's basically a frame you can put around to surface to get more control over the specific surface. So let's implement all of this. And then I explained rectangles and more detailed when we work on it in the code. So here we are back in our code. And the first thing I need is to impart a crosshair. And I do this and start off the code, and I just call it crosshair. And we're going to import it in the usual way, sort of pygame dot image to load. And I caught a file cross haired dot PNG. So now we have a cross here. What we want to do now is put this on the screen on the exact same position where our mouse is going to be. And to do that, we have to check the position of our mouse, which we can do in the event loop. So here, now, right now, we are only checking PyGame but quit. So if the game is being closed, now we have to add another event dot type. So now we're checking for different kind of event. And what we want to check is pygame dot mouse motion. And what most motion is is that whenever you move the mouse, this event is being triggered, which is basically all the time. And inside of this, we want to check exactly where the most east and then we use that information to place this crosshair. And there are two different ways we can check the mouse position. The first one is to use this event. So position B, event dot POS. So event dot pause just gives you the position of where this event happened. And what is event happened is just wherever this mouse motion happens to be. So this would be one way to get almost position. Another way would be PyGame dot, mouse dot, get underscore PaaS. And this would be a more general way to get your most position. And this would work even outside of this if statement. But in my case, event pause is the easier way. So now we have the position of our mouse. Now we need to figure out how to place this crosshair on this position. And we could do something like screen, dot, split, crosshair and event pause. This one would work and to swiftly looking quite similar to something like this. Because event pause gives you a tuple of an x and a y position. So this greened up blood would work at least in theory. But the problem here is the first problem I talked about earlier, that Demos position would be in the top left of the crosshair, which would be very inaccurate for the game and quite frustrating. So we have to solve this in another way. And how we're going to solve this is we're going to create a rectangle around our crosshair surface. And we placed the middle of this rectangle on our screen. And then later on in the code, we take our surface and put it on this rectangle, which is sounding quite complicated, but let me go through it step-by-step. The first thing I want to do is to create a cross hair undiscovered, right? So this is a new variable. And what we want to do, and this one is to take this surface and put a rectangle around it, which we're gonna do with crosshair, underscore, get wrecked. So now we have drawn a rectangle around the surface. You wouldn't be able to see it, but you can use it to place the surface. And every surface has a couple of positions on where you want to place it. And the one that we to use right now is center, which is right in the center of the rectangle. And this center gets event dot. So now, instead of putting the image on the screen immediately, instead we're drawing a rectangle around the surface and putting this rectangle around the center of our mouse. But if we're under gave now, we would not be able to see anything. And the reason for that is quite simple. We first have to use this crosshair rectangle to place the surface itself. And this happens again forbidden here in our game loop. And let me place it below the clouds. And we still use screen doublet. And we want to bled our crosshair. So this one crosshair. So just one stays just the same. But now, instead of having one specific position like for Cloud one, we want to use the rectangle and this can be used immediately. So cross their underscore wrecked. And if I run this now, we can see our Coursera. But it works quite well. And do note here that the cross it is appears below the clouds, but this above the water and the land. And the reason for that is because in the code it happens before the clouds, but after the water and the land. And this is basically using a rectangle. So let me go over the logic here of what we just did, because this one probably is quite confusing to you right now. The first thing we did was to import the crosshair picture. Is that something you have seen before? And this is, I think, quite simple. So now we have our image on a new surface, but we don't immediately put it on the screen. Instead, if we draw a rectangle around it, and the center of this rectangle is on our mouse position. And this rectangle also has the same positions as our crosshair surface. And then in the game loop, when we put this surface on the screen, we don't put the top left on a specific position. Instead, we're using a rectangle with the same dimensions as the surface. Place it on a specific position on discrete. And we have not been checking collisions as going to come in the next couple of videos. But rectangles are also required for collision checking. But before we're getting to that, we first have to put some ducks on the screen. And this is also going to involve rectangles. And I will see you there.
10. Shooting Range 5: Adding Targets: Hello. In this tutorial, we are going to place our ducks on the screen so that we have some targets to shoot at. And we are going to do all of this also with rectangles. So the process is going to be kind of similar competitive last video. And I think that's going to be a perfect way to practice a rectangles and a little bit more detail, because rectangles usually takes some time to understand and PyGame, let's jump right in. Let's begin with a recap on how we imported the cross here and the last tutorial. We first import it in image, and this image was put on a new surface. In next step, we put a rectangle around the surface and we put the center of this rectangle somewhere on the screen and deposition was whoever our mouse happened to be. And then in the game loop, use this rectangle to put the surface and a specific position. And that way we ensured that the center of our surface is always going to be on the mouse position. And for our ducks, we are going to follow quite a similar process. We are still going to import a single image. That part stays the same. And we're also going to put a rectangle around the resulting surface. So these two parts stay exactly the same. But now instead of putting this rectangle on a specific position on the screen, we want to put it on a random position on the screen. And also, we don't want to create a single rectangle. We want to create a list of rectangles so that we have multiple targets. And then in the game loop, we're going to cycle through this list and put a surface on each rectangle. Let's actually implement the logic for our ducks. So here I'm back in my code. And a very first thing I want to do is to import a picture of the duck. And I'm going to call the variable duck surface. And is going to be PyGame dot image dot load. And I called the file Dr. PNG. And as always the code and to file have to be in the same folder. So now we have our surface. And next up, I want to put a rectangle around it. But I don't want to create just from one rectangle. I want to create multiple rectangles and store them in the list. So the first thing I need is a list that I'm going to call dark list. And this is just going to be an empty list for now. Or we're going to append lots of stuff in just a bit. And now we want to create a duck rectangle. And this rectangle, we gotta just as before, dark, surface dot get rect. And dissenter of this rectangle is going to be random x and random y. So obviously these two wouldn't work right now there just to illustrate that we wanted to put this center off this surface in a random position on the screen. And the first has to be a random x integer is second value has to be random white integer. So we have to figure out a way to create random numbers and PyGame or in Python in general. And to do all of this in Python, we need to input and never module. That is called random. And random gives us lots of different ways to create random numbers. And to my case, I'm going to use rand range and it's quite a simple function. All it really does is that it takes stop physician and an end position, and then it takes a value in between. So we effectively take a random point from a range and let me create some new variables to store them. It's so R1, so ducked position x is going to be random.random range. And I wanna put these values between, let's say 5300. So why did I choose those values? Well, a la main display surface has a width of 100,280. So I basically put the targets somewhat in the middle of that. And the main reason for that is that our targets should not be going outside off the screen because I would look a little bit weird. And to achieve that, I put a little bit of a distance between the edge of the screen into area where targets can be. So the furthest to the left, the centre of a target could be exposition 50. The furthest to the right. A target could be, would be one hundred, two hundred. So that way it Target could basically never go outside off the screen. And we have to approach the duct position y end. Quite similar wastes. So when he'd random.random range. And now we need a position from the top of the screen to place the targets. And here we have to be a bit more careful because the bottom of our screen is covered by water and land, and on top of our screen is covered by clouds. So we need to be a bit more specific here. And in my case, by trial and error, I found a hundred and twenty and six hundred work best. So they would take a 120 pixels from the top and also 600 pixels from the top. So at this roughly 500 pixels, this is what all the targets are being drawn on the vertical axis. And now inside of our surface, we just need to duck position x and position y. So now we are creating one duck rectangle. And we wanted to append this dark rectangle to the doc list. So doc list, dot append, and duck rectangle. So now we would have one rectangle, which is a good start. But we want, let say, 20 rectangles. So this one wouldn't be good enough. We have to repeat this operation 20 times. And to achieve that, we need a for loop. So let me attend all of this. And what I want is for duck in range, let's say 20. So now we're repeating this operation 20 times. And let me explain how to follow up your works that we look for, for duck in range 20. And this range 20 gives us 20 different numbers, starting from 0 going all the way to 19. And this doc is then going to be 01234 all the way until it reaches 90. And we're not going to use that value whatsoever. All we really care about is that this operation is being repeated 20 times. And if we do that, we're going to create 20 different rectangles and placed them on random positions on the screen. And at the end of that, we have a list with Office 20 rectangles and we can loop over them. So that's basically all we need to create all the rectangles. But obviously, when we run the game, we can't see anything right now. And that is because we have to put a surface on this rectangle. And this is going to happen in our game blue. And I'm going to do this below our crosshair sorta crossover goes above the ducks. And now all we need is for dark, wrecked in dark lists. And just as usual, screen dot doublet. And I called this duck surface and dark rect. So if I run the code now, we can see all of our ducks. And obviously I should have drawn him behind the water because this looks quite weird right now. And it's quite a good way to illustrate why the order of the Cold War really matters. Because having these ducks in front of the land looks really weird. But if you look at the top, they are behind the clouds and this is quite nice. So it just gives some depth to our screen. But okay, to put other ducks behind the land, we just put, let's say here. So they're right on top of the wooden background, but behind everything else. And let me move out of this. If I run this now, we can see that we have some ducks behind it as well. And they're roughly in the middle and they're all randomly distributed. And that's basically all you need to create our ducks on the random position on the screen. I hope that made sense. And if you are still confused about rectangles, just let me know in the comments and I'm happy to help you more of that. But with DEP on done, we can come to some actual collision mechanics that we can actually click on the ducks and then they disappear. I will see you then.
11. Shooting Range 6: Collisions: Welcome back. For this tutorial, we are going to create our collision mechanics so we can actually shoot at the ducks, which is already getting quite far towards having a finished game and we're actually quite close to finishing it. So let's jump right in and create a bullet shooting mechanic. And let's talk about what we are going to do specifically. They talked about this a tiny bit in an earlier video, but let's go over this and full. Right now on our screen, we have two different kinds of rectangles. On the screen itself. We have lots of ducks and around each dark das or rectangle. And then around o a mouse, we have another kind of rectangle, and that is for the cross there. And effectively what we are going to do is to check if the cross, a rectangle and a duck rectangles are overlapping and we are pressing the mouse. Then we are going to destroy the docs that is overlapping with the mouse. And this would give the illusion that we have shot at the dock. So what we are effectively looking for is a collision between the crosshair rectangle and what doc rectangles. And this is done with the method collide wrecked and other collide wreck does is it checks if two rectangles have been colliding or overlapping, which is basically the same thing. So let's go into our code and actually implement all of this. So here we're back in our code. And the very first thing I want to look at is that we can check for mostly, which happens fervor in the event loop. And we already checked for mouse motion. And to check for mouseclick, it works in quite a similar way. So if event dot type equal to PyGame dot mouse button down. So this checks if any mouse button has been pressed on. And instead of that, we need to give it some functionality to check what is going to happen if we press the mouse button. And in the simplest possible terms, what we want to do is if our cross her rect is collide correct. With it dark, wrecked. So we're checking our crosshair and we want to check if it's colliding with another rectangle, that is the duck rectangle. So anything that's in this list, this would not be working because they're all in this list. So what we first have to do is loop over this doc list, kind of like we have done just before in the game loop to draw them. So basically what we do when we click the mouse button, we want to loop Ford dark in dark list. So when we click the mouse button, we are looping for every single duct rectangle in the doc list. And then if our cross here collides with any of these dark rectangles, then we want to do something. And what this line here returns is ever true or false. So if there's an overlap that is going to return true, if not, then it returns false. Then what we can do is if this line is true, now we want to do something. And for now just to check if this is working, let's just print duck hit. And if I run this code now, we can click on a duck and we can get ducking down here. But there's a problem with that kind of logic right now. Because we don't know which doc has been hit, because we'd just go through the entire list. And if any of these tax has been hit, we print something. But we don't know exactly which doc has been hit. Which we kinda need to know because let's say we wanna click on this dark here. And then when we click on it, it should disappear. But to make it as appear, we have to know which dock we have been shooting at. Which fortunately we can do quite easily. And to do that, we need enumerate. And this goes right here. And if you're new to Python, you might not be that familiar with enumerate, but it is incredibly useful to loop over a list. Basically what a numerate does is that it gives you an index of what item you are looking at in the ductless. And you have to add this index in the beginning. And now this line here would work. And basically what happens is that this enumerate gives us the item that we're looking at or the index. And then this index can also be looked over. So then let's say on the first doc item, this one's going to be 0 and this duct rectangle is going to be the first rectangle in this list. When we come to the second one, this index is going to be one, and then we have another duct rectangle. Then our next item, this is going to be two and then this is going to be another rectangular. And that way we can always tell exactly on what number we are inside of our loop. And to check if this is working, we can just print the index. So if we run this now, applique on a duck, we know distance is number 12. If I click on another duck, duck, number nine, if I click on this one, we have Doug aid through lots of different ones. So now we have a method to check which DAC we are looking at, what shooting at Robert. And we can use this to lead the duck from the list and then it disappears from the screen. So basically all we need to do is if we are clicking the mouse button down on a specific duck, we want to remove this duck from the list. So then when we come to the actual game loop and we draw off them, this doc is not going to be drawn anymore. And to delete a duck from a list, or we need Dell doc list. And now nifty index of what we want to delete. So what happens in here is that we delete from the list a certain index, the index we get from here. So whatever duck We have been clicking on, and this should be working already. So if I do this now, and yeah, we can click on a duck and they are disappearing. There's one problem with that, that, Let me illustrate this with these two ducks. If I click on this, okay, that example, let's say I click on these two ducks. Audi's free vaccine offering disappear. And the same for this one. And for these as well. That right now, if our crosser rectangle overlaps with multiple ducks, all disappear. And let me illustrate this. So I'll cross a rectangle is not 1. Instead it is quite a large area of the entire rectangle around to crosshair. And because of that, it's quite possible that it overlaps with multiple ducks at the same time. So they would all trigger collide wreck being true. And this isn't ideal. But in our case is our game is that simple? We don't worry about it too much. Just do be aware. This can be a problem. But alright, now we only need one more step to actually finish the game. And that is to add a wind condition that if all dogs have disappeared, then we want to write you win on the screen, or really.
12. Shooting Range 7: Displaying text: Hello and welcome back. And in this video, we keep them working on our game. And the one major thing that is missing right now is that once we are fit, all the ducks lab meters go through it really fast. Then, well, nothing really happens. You just see this screen by itself and the game never ends. So what we are going to end for this tutorial is some kind of text in the middle of the screen that says you have one day game. Nothing particularly fancy, but at least some kind of closure. So there are two things we have to cover in this tutorial. Number one is that we have to add text to PyGame. And number two is that we want to show this text only after certain condition has been met. And that condition is that all the ducks have disappeared. And that's basically it lets come right in. So let's start working on the first problem that we want to display some text. And to display text and PyGame, you need a couple of steps. But if you have paid attention in the last few videos, quite a bit of this should look familiar. So let's go through it step-by-step. The very first step you need is to create a fund object. And oldest fund object contains the font itself and the text size. If you don't know what a font is, it's basically the styling of a text. So really famous fund for example, is Times New Roman, or it is also Aereo. And there are hundreds of different fonts. And text size is well, haulage to Texas. So that's gonna be the first step. And in the second step, you use this font to render text, which basically means you're writing new texts. And this new text is going to be put on its own surface. And from here on out, things should be looking quite familiar. Because this new surface you can just put on the screen or you could put a rectangle around it and then put this rectangle on the screen and pass the surface into it. So let's implement this. And for now, I'm just going to show text. I'm not going to worry about showing this text only after certain condition has been met. So here we are back in the code. And the very first thing we need is to create a font object. And this one needs to be stored in a variable. And I'm going to call mine game fun. And to create a font, we need PyGame dot font, font. And make sure the second Fund has the first letter capitalized. That is quite important. Right? Into this, we need to pass in two arguments. The first one is the font we want to use, and the second one is to text size. And in my case, for fun, I'm going to go with none. Which basically means that we're gonna use the default font pygame has. And then when your text size, and in my case, I am going to go for, let's say 60 were quite large text. Now we have a fond, and now you'd use this font to render text. And this is also going to add a new variable. And this variable is going to store an entire surface with the text on it. So I'm going to call this text surface. And how we render the font as you first have to font. Then render. And number two, pass and free arguments. The first one is the actual text we want to render. So let's say for now, because it's just going to be test. Next up. We have the information if the text is anti-aliasing or not. And all this means is if the text is a bit sharper or not. And you could write true or false in near the impact is going to be quite minor. But in my case, I'm going to go with true. And finally, we're going to need a colour. And in my case, I'm going to go with white and to create a color. When he was caught an RGB tuple. And let me first pass on the color and then I'm going to explain. So I've passed in three numbers into this tuple. And these three numbers stand for the different colors. The first one, this one here is the amount of a we have. And this could be anything between 0255. And this number determines how much red we are going to have in our RGB tuple. If there's almost 0, we would have no record whatsoever. So it would be black. If this one is 255, we have the full amount of red. And the second one is the amount of green we have in our tuple. And this works just like we've read before. If didn't a 0 data's the absence of green. If this one is 255, we have the full amount of green. And then if you go lower, so let's say if we go a 130, you have about 50% of green, but i want for green. And then finally, we have the blue colors. And same principle again. If you have 0, you have no blue. If you have 255, you have the full amount of blue. And if you have something like 200, you have something like 70% of fuel. And if you mix the full amount of all the free colors, you get a white color. And basically what RGB means is red, green, and blue. And this is how you create most colors that you just combine the most basic colors. You put them together. Now we have a surface with our taxed. And the only thing left to do is to put this surface on our actual game. And this atlas fervor down again in the game loop. And let me put it right at the top above everything else. And this is again screening of blood. And for now I'm just going to put in a random position, but we are going to work on putting it right in the middle in just a bit. And I called it taxed surface. So we need to surface again. And now a position where we want to place it. And let's say for now, we're just going to be three hundred and three hundred. And unless I made a mistake, now we should be seeing text. And there we go. We can see test. And this is a good start. But there are a couple of things we do want to change. Number one is that this shouldn't say test. It should instead say something like you one. Number two is that I want this text right in the middle of our screen. Because right now it looks a little bit of, and the final one is that we should only show disk taxed once all the ducks have been shot. So let's work on these things one by one. And the easiest one is to change the text. So if I go up and here we created a text. And I just needed to change this test to u1 or really whatever kind of information you want to pass in here, any kind of string is going to work. And with that we're done. Let's work on the condition that this tax is only going to be shown once all the ducks had been shot. And effectively what we want in terms of game logic is that if this doc list is empty, then we want to show it taxed. Because if this list is empty, we noted all dogs have been shorter. And in our game loop, this can be done really easily. So here we are drawing all the ducks and we check if this list has anything in there. So right afterwards, we can add an if condition. If the length of our doc list is equal to 0, or you could even be smaller or equal to 0. Both would work. Obviously, you can't have a list with fewer non-zero entries that just wouldn't exist. So both would be fine. It doesn't really matter. But now we check if there is no doc in our doc list, which means there's no Duck left on the screen. And once we have that, we can only done raw our screen. So this part here. And let's actually try this now. So our code runs as well. Let me just chewed old ducks. And there we go. We can see our text now only once all the ducks have been shot. So that's a pretty good start. So there's one thing left. And that is that this text should not be on a position for three hundred and three hundred. Instead, it should be right in the middle of the screen. And that is going to be your challenge right now. That I want you guys to use a rectangle to place this text surface right in the middle of the screen and pause the video now and try this for yourself and see how far you get. And once you are done, we're going to have a look at this together. Alright, How did it go? I think there should have been quite doable by let's go through it together. So here I'm back in my code. And the first thing I need is an actual rectangle around this surface. And I'm going to call this texts underscore wrecked. Otherwise we get this with texts Surface dot get wrecked. And this will be giving us a rectangle around the surface. And well, all we really need to do to put it in the middle is to add Center. And now many dimensions of our screen, which are 1280 by 720. So we just need to divide these two by two. And then we have the millivots screen. So this will be 640 and run at 60. So now we have a rectangle, and the center of this rectangle is right in the middle of our screen. And then when replaced this surface right here. Now we don't want to place the top-left on position three hundred and three hundred. Instead, want to place it on text rectangle. And that is pretty much it. So let me try this again and I'm going to make one little change that we only have one dark side change this range to one source, only one dot on the screen right now, remove it. We have u1 right in the middle of the screen. And that is basically it for the most basic kind of game. There's going to be one more video.
13. Shooting Range 8: Refinement: Hello and welcome to the final video on this game. And we're only going to add some final touches to it. So nothing major's going to happen in this video. And the two things I want to work on in this video is to hide the mouse and to improve the collision mechanics. So let me explain what that means. The first one might have been confusing for you because whenever court is videos, I don't record the mouse. So obviously you couldn't see the actual mouse pointer in the game. But when you type the code yourself, you should be seeing your mouse cursor, which looks a little bit distracting. So we're going to add some code to our game to hide our mouse cursor, which is literally going to be one line. It's super easy to do. And the second one is that our collision mechanic can be improved quite a bit. So let's jump right in. So here we are back in our code. And let's say I'm gonna add this right at the top. And what I'm going to add is one line to hide the mouse. And all we need to address any kind of mouse functionality. Mpeg-1 is pygame dot mouse. And what we're looking for a set underscore, viz, a bill. And this one needs to false. So now when you run the code yourself, you should not be able to see the mouse cursor. You would only see the crosshair. But if you go outside you can see our mouse cursor again. And that's already it for the first, quite an easy thing to add. And without London, let's go to the second I will collision mechanic and and let me go down. It is right here at right now, which like our crosshair rectangle, if this one is colliding with any of the duck rectangles. And instead of checking the entire rectangle, what I want to check is only our mouse position. So let's get rid of all of this for now. Well actually let's put it all into a common so you can have a comparison. And what have you so far is collide wrecked, but there's another commodity check collisions and that's collide point. And collide point checks if one rectangle has been colliding with a specific point on the screen. And a specific point we want to check is the one most cursor or the position of almost cursor to be more precise. And it can be done actually really easily. So the first one is the duck rectangle. And what am I doing this rectangle is to check collide hot. And now you tell it which point we want to check for. And in our case, we can just use events again just as before. And that is already all we needed. So let me get rid of this common enough. And if around the game now, and let me click Close to the mouse, this wants to works, but if I click closer, now, it only really works. Gonna click right on the duck. Obviously you still click on the rectangle around the duck with the click right above the tail, the sum would still work. But now let's say here we have a couple of ducks right on top of each other. If I click on the deck on top, on this one is going to disappear. And I really have to be a bit more precise now. And here's another good example of these two ducks. If I click on the right, this one's all you want to disappear. And on the left, this one's also going to disappear. So with this one line, we have improved the collision or the bullet shooting mechanics quite a bit. But alright, that's basically our entire first game. So congratulations, you have made your very first game. And Python, obviously, it's quite a simple one. But in our next game, we are going to make a much more complex game. So I'll see you then.
14. Meteor Dodger 1: Intro: Alright, hello and welcome back to our second game and PyGame. And in this game, we're going to make a spaceship shooter that is going to look like this. You control a spaceship and you can show that meteors. And the basic point of the game is that they do meteors and you try to survive as long as you can. And once you have been hit five times, the game is over and you get a high score. It's pretty simple as games goal. But we are covering quite a few more topics. So for example, we cover a health system. We are going to cover a bullet shooting mechanic where can actually see the bullet. We're also going to cover different kinds of timers that is going to become quite important. And most importantly, we are going to cover sprites. And sprites are one of the more fundamental concepts and pygame that are going to help us organize all the other elements in our code. So let's talk about those in this video in particular. So what's a sprite? Now to understand what that is and why it is important, let's look at our last game. In here. Even to draw a very simple graphic, you need to add lots of different code. You have to import a surface, you have to put a rectangle around it. You have to move that rectangle if you wanted to. And then you have to draw on off this inner game loop, lots of different steps. And you have your code scattered all around to program. And really it's not very convenient to work with. And a sprite is basically had to organize on of this better. So instead of having four different elements all across the screen, you put all these four elements into one class, and then you only call this class to draw this object, which makes our code significantly more organized. But the basic logic is still the same. You're still creating a surface and a rectangular onto surface. But no, both of these elements are inside of a class. And then you draw all the elements from this class. So the point of the sprite class isn't that you have less CO2, right? Instead, the point is that you have code that is more organized and easier to work with. But sprites have quite a few other advantages besides managing your code better. And one of them is that you have groups of sprites. So when you draw a sprite, it don't just draw despite itself. Instead you put destroyed intragroup and then it can draw every sprite inside of that group. And groups would also allow you to update lots of sprites simultaneously. And we are going to use this later on. But basically, every sprite and pygame has an update method inbuilt. If you're on update on a group, oldest sprites inside of that group will run their update method themselves. So having sprites and groups is a really easy way to create lots of different elements on your screen and moved them simultaneously with very few lines of code, something that you could do and the previous approach, but that would take much more code. And that's basically it for sprites. They are there to make a code a bit more organized, and we are going to use them quite extensively in this game. So let's actually go into the code.
15. Meteor Dodger 2: Sprites: Hello and welcome to the first proper video on OS spaceship game. And in this video, we are going to cover two major things. The first one is that we are going to create a basic setup for our code. And this is the easy part because we have already seen all of this in the last game. And I'm going to reuse most of the logic for the basic setup. But the second part is more important that we want to use a sprite class to create Alice's spaceship. And for now it can't move it kind of redo anything. We just want to display a sprite class that has a spaceship in it. So these are two things for this video. Let's start with the first one, or basic setup for pygame. And for that, I'm going to start with the same setup we had earlier. So here I'm back in my code and this should look fairly familiar. So on the first line I input PyGame ANSYS. Next up I initiate pygame, and then I create a display surface so we can see something on the screen. Next up recreate a PyGame Clock object, and this one later on we're going to use to control the frame rate all the way down here. And after that, we create our game loop. And then the game loop we check for events. And the only event we check for right now is that the game is being closed. And then we uninitiated pygame, and we'll just close the entire program. And then at the end of the game loop, we use update to draw the frame. So all of this we have seen in the last game, and I'm going to assume that you have at least the basic idea of how all of this works. If you're confused about this chapter first video in the last game, this one explains all of this in more detail. But there's one more thing I do want to add to it that when we run this game right now, it is completely black. But for our background, I don't want it to be black. Instead, I wanted to be a dark purplish color. And this we can change quite easily. And all we need to do is to take this entire surface and fill it with a color. And we can fill any servers with a plain color very easily. All we'd just an a off the surface, then dot fill, and then an RGB tuple of the color we want to fill it with. And this is working Wolf of display surfaces and those surfaces, so we can use it on both. And in my case, I want to fill my screen with the RGB tuple 40 to 4551, which is let me show you it. Dark, ish gray properly color. And yeah, that's our basic setup for now. Now we come to the second part and that's to create our spaceship. And this is going to happen when a sprite class. So let's talk about Sprite classes in general. And the first thing is that you have to create a class first. So we always into class keyword and then the name of the class we want to create. In my case, this is going to be spaceship and a sprite class. And PyGame always has to inherit from a specific class in pygame that is called PyGame dot sprite, dot sprite. And this is a fairly empty class, but has some functionality that our sprite classes need. So it's basically a template that we can add quite a bit of detail to. And then in this class, we first have to make sure we get all the functionality from this class we inherit from buf super.onCreate. Then we have to give it a surface, and then we have to give it a rectangle. And these are the basic things that we have to create in there. So let's implement this for now. So here I'm back in my code. And the very first thing I need is to give me some whitespace. And I want to create a class that I'm going to call Spaceship. And this class takes inherit from PyGame, looks bright. Dot sprite. Now when creating this class, we need deaf underscore or double underscore in it. And the thing that always needs a self. So then when we use this class to create an object, we have to pass certain things into it. And there are a couple of arguments I want to be able to pass in later. The first one is path. And this is going to be a path to a file that has an image of the spaceship. Then I want x position and y position, and then I wanna speed. So x and y pulse is going to be where the spaceship is going to be put on the screen. And speed. If I type it correctly, It's going to be how fast it can move. And now we need to create the actual attributes of this class. And the first thing we need to create a surface. And in a class does this for some reason called self dot image. So this image is just a surface. And this surface we create an insanely recruited earlier. So PyGame dot Image.all load. And I want path. So then whatever file name be passing here, we're going to load this image and we're gonna put it on a surface. And this surface is by convention called image. So now we have a surface and now we need to put a rectangle around it. So self-direct is going to be self dot, image, dot get, right. And you have seen this before. The center is going to be at exposition. If I'd have correct expos and bypass. So now we have a class that has a surface and a rectangle. But there's one thing I forgot, which I do all the time, that we need super dot in it. So that when we inherit from this sprite class, we got all its functionality and this is really important. So this is the most basic kind of sprite class. You can create an pygame that at least has some kind of functionality. So now how can we put it on the screen? Now, obviously, the first one we need, and I put this a bit further down here. We have to use this class to create an object. And I'm going to store this in a variable I call spatial on a lowercase. And we used the Spaceship class. And the first thing is that we need the path to the file. And I have called mind space ship dot PNG. And now we need to put it on a certain position on the screen. And for now I'm gonna put it in the center of the screen. So as always, at 640. And I'm not going to put it in the middle of the y-axis, are going to put it a little bit further down. So let's say 500. So when the middle of the horizontal and slightly on the bottom of the vertical axis. And let's run the game now. And we get an error that i forgot the speed of our spacial, which is very good at fixed that say for now we want to speed of ten, but not as run it. And we can see that we can't see anything. And that's for a reason that is bright and PyGame is only drawn inside of a group. So we have to take this spaceship and put it into a group and then tell the group to draw oldest sprites inside of the screw. And there are two kinds of groups that we can have. The first one is just called group. The second one's called Group single. And group singlets, what we are going to use for now. And the only difference between these two is that group Single can only take a single sprite, whereas regular group can take any number of sprites. And in our case, since we only have one spaceship, we're gonna put it into group single. So here I'm back in my code and I want to create a class that I am going to call space ship Group. And we create a group of pygame dot sprite dot group. And in my case that is groups single. And it does not need any arguments. And now I just need to add our spaceship to the spaceship group. So here we created a group or a single group. And here we added this spaceship tutors group. And that's all we need to do. So now we have a group with this spaceship inside of it. And now in our game loop, we have to tell PyGame to draw this spatial Group on every single frame, which happens with a spaceship group. Draw. And now and you tell it on what service to drawn, which in my case is screen. So now if I run the code, we should be able to see it. And there we go. We have our spaceship. And all of this might seem quite extensive to put just one image on the surface. But when you look at the code in the game loop, this is what you really want things to be cleaned because this is where the game logic happens. And this is where spreads work incredibly well. Because in the game loop we have one line that draws all the objects inside of this group. And if we are to normal grouped as could be hundreds of different objects. And later on when we come to the meteors, we are going to have hundreds of different objects inside of this. But in the code, we just have one line to draw all of them. And yeah, at the top here, all of our spaceship is inside of one class. And in the next couple of videos, we are going to give it more and more methods to give it more abilities. But in the rest of the code, nothing is going to change or well, very little is going to change. And this is Wes, brides are incredibly useful that you create one object and all the logic of this object is concentrated with in this class. So it's all in one class that is very easy to manage. Alright, in the next video, we are going to move this thing. I will see you then.
16. Meteor Dodger 3: Spaceship movement: Hello, in this tutorial, we are still going to work on our spaceship game. And specifically, we are going to give our spaceship the ability to move. And we're still going to use sprites to move it. And in this tutorial, I think you're really going to see why sprites RB useful. So let's jump right in my basic approach to moving the spaceship, It's quite similar compared to what we have done the last game of the crosshair. I just wanted to put the spaceship wherever our mouse cursor happens to be, which is essentially the easiest way to move something on the screen. And we're still going to use a rectangle to move to Spaceship. But this time, that's the rectangle is going to be inside of the class. And I think it's best to explain all of this work directly doing it. So let's jump right into code and apply all of this. So here I'm back in my code. And what I want to do is give this class a method that can move the entire spaceship. And this I am going to call update. So I'm going to define a new method. And there's always this in itself inside of it. And now we want to use the rectangle of this class. So to think we have created earlier. And this time we can't use Event pause because event pause can only be used inside of the event loop. So in here, which we are not doing right now. But I have talked about this a little bit earlier, that instead of event on pause, we can use PyGame dot, mouse, dot-dot-dot, get undressed, got plus. And this gives you the same result. The only difference is that this guideposts works all the time, whereas this event pause only works when you use events. But the result for both is the same. You get the position of your mouse. So now we have the position of our mouse. And I want to set this to the center of our rectangle. And that is pretty much all we need to move the spaceship. Let me run the code right now and nothing's going to happen just yet. So here we have two spaceship and you can't see it moving, even though I'm moving my mouse. You can't see that on the screen, but just trust me. And the reason for that is that this update method is not being called. But we can call it very easily via our group down here. And let me do this right now and the next pen afterwards. So we have spatial proof and all we need is update. So if I run the code now, we can see our spaceship is following the mouse. So why did that work? Because we didn't call this up benefit immediately. Instead, we called update on the group itself, not the sprite. So let me explain how that works. Essentially, every spread class in pygame has an update method, except by default, this update method doesn't really do anything. You have to give your own functionality. But the reason why this update method is special is because whenever you call update on a group, every sprite in this group is also going to run the update method and it has, and this would allow you to update lots of different sprites simultaneously. So for example, when we look at the meteors later on, we're going to update hundreds of different meteors at the same time. And all of this would be done by updating the group all these meteors are in. So this update method for sprites is incredibly useful to just update lots of different sprites at the same time with just one line of code. But alright, that's a fairly rudimentary movement mechanic. So now our spaceship can move. But there's one problem. Let's say for run it again, we can move our spaceship kind of outside of the screen, which looks a bit weird. So I wanted to add a tiny bit more cold to constrain our spaceship to the screen so we couldn't move outside of it. And this we can also do quite easily inside of this class. So I want to add a new method, I'm going to call screen constraint. And it needs self-aware. And we're still going to move our rectangle. But now we are going to use a new attribute of the rectangles that I haven't talked about earlier. So under screen right now, you can see all the attributes of a rectangle. So we have left, right, top, bottom, lots of different points on this rectangle. And we can measure all of these points and we can move all of these points. And if you move any of these points, you move all of them simultaneously. So what we have seen so far is that we always move to center. And if you move the center to the right by let's say 20 pixels, you also move the top rate by 20 pixels, or the bottom left, always stay relative to each other. And what I want to do to constrain the spaceship on the horizontal axis is to measure the left and the right point of the rectangle. And if the right point gets too far to the right out and put this spaceships right point on the right of the screen. So essentially whenever we go too far to the right, the game puts us back on the right side of the screen. And then the same thing for the left side. So let's implement this. So here I'm back in my code. And what I want to measure as if self.age direct dot left is greater or equal than 1280. And of course, I mean the right is greater or equal than while 80. So 1280 is the dimension of our screen. So this is the right side of the screen. And if the right side of our rectangle, so this spatial rectangle is greater than that. Then we want to constrain it because at this point we noted has gone outside of the screen. And I wanted to do is self.age, correct? Right, is equal to 1280. So basically what happens is that whenever this point goes too far to the right, then we wanna put it on the right point. So effectively we can never go outside of it. And now we just need to call this method inside of the update method. So self.age screen constraint. And now let's try this. So I run the code. We can still move the mouse. If I go to left, we can go outside. But no, if I go to the right, we are stuck here. And if I move my mouse outside, it stops moving obviously. But I can never go further to the right than this point. So that works quite well. That brings us to the challenge for this video that I want you to implement the same mechanic for the left side. So pause the video now and try to sell. How did it go? I think it should be fairly easy, but let's see how we can do it together. So here I'm back in my code. And what I want to do is to check if self.age correct dot left is smaller or equal than 00 is the left side of our screen. And if that is the case, I wanna go self.age direct dot left is equal to 0. And that's pretty much it. Let's run now. So the right side still works, and not a left side also works. And to understand what a zeros coming from, you really have to understand the coordinate system we are working with. At the top left of the screen is position 00. So the left side of the screen is always 0. And so is the top of the screen there both 0.05. and then the right side of the screen is always discrete dimension, as is the bottom. So on our screen, The left side is 0, the top side is 0, the right side is 1280, and the bottom is 720. And helped them make sense. And in the next video, we are going to add our first Meteor. I'll see you then.
17. Meteor Dodger 4: Creating a meteor: All right, welcome back. In this tutorial, we are going to create our first Meteor for the spaceship game. And you should actually already know how to do this. Because we are going to follow pretty much the same approach we have done with the spaceship. So we're still going to use the sprite for one Meteor. And then we're going to move this material in a certain direction, mostly downwards, but we're going to give it a bit of a left and a rightward movement. That is mostly going to be random. And since you should already know how to do this, Let's start this tutorial with a challenge right away. That in the tutorial folder they have three files. Could Meteor one, Meteor, and Meteor free tried to use any of these files to put one Meteor somewhere on the screen. It doesn't really matter where it is, just trying to put it on the screen by using sprite. So pause the video now and try this yourself. Once you're done, I am going to go through this in proper detail. All right, let's try it together now. So here I'm back in my code, And here we still have to Spaceship class and it's getting quite a bit larger. But let's close it for now because we don't need it. And what I want to do is to create a new class that I'm going to call Meteor. And Meteor also needs to inherit from pagan cults bright dot sprite. And then inside of this class, we have to define an init method, then itself, and a few more parameters. And the first one I need is the path. So that is going to be the path to the file off the meteor. I want an x position and y position. And this will be enough to displace it on the screen. But I also want an x Speed. And why speed? So the wind speed is basically how the media is going to move downwards. And the expert is there to move it left and right by a tiny bit. But why speed should be the larger one? But, alright, now, we need to properly used all of these arguments to actually create our sprite and is always test starts with self dot image. And let's start for now with pygame dot image dot load. And I'm just going to stick with Meteor one dot PNG. Then our self-taught direct, this going to be self.name, image, dot, get wrecked and center. I've really kind of type is going to be our x position and our y position. So this, if I opened our spatial began, is essentially the same thing we have done here, except again, I forgot a super init method. I do that all the time. Now, it's basically the same. So we have created a class, we've created classy as well. We have our super init method so that this Meteor can properly inherit from the sprite class and gets audits functionalities. Then we create a surface that we called image. This one, again is just a picture, just like here. I could actually just call this path. Then we put the picture in there when we create the object. And then we have a rectangle, just like here. So all of these things should be fairly obvious by now. And let's actually use it. So forbidden in the code I'm going to create, let's call it Meteor one. And this is Meteor. And I want to pass in Meteor one dot E and G. Then I, let's say we're going to put it at position four hundred and four hundred. And we also need to speeds. We haven't implemented them yet, but we are going to that in just a second. Let say for now I just gonna put in 11 because they don't matter. So now this should be all we need. Now we have a meteor or an object of a meteor. Now we need, let's call it a meteor group. Group, and this is pygame dot dot group. And this time we use a normal group, not a group single, because I want to put multiple sprites and psi of this group. Now when you meet your group, dot dat and meet here one. So now we have our medial inside of a meteor group. And I want you to do now is to draw this meteor group. So Meteor Group dot withdraw and just happens under screen. And I really wanted to emphasize that all of this is incredibly similar to what we have done before. So here we brought a group. Here we create a group and add a sprite to it, just like we have done before. And here we have two classes and they look really similar. If you compare this and this, it's basically identical. Couple of small details are different, but this doesn't really matter. So if I run the game now, we have our Meteor. Obviously we can't do anything with it just now, but we have it on the screen. So I hope you manage this yourself. And if not, let me know in the comments why you struggled. And you finish this video off. Let's move this meteorite and this gets us to another challenge. So we have two challenges in one video that I want you to create an update method for this Meteor and make it move downwards for now, by the way, Speed. And pause the video now and see how far you get. Alright, how did that go? So let's do it together now. So here I'm back in my code and I'm standard Meteor class. And what I want to do is to create an update method just like photo spaceship, except now for the meteor that just moves it downward. So I gonna create update and has always it needs self. And we still have to target self.name. So we're moving the rectangle. But now we can't use Center like we have done before, because Center is expecting two arguments. So when we have used get PaaS here, this gives us an x and a y position. But now we want to have an x speed and the wind speed. So it immediately moves downwards at quite a fast pace. But by the Expedia doesn't move all that much. So we basically need to separate the X into Y speed, which we can do. And this we do by center x. So this one would give us only a single point, and that's the position of the spaceship on the horizontal axis. And this one we can also move. So this one, if we wanted to plus equal self.age x speed. And now we can do the same thing for y. So self.age direct dot center y plus equals self dot y speed. And just to be clear, when we use Center, we get an x and a y position. When we use Center X, we only get the x position of the center. Center. Why we only get the y position of the center. And then obviously we can both measure and move both of these points. But that's pretty much it. Now we just need to call update on our Meteor group. So Meteor Group dot update. And now if I run this, we are getting an error. And that is because I didn't create attributes out of these two arguments. But we can do it very easily. So it has a self.age speed equals speed. And then we have self.age, high-speed equal to y speed. So now they should be working. And there we go. Ok, obviously is moving incredibly slowly and it starts in the middle of the screen. So that's not exactly great. But we can change that barely easily. So now we can still started on x being 400. But instead of studying under y being 400, we can put this two minus a 100. And let's say to y speed, which is this one, shouldn't be one. Lets put it down at ten. Let's see how that looks. But run the code now, the media should start from the top and is moving downwards. So that works. It's almost too fast. Let me try this again, and let's make this a bit slower so we can actually see what's happening. So here we can see the meteor starting at the top and going to the bottom. So now we have one Meteor. But obviously that isn't exactly great because we want to have hundreds of meteors. So in the next video, we are going to create a mechanic that spawns a ton of meteors all the time.
18. Meteor Dodger 5: Timers: Hello and welcome back. So far, our game has a spaceship and one meteoritic goes from the top to the bottom, which is a start, but isn't very exciting just yet. So for this video, we are going to add lost my meteors with timers, which is actually going to be surprisingly easy. So let's jump for it in the logic for or meteors right now is that we are creating a meteor in a certain position with a certain speed. Then we add these media to a group and then we update this group. And this works as intended, and we are getting one Meteor. But that is basically at, we're only getting one Meteor. So here's how I'm going to change this. Instead of creating one Meteor, I am going to create a timer that triggers multiple times a second. Every time it triggers, it creates a new Meteor that we put into the group. And then this media we created is going to be in a random position with a random speed. So effectively we have lots of different meteors and multiple places. And the one new thing we need for that is a timer and pygame, which we can create quite easily. And I think the best way to explain it as by actually doing it. So let's jump right into the code and let's create our timer. So here I'm back in my code and let me close to two classes for now because we don't need them. And here's the logic we had so far that here we create a meteor, here we create a group of meteors, and here we are adding to one Meteor, shoot a group of meteors, which works fine by itself. But for now, all we need is to Meteor group by itself. And then in the time and we're actually going to create a meteors and self. And to create a time and PyGame, we need two things. The first one is what's called a user event, and a second one is an actual timer, and let's create them right now. The first thing I want to create is a material event. Just spelling it correctly. Here we go. So 40 meteor event, I want to create PyGame dot user event. And this has to be all in uppercase letters. And once we have that, we have a user event. And this is basically an event like the events we have in our event loop. So far all our events were user input, like moving a mouse or closing the game. But the user event could also be triggered by a timer. And this could be disused event. And to trigger it every couple of milliseconds, we need to add another line of code. And that is to add a timer, which would get by tag m dot time, dot set timer. And now we need the event, which in my case is meteor event, and dominate the length of the timer, which in my case is 250. And this is 250 milliseconds. So this timer is going to trigger every 250 milliseconds, or four times per second. So in 1 second you have one hundred, ten hundred milliseconds. And with that, we have one event that triggers four times per second. And now we can use this in our event loop. So if event dot type equal to meteor event, and now in here we can add lots of different code. And just to test this, let's just print something. So let's print meteor that run the code. Now we got meteor or quite often, and as keeps on happening over and over again. And that is exactly what we needed. And now we just need to create a new Meteor inside of this meteor event and had destroyed a group. And then this group is going to update automatically with this line and this line. So we don't actually need to change anything in the game loop. We just need to add a new Meteor in here, and the rest is going to happen automatically. And since I want quite a few random things, The First we need is to import the random module again, just like we have done before, because we want to have a random speed and a random picture for the meteor. So we need some random numbers, and that's basically it. So let's come to create the Meteor. And basically what we need is that our Meteor is still going to be graded by the meteor class. I call it a meteor, yep. And immediate class Levy orbit. Again, we need D's different arguments. So we need a path, an exposition of y, position and speed and why speed. So let's go through them one by one. And I'm going to create them in separate variables just to make it more obvious about what's going to happen. So the first thing I want to have is a meteor path. And for Meteor path, we have free different files that we want to choose randomly from its Meteor one media to a meteor free, all of which are PNG files. Effectively, what we need to do is to choose a random item from a list, which we can do if random.choice. So RAN them dot-dot-dot choice. And what random.choice does is you pass in a list or tuple and a pigs, one of these items. So we pass in Meteor one dot PNG, meteor to dot PNG, and meteor free dot PNG. And with that line, we get one image of our Meteor and it picks one of these free at random. And that's our first argument, 40 Meteor. So we have Meteor path. So that's number one. Next step, we need an exposition and a y position. So why we wanted to media to start this, we can do quite in similar way compared to what we have done with the targets and the previous game. We can use random.random range. And let me choose a random x position. And we need to random dot rand range. And I'm going to use the entire width of the screen. So 01280. So 1280 is to avoid screen, which is this width and a 0 is the left side of the screen, and this is the right side of the screen. And an ex post is going to take a random number in between. And that will be our next argument. So random x plus. And we are going to do quite a similar thing for the y position. So random y position. And the only difference is going to be at the Y position should start above the screen. So it should have negative starting positions. I wanna go with minus 500 to something like minus 5050. And there are two things you do want to be careful about with this line. The first one is that the media should not start at the 0. Because in the worst case, the bottom of the media might start exactly on the screen, which isn't ideal. So we start on minus 50 immediately when it first sponsor is never going to be on the screen. It's a small detail, but it is quite noticeable. But the other point is, why can't we start all the meteorites at point minus 50? Why do we have to give them a range? And the point here is a variance that we want to meet yours to look a bit more organic. If they are starting the same y position, it is going to look a bit static. So forgive them, arrange. It is going to look a bit more organic and a bit more chaotic, exactly what we want. But with that, we have random lied position. And now we need two more things. We need the x speed and a y speed. And those can be done in basically the same way. So random x speed. I want random.random range here for the speed. We want them to be able to go left and right. So we don't want to start at 0, we wanna start at minus 11, or you can make them larger, but I think this is already quite a bit. And basically what it means, we can navigate minus1, 0 or one. So if we get minus1, the media's going left. If we get one, Demeter's going right. If we get 0 to Meteor is going straight downwards. And we can do the same logic or random wave speed. Instead. In this case, we want to start at not even 0. Lets say we start with four, so to always move downwards, and then the highest one is going to be ten. And yeah, that's pretty much it. So random y, random Expedia and random. Why speed? I hope I have to write honor, it looks good. And now we have a meteor with all the required arguments and it's going to be completely random. And now we just need to add this meteor to ometer group. So Meteor Group dot app and leaky or, and what is now going to happen is that every 250 milliseconds, we are going to create a new Meteor with all of these random attributes. And in our game is going to look like we have a meteor storm. So let's try all of this and we are getting an error. And the reason is that I made a spelling error, that meteor should not be in all uppercase letters. If I try this now. And as another typo, and it's up here, writing and talking at the same time can be quite hard, but now it should be working. Let's hope it does. And here we go. Now we have a perfect setup and we can see lots of meteors that go and pretty random directions. And you can actually experiment with this quite a bit. So this 250 might even be a bit too low. Let me change this to a 100 and let's see what happens. And this actually looks quite a bit better. So it's a lot more stuff going on the screen. And we have lots of different meteors. And that is already quite a good start. But there's one more thing we do have to worry about. And that is that this meteor group is going to get larger and larger because we are creating a new Meteor every 250 milliseconds. And to illustrate all of this, let me change this to a very low number. Let's say one that we are creating a 1000 meters per second. If I run this now, it's going to get crazy. And the game is slowing down and noticeably. So it gets very laggy. And in a second, you can barely see my ship anymore. So we can basically see that the frame rate is dropping very hard and it's very hard to look at. And the reason is that we have more and more elements on the screen and even when the meteors leave the screen still being processed. So I don't disappear. And PyGame studies to render them. And at this point or frame rate is basically dead. And this is quite a common thing in video games that you have to make sure not to much happens on the screen, so the frame rate stays okay. And one key thing for that is that you disappoint elements once they're leaving the screen. So what we want to do is for this Meteor, once it leaves to screen, we want to destroy it. And this is really easy to do with sprites. And we can do this in the class itself. And the command we need to respond. A sprite is kill. And if we applied this on a sprite is pride is going to get deleted from all the different lists. So even if it's in two different list is going to get deleted from all of them. Which is perfect in our case because it makes it very easy to make sure it is bright, doesn't exist anymore. And we're going to do is now an update method. And other logic we need is self.age rec center. Y is greater or equal to, let's say 800. So all the logic we really need is that if any of these meteors that's creative bite his class is outside of the screen, so it's greater than 720. And let's give it some space just to be sure. And if it's outside of this range, then it is definitely not going to be on the screen anymore. So we can safely destroyed. And that is self.age, kill. And that's all we need. So now whenever any of these sprites goes beyond this range, it's going to get destroyed. And that makes it quite easy. So if I run the game now, it is still going to get really Leggett because spawning 1000 sprites and a second is gonna get crazy. But let's actually try this and see what happens. So here. And yet you can still see a slowdown. So killing the sprites once outside of a screen is helpful, but is not a one-stop solution. So it's tough to make sure you don't have too many sprites on the screen at any one time. Obviously in most games that is not going to be a problem because you're never going to have this many sprites and you're not going to need them. But it is something to be careful about. But already if I move this down, let's say to a 100, then our game is going to run very smoothly. And this looks very nice and smooth. And yeah, that's basically it. Obviously for now we can't do anything and if we collide, nothing happens, which is going to take some more code to fix. But next video, we're going to give our spaceship and Lazar, I'll see you then.
19. Meteor Dodger 6: Lasers: Hello and welcome back. Right now, our game looks like this. We can move the ship around and we have lots of meteors, which is a fairly good start. But obviously it's still fairly passive. And to change that, we are going to have laser today's tutorial. So whenever you click the mouse button, we are shooting a laser, which is actually quite a simple thing to do. So let's jump right in. So to major difference in this tutorial compared to the last game is that we can actually see the bullet or laser or whatever you wanna call it. And for that, we are going to need a bit more logic. But it's actually not that complicated. Effectively. Only to do under code is that whenever we click a button, we want to create a new bullet or legs are in a position of our spaceship, then this laser is moving upwards in a straight line. And we have all the tools to create all of this. There's nothing new we need to learn. So let's jump right in. So here we bag and what we have seen so far. And for now, I'm going to close the spatial class and our Meteor class because we're not going to need them. And instead, I'm going to create a new class that I'm going to call laser. And just as before, this one has to inherit from PyGame, looks bright but sprite. And in here, we still want to do is same thing we have done before. So I can just copy from our Player class. We'll copy this and paste it in here. We still want a path that's a file to a laser. We want an x and a y position and we want to speed. So all of these stay exactly the same. And we still want to load the file and we want to put it in a specific position. There's one difference though, that this time I don't need X into Y position. All I need is POS. Because when I'm going to credit later on in the event loop here, I'm going to pass in D Event position of our mouse. And this one contains x and the y position. So we can just use this one. So I can remove all of these things and we just need posts. And then this one also gets itself Godspeed. And it's just going to be speed. And I realized in our player glass artist spatial class, this speed was never used, so we can just remove it. I don't actually know why I included it. It's kinda pointless. So let's remove it here. And then when we create a class that's also remove it, it's ten here. So no change, we just remove a useless and variable. And now we want to move this laser in the same way we move to Meteor, this one. Except now instead of moving it downwards with some x variance, we want to move it just straight upwards. So I'm gonna create a new update method that needs self as usual and introduce update method self-direct dot center. Why? Because we want to move it on horizontal axis and this one gets minus equal self.age, speed. So basically what happens on every frame, we moved the center of the rectangle on the vertical axis by the amount of speech we pass into it in the negative direction, so it goes upwards. And that is literally all we need for the laser class. It's actually quite a simple one. So let's close it. And now we actually do create this class when you click a button. And before we can do that, we first need to group for the lasers. So down here, I create what I call laser group. And just as before, this is pygame dot sprite. And then in our game loop, I'm going to draw this. And here's something you do want to be careful about, that I want to draw the lasers below the spaceship. So I have to make sure that the layers are being drawn before the spaceship group. And this is quite important. Otherwise it would look, I've always said would look a bit silly. So laser group got drawn, draw after spoke directly and screen. And then we also have to update it. And let me actually give some space between these different groups that should make it a lot more readable. Iraq spaceship. Like this. There is a group DOT update. So now we are drawing our lasers and we update in the laser. So the only thing now left to do is to create a laser whenever we click the mouse button. And this happens back here in the event loop. And that is actually going to be your challenge that I want you to add a new if statement that if we click the mouse button, then we want to add a laser sprite to laser group. So pause the video now and try this yourself. Alright, how the depth goal? It should be quite straightforward I think, but let's do it together. So here I'm back in the code and I want to add a new if statement that if event type is equal to PyGame Mao's button down. We have seen the exact same thing in the last video. And I hope it's still a bit familiar. And when we click this button, I want to create, let's call it a new laser. And Disney laser is created by the laser class. And then just laser class. I'm going to pass in a file that I called laser dot PNG. And now into position for this laser. And this is the position of this event. So wherever must happen to be when we click the mouse button, this is going to be disposition and it is going to be an x and a y position. So it gives us all we need to place the laser. And finally, we need a speed. And let's say for now, I am going to go with five. And let's see what it looks like. And that's basically all we need. Let's try to run this now. You can some of our game, and if I click a button, nothing happens. And the reason why nothing happens is because let me close this. I only created laser. I didn't add it to the group, which is quite a silly thing to do. So we have laser, Group dot add new laser. So now it should be working. Fluid has to move around. If I click it now with a laser, it counted aquifer anything yet, but that comes later. But we have a laser to start with and I think it's quite slow. Usually lasers are bit faster. Let me close it and let's put this to 15, but a bit faster, and yet it fits much better. And alright, this gives us laser. There's one more thing we need to do that just like with the meteors. We have to kill the sprite once against too far up. And it's the same principle as before. If every time we create a laser, we are creating a new sprite. It needs some processing time. And Somalis, as we have, the more difficult it is for our game to run. So just as with the meteor class, we need if self dot dot, let's use center y. And this time we need is smaller or equal because we are looking at the top of the screen. And let's go with minus 100. So we have a bit of space above the screen. And if that is the case, I'm gonna go self.age kill. So whenever we're bullet goes too far up on the screen, it gets destroyed. So that would never have too many bullets on the screen. And that's the same logic we had with the meteors, that we want to destroy them once I go outside of the screen in order to make sure that it is never too many meteors at the same time and our game runs smoothly at all times. But art, that's another good step towards the game. And the no next tutorial, we are going to add health or shields starship. I'll see you then.
20. Meteor Dodger 7: Shields: Hello and welcome back. And for this tutorial, we're going to add some health to ownership or some Shields, however you want to call it. It's the same principle really. And specifically what we are going to do is to give our ships on health and to display the amount of health we have in the top left of the screen. And again, we're not going to learn any new tools. All of this can be achieved with the same tools we had earlier. So let's jump right in. And the logic 4000 eigenstates actually quite symbol that we have an icon that represents one health and it's a simple surface. And you want to multiply this by the amount of health we have. And that's really all there is. We can do all of this regular code actually. So let's go right into that. So here we are back in my code and I've minimized all the classes so we can focus on the important stuff easier. And what we want to look at is our spatial class. So I opened this one and here we have to add two more attributes. The first one I called self.age, shield surface, and this is just a picture, nothing special. And this is peg m dot image, dot load, Image.all load. And I call the image shield dot PNG. And here's one thing you do have to be careful of when it comes to sprites, that in a sprite to surface that is drawn is self dot image. You can't have most surfaces in the class, but only images being drawn automatically on the position of the rectangle. So when you input something besides the image, you have to make sure you don't call it image by accident. It's honestly quite an easy thing to avoid is to make sure that only the image is actually being dropped dramatically in the end. But we can draw more elements inside of a sprite class. So effectively what we are going to do in the end is that our sprite class draws an image and to shield surface both at the same time. Besides our shield surface, we also want self-taught. That's called health and dust by now that start with five. But you could have any number of health in here. And that's all we need for start. Now need to create a new method that actually displaced this amount of health. And I'm going to call this display health. And in here, we need to follow to display all the different surfaces. And basically what I want to do is to draw all of them automatically into four loop. So if we draw the amount of health we have, and we draw each health Eigen in a specific position, so we offset them in the exposition. And offers can be done inside of one for loop. But we are going to need to enumerate method again. But let's start a slug. The first thing I want to do is for, let's call it shield in self.age, health, and disk right now is not going to work because you can't use a for loop on an integer, which is what the health is. So we have to put this thing inside of a range method that we can't actually loop overt. So this, instead of being one integer, is going to be arranged object that goes from 0 to four, which is exactly what we need for our shield. And inside of this, we want to just draw the shield. So what do we want to do is screen the outlet and we want to draw our self.age shield surface. But now we need to position for each different shield and we have to offset them. In the exposition. We know the y position, just one. It's the same for all five of the different shields. And, but the exposition is going to be a bit more difficult. So I want my first shield to be on a position 50, the next one on the position, let's say a 100, next one position a 150. So what we need is an index for each of the different shields inside of the for loop. And for that the enumerate method is perfect. So I am going to add this enumerate. Surprisingly hard to write. So now our follow-up gives us two pieces of information. The first one is to arrange objects or somebody from 0 to four. And then the enumerate method gives us the index of that position. So now we need an index, and this is what we are going to store it at two pieces of information. And now we need to work on the position of each of the different shields surfaces. And we already know to y position, I'm going to put this at ten. So each field is offset by ten pixels from the top. This one is easy and the same for all of them. And know for the horizontal position, I want index and as called as times 40. And basically what happens here is the first index is going to be 0 because this index is the first one. So it is going to be 0, is second one is going to be one. So then this is going to equal to 40. And then the next one is going to be number two. So this one's going to be 80, and so on. And you can add this to us, may shoot as you want. And this should actually work already. What obviously we have to call this method inside of an update method. So self.age, display health. And let's try and see how this goes. And here we go, we can see some shield at the top left of our screen. We can however, see that a top left is a bit too far to the left. So I want to add a tiny bit of an offset to each of them. And so I just add plus ten for each of them. And yeah, this looks a bit cleaner. So here now we have five different shields on the top left of our screen. They don't actually do anything yet because we can't collide with any of the meteors. But for now, that's a pretty good start and also can make this as long as you want. So I can change this to 50. This would still work. Now we have a crazy amount of health. And alright, that's actually pretty good so far. In the next tutorial, lets actually get the collision started. I will see you then.
21. Meteor Dodger 8: Collisions: Hello and welcome back. So far, our game looks like this. We have our ship and we have lots of meteors falling down. And we also have some health at a top left. But nothing is really happening because we have no collisions whatsoever. And this is going to be the topic of this video. Or we're going to add two kinds of collisions. One is a collision between a meteor and our spaceship, and two, as a collision between our laser and meteor. And that is bringing us to a new topic, and that is collision between sprites. Let's have a look at that. So far, we have only seen one way to check for collisions and there was collide erect. But obviously we can't use it because we don't have rectangles, we haven't highest sprites. But sprites have a similar method. It's called Sprite collide. And here's how it works. Spread collide takes three arguments. The first one is one's priority. You want to check for collisions. A second argument has to be a group of sprites that you want to check collisions with. And the third one is called Duke hill. And if this one is set to true, any spread within the group that is colliding with the sprite we're checking for is going to disappear, which is actually really useful for us. And then this method returns a list with all the sprites that have been collided with. And this one method is actually all we need to get all of this started. So let's jump right into the code and let's implement all of this. So here I'm back in my code and I minimized lots of stuff to make it easier to observe. And what we want to go is inside of our game loop. So somewhere in here. And we want to check for collisions. And let me give some space. And I should add a comment just to make it clearer. Just an edit bitmap consistently. But, but I guess but a later Never Give me one to check if a collision between our spaceship and meteors happened. And once we're done with that, we're going to check for collisions between the laser and the meteors, but step-by-step. So to check for collisions between our spaceship sprites and or meteors, we first need PyGame looks bright, dot sprite, collide, collide, add. Now need to go for the arguments. The first one is that we need one sprite we want to check for, and this is our spaceship. And this I'm gonna get with spatial Group dot sprite. So does the one's pride that we have created here. And this is the one we actually want to check for if any collision with this thing happens. And then later on, if this one has a collision that we wanted to reduce our health and dissolve first argument. So now we need a group of sprites and now against this is our Meteor group. And then finally, we want to check for the Duke Hill argument. So do we want to remove the meteor if it hits the spatial or not? And in my case, I think it's quite a good idea. So I set it to true. So all of this is running. Anytime our spaceship collides with immediate, we're getting a list of two sprites. And we can use this as an if statement actually. And let me explain how this works. If no collision happens, this one is going to return an empty list. And empty lists in Python are not triggering if statements. However, once there's one element inside of this list. Once we have a collision, then the if statement is going to trigger. And basically what we are doing is that Python can convert different data types. So when we use an if statement, we don't necessarily have to use True or False. Python can automatically convert different data types to true and false. And empty lists are always going to be fault. And A-list with any value is going to be true, which we are going to use in our case. So if there's any item in this list, then we want to run some code. And for now, let's just see if this works and we want to print collision. So let's run the code and that's a lot of those working ad wherever collision intermediaries also disappearing. And this works really well. So down here we can see all of our collisions. Cool. So this is working. But now we have to do something more useful in this line. And what I want to do is anytime our spaceship is hit by a meteor, I want to reduce the amount of health of our spaceship by one or by a certain amount. It doesn't really matter, it doesn't have to be one. And to get this, we have to go to our class and add a new method. And the method I want to call, let's call it get damage. It needs self as always. And I also want to add it damage amount so that we have a bit more control about how much damage is being done. And now whenever this is R1, we want self.age minus equal damage amount. So I, whenever this method is triggered, we want to reduce this amount or felt by certain number, whatever we pass into here. And with that bag and our spread collide if statement, we just have to run this. So we want spaceship group and we want the sprite inside of it. And in here we want to get damage. And now we need to reduce the amount of health. And let's just start display one. And that's actually all we need. So let's actually run this. And yet, you can see on the top left, the shields are disappearing. If they're completely gone, nothing changes. That's gonna come later. But for now, this is working. And here's why this works. Let me go to our spaceship. Plus. So effectively, on every single cycle of the loop, we are displaying our health again from scratch. And this method here, or this method here, always looks for the amount of health. And by default it's five. But if a reduces, this line here is only going to run four times or three times or whatever our health is. So if you reduce the health in this amount and this one automatically updates, which is really nice and makes our life quite a bit easier. So this one's perfect. And this is already the first step to getting a more functional game because now we have basic collision mechanics and we could even pass a different number in here. Let's put this to form. So we get a lot of damage if we get hit and if we get hit once, then although health disappears. So this is looking quite nice, but I think one is the better value for this. Now we need to implement a lazy mechanic. And this one is going to look at little bit different because we have different requirements. So basically all we need to do is if a laser hits a meteor, we just wanna get rid of the Meteor. We don't have to calculate anything from that Meteor. So we did calculate damage fatwa spaceship. We don't have to do anything like that for all laser. And to destroy a media, we can just use a do kill argument from our spread collide method. So we don't actually need an if statement. But there's one more thing that's different. For our spatial collision. We have a specific sprite because we have a group single. But now for the lasers, we have irregular group that we want to check with, a never regular group. And in a normal group, you cannot access a specific sprite immediately. Instead, what you have to do is to cycle with a for loop for every single sprite inside of the group and then check specific things from this for loop. So that's a lot of talking. Let's implement this and I think then it's going to make a lot more sense. So what I want to do is for laser, in laser, THE rubric called it. So laser group is this one here. And we have all the lasers in this group. And we want to look at every single laser or every single laser sprite inside of this laser group. And for every single laser, we wanna check this method here that if any single lasers bright intersects with any of the sprites into Meteor group. And devalue returned from this method doesn't matter to us. So all I need is pygame dots, right? Dot sprite collide. And I want to look for the laser. Then as before, I want o Meteor group. And I want this to be true. So now if any latest pride inside of the laser group intersects with any spread into Meteor group, then we are going to destroy the sprite as colliding with the laser. So let's try to us. And I can shoot at the meteors. And the laser is quite strong and we can destroy multiple meteors. And that's fine for our game. I think it doesn't make too much of a difference and add our edge that's pronounced progress. But obviously, if we lose all our health, nothing changes. So we need some kind of game over screen. And that is going to come in our next tutorial. I'll see you then.
22. Meteor Dodger 9: Game over and score: Hello and welcome back. For this video, we're going to add a game over screen to our game so that when you lose all of your health, their game ends, which is how it's supposed to work. And that brings us to kind of a new topic and pay gap. We are not going to learn any new tools, but we are going to create different stages and our gain, which is quite a useful topic. So effectively, we are going to have two stages in our game. We have to stage, we have seen so far, that is our game. And besides that, we also going to have a game over screen. And in the next video, we are going to add a score to the screen by let's do the step-by-step. So in this video, we will cover how to add different stages to our game. And all of this is happening in the game loop. Let me put it on the screen. So here is effectively the entire logic of our game. And really all we want to do is if you want to go to a different stage, is to run some different code in here. Well, obviously, but specifically what that means is that I want to put all of this code into a specific function and then only run dysfunction if a certain condition is met. And if a different condition is met, then I want to run different code. So basically our different game states are just an if statement. So to we are drawing an updating certain sprites. If a certain condition is true and if that condition is not true, then we're going to draw something else. And more specifically, that if we have our player health above 0 and we add wrong domain game, and if it's 0 or lower than we are going to draw a different kind of logic. And I think implementing on-off test is going to extend it the best. So let's jump right it. So here I am back in my code. And down here I have all of our game loop. So this is what the actual logic of our game happens. I'm going to ignore the background image because this one doesn't really matter and it's not supposed to change. So this one here is what he actual game happens. And all of this I want to put into a dedicated function. So let me copy the entire thing and create a new function. With deaf that I'm going to call main game. It does not have any arguments. And I'm going to paste all of my code in here. So now we have a function with voluntary game. And I call this function main game on every single cycle of the loop. So if I run this now, we should not be seeing any change. And it looks pretty similar. I can still shoot by laser and I can still lose on my health, but still nothing happens. So that works as intended. And let me remove the whitespace. Alright? And now we only want to run this function if a certain condition is true, which are my specific case means if the health of our spaceship is greater than 0 and we can check very easily. All we need is if spatial Group dot spread. So again, spread we have created and I called this health is greater than 0. So if you have at least 1 of health, if this is true, then we want to run our main game. And let's try this. So what I'm expecting now is if we lose all our health and let me get to one here. Now, we can't see anything. And let me explain why this happens. So let me close this. Right now. We are always trying our background screen no matter what happens. But the entire rest of the logic. So all of this, like drawing or a spaceship, or lasers or meteors. Only happens if the health of the player is above 0. And if we get hit by too many meters, this is not the case anymore. So if that is the case, then pi games only drawing the background image. And now we can add an else statement. Else. And what I want in here is some kind of end game or game over screen. And this is going to run inside of a different function. So I call this end game, does not need any arguments. And in here for now, what I want to do is to print game over. So nothing fancy, but we are going to add a score later on to this. So we are back to creating texts and PyGame. And for that, we need a font first that I'm going to create in our main game set up under init and the clock because it fits better in there. I call this game font. Is it's PyGame. Again dot fond, fond. And again for simplicity, I'm using none, but you could import different fonts. We can have a look at this later actually. So now we have a font. And I think there's a perfect flight challenge. What I want you to do is to print Game Over on the screen. In the middle of the screen, you have sync basically descend kind of texts. And the last game to have a look at this, if you can't remember, but pause the video now and try it yourself. Alright, I hoped I'd worked out, but it's tried to give an L. So again, for text, the first thing we have to do is take this font and render it. And then this new render text is going to be on its own surface. So let me call it text surface. And this one's gonna be game fund dot-dot-dot surrender. And now I need to pass on some information. The first one is the text we wanted display, which in my case is GameOver. Then we need to tell PyGame if disk Texas enter aliased or not, which in my case, I want this to be true. And finally, what we need is the color of the text. And I'm going to go with white. This is to 55 to 55205. So we have the full amount of read, the full amount of green, and a full amount of blue. And if you combine the full amount of all of these colors, you get quite in the same sense that if you put 000 and here you get the absence of our colors or black. But now we have a text surface. Next step to make it easier to put this text in the middle of the screen. I needed texts rectangle. And this one is text, Surface dot get wrecked. And dissenter is going to be half of whatever is in here. So this is 640. And so now we have a surface without text with a rectangle in the middle of the screen with the same dimensions. And now I need to put this surface in, sign off the rectangle. And this happens with screen doublet and disservice. I want its text surface. And this has to be under Text wrecked. And now this should be good to go. Let's try it. So let me get rid of all my health and we have GameOver. So it is working actually quite well. And in our next video, we're going to add a score to this. I will see you then.
23. Meteor Dodger 10: Reset: Hello and welcome back. In this video, we are going to improve our game over screen. And specifically we're going to add two things to it. The first one is an actual score, so you have a bit more of an incentive to play well. And the second is when we are on our game over screen and click a button, then we reset the games we can play again. And let's start with the easier part. And that is to reset our game when we click a mouse button in our game over screen. And we can do that straight in their code. Let's have a look at that. So here we are back in our code and it looks as usual. And to restart our code, we have to go down in the event loop. And here we are checked for all our input. And we only have really one kind of input in here and that's mouse button down. And if this one is being pressed, then we should laser. But this laser's only rendered in the main game loop. So clicking this button when we end the end game screen doesn't really do anything. So we have to add some functionality here that if we click a mouse button and we are now a game over screen, and then we want to execute some code. And this we can do quite easily. So let me just copy the entire line actually, to be the easiest. So now we check for mouse button down, but we also want to check for something else. And that is, our spaceship group looks bright, that health is smaller or equal than 0. So what this basically means is we are checking if we afflict the mouse button and if our player health is 0. And what we have done in the last video is that if this condition is true, then we are automatically at a game over screen. So this one would only triggered if the game is over. So these two conditions together make sure that we can check for mouse button click that is only registered when the game is over. And all we have to do in here is to give our spaceship its health back. So as always, spatial group that's bright, dot Health. And I set this back to five. And now if we run this to shut the working, so this works fine, let me just throw myself. So when a game over screen, now click the mouse button again and we're back. But you have seen there was one problem and let me try it again. That we have a crazy amount of meteors at the same time. They have made it again kinda hard to play. And this should make sense if you think about it, that when we enter game, we still have lots of meteors in our Meteor group. And this one here, because we don't emptied his group. So when we start the game again, this group already has lots of meteors inside of it, which we don't want. So what we have to do in this condition besides resetting our player health, we also have to empty the meteor group. And it's one. We can also do very easily with Meteor Group dot empty. And all that empty does is it empties the media group or any group that's applied upon. So if I run the game now and let me just turn myself as usual, an onclick again, again. Now, we slowly have meteors coming in again. So the game properly starts and have some time to prepare. Which was much better. So making good progress. And with that, we can start the second part of this video. And that is that a high score to our game. And the logic for it is quite simple, but there's one thing we do have to take care of by, let's go through it step by step. The first thing I want to do is to create a simple variable that starts at 0, and I'm going to call this score. And in our main game loop, I'm going to add one to this number every single cycle of the loop so that it continuously increases. And then when the game is over, I'm going to display the resulting number. And then when we reset our game, this one goes back to 0. So let's start implementing all of this. Yeah, I'm back in my code and the first thing I want to do is to create a variable to track the score. And I'm going to call it score. And it's going to start at 0. And now every time a la main game loop is running, I want to add one to this number. And this is where we have one problem. That if we do something like Libyan example, score plus equal one, this would not be working. Or the simple reason that in our main game loop, we have a local scope. But our score, this one here is in the global scope. And this is generally an issue in Python or any programming language that you have to be aware of, that you are working at different scopes. And you really have to make sure that you're addressing the right variable. Because if you were to run this, again, would not know what score variable we are talking about because it didn't initiate it in this local scope. So in the scope of this function. So what we have to do is get this score out of our local scope. And there are two ways of doing it. The first one is to just declare this score as a global variable. And we can just do it like global and score. And this would be working. But it also wouldn't be good practice because ideally you want to avoid global variables. And instead what we can do, we can use the return statement. So every time this function is run, it returns the integer one, which we can then use later on in the code. When disliked, he has run to add to our score. So score plus equal men gain. So whatever's being returned from this man game, which is always going to be a one, is going to be added to OS score. So every time off to this running OS gauze increasing, which is exactly what we want for our game. And with that, we have an increasing score. So let's actually print it just to make sure this is working. So below omega M. And it's gonna print score just for testing purposes. And now from the game, we can see it doesn't update, but here it is increasing. So this we can use as a score. So the family we go to higher this number is going to become. So now we have our score variable. We just have to display it. And this is going to happen in our end game loop. And in here we already have some text. All of this year, all of this. He actually, and I just want to copy out of this and use it for another line. And this one is going to display our score. So let me rename some variables. So it is going to be score surface. And we worry about the content of this in just a second. And then we have outscore erect. And because this can obese direct and all of that is going to be scores surface and score rect again. And now we have to worry about the position of these two pieces of text. Because right now they're right on top of each other, which isn't ideal. So we're going to move the game over screen a little bit higher. So I'm going to reduce the y-dimension, true, let say 320. That's there it goes. And then I increase this one to 400. So now they're on top of each other, but still in the middle of the screen. And now we have to change this game over screen. And I'm going to do this with an F string, which looks like this. And now in this F String, we can combine text information like this or strings with our variables. And what I want to write a score. And now in curly brackets, here we can add any kind of variable. And then Python automatically combines them into one string that gets displayed, which is ideal for our use case. And this is basically all we need. So let's try and run this and let's see how far we get. And then we go wherever score. And I think that distance between the two is a bit too large. So let's reduce it a touch. Essentials differently and 40, and let's say 380. And let's try it again. And let me just destroy myself. And yeah, this looks much better. We're going to update to fund later, but for now, the functionalities there, although deaths one problem. And let's restart the game now. So here at the game looks the same again, but now the score gets much higher. And the problem here is that we never reset our score. So I think in the first one off the scheme we had something like 200. And now in our second rounder must have had something like 300. And we just added those two numbers together. So I run our game again. This is going to continuous, so our number is going to get even larger. And Domo I play, we always get a higher number. So to score count as a bit broken. But we can fix it very easily. And all we have to do is in here when we reset our game to set score back to 0. So that whenever we picked a mouse button in the end screen, we reset our score. Let's try this now. And we have 228. And let's try it again now. And let me try to stroma service Basilica. We have 217, so when notices working, and that's perfect. So now we have an end screen that shows a score and we can restart our gain, which is quite a nice update. So we're getting much closer to a finished game. In the next video, we're going to add some laser charging mechanic. I'll see you then.
24. Meteor Dodger 11: Laser charge: Hello and welcome back. Right now, our game is working kind of decently. However, I think we are a little bit overpowered. And what I mean by that is here's our game. And we can just fire or laser as fast as we can click the mouse, which makes it really easy to get rid of all the meteors and makes the game just very easy. So instead, what I want to do is that our laser charges for 1 second before we can fire it, which forces you to be much more deliberate when shooting laser. But when implementing this, we also have to add another thing. And that is that we have to tell the user or the player that our laser is ready. Because if we only have account after 1 second, the player never really knows when the laser is ready. And in our game, what that means is when our lasers ready and we are going to give our player ship a slight yellow outline. So you can tell it's ready to fire a laser. And let's start by creating a timer. And we've already seen a basic time afforded meteors. However, for the laser, we are going to need a different kind of timer because we want to wait exactly 1 second after we have shutter laser, we don't want to repeatedly count something. So our setTime or from the earlier tutorial is not going to work. Instead, we have to use a method and PyGame that's called getX. And what getText us. It gives us the time since our game has launched, Austin's PyGame ended was called to be more specific. And we can call dysfunction whatever we want in our game. And from this we can create a timer. And basically how this works is that we are measuring two points. We're measuring 1 once and time. And let's call this point a static point. And then from this point, we keep on measuring our current time and measure the distance between those points. And if the distance is greater than a certain time, let's say 100, then we want to run a certain function. So it's essentially a basic if statement that if our current time minus L aesthetic time is greater than a thousand, then we want to run a certain code which we can implement fairly easily. So let's jump into court and implement this. The first thing I'm going to need is some kind of laser timer. Let's call it lays a timer. And by default, this is going to be 0. And in this variable, we're going to measure when our laser was shot. And when our laser sharp, we can get from this event here. So when we click our mouse button in dimen game, then we're shooting a laser. And in here we wanna measure when does laser was shot. So lays at time I called it. And to get the ticks, we want PyGame dot get ticks. And it doesn't have any arguments. And this one tells us when the laser was shot. And let's actually print it just to illustrate this laser timer. Let me run the code. And now on the bottom, you can see that we've shot the first lays up after about 1 second. Then we're shooting one Lays after four seconds, then after six seconds and so on. So this gives us the time window, a laser shot, which is a pretty good start. So let me get rid of this print statement again because we don't need it. So now we have a static point in time. The next thing we're going to use to continuously measure our time and then subtract this static time from that time. And then if the difference gets greater than 1000, then we want to recharge to laser. And to recharge your laser when you have a variable that I'm going to call laser, active. And by default let's put it to false. And the entire time mechanic, I'm going to put into our main game loop because that's where we are shooting our laser. And let me put it right after here. And I'm going to call it as laser timer. And this is just an if statement. And here we want to check if Pi, game dot time dot get ticks. And since this is going to run on every single frame, this is going to continuously update. And from this one and subtract our laser timer. And now if this is greater or equal to 100, and again, we are measuring in milliseconds. So 100 milliseconds is 1 second. Now we want to do something, and for now, let's just print. Let's call it test. So nothing happens and I shoot a laser and we can see test lots of times. And the reason for that is after 1 second, this one is becoming true. And then this one triggers all the time. So we can tell it's working. And what I want to do in here is laser actively colder, it is going to be true. And then in, when we run this one here, then our laser is going to be non-active anymore. So I'm going to add laser active is equal to. So basically what happens is whenever we clicked a button to shoot a laser, a laser schooling to get faults. And in a second we're actually going to make this work. But the idea is if this one is false, we can't shoot a laser. And then when we are running this line here, and after 1 second, it becomes true and we can shoot a laser again. And the only thing we need to make this work is that this only works when you click a mouse button and laser active is true. And this freakin out with a simple if statement and laser active. And now debts, essentially all we need. So now we can only shoot a laser if you press the mouse button and laser active is true. And then when, when this is executed, we create a laser and laser activist set to false so we can't shoot anymore. And then we get the time. And then further up here, we are checking if the current time minus time we clicked on our laser is greater than 100. And if that is the case, laser active gets back to true. And if I run this, I can't shoot and even not a 1 second icon shrewd. That's for a reason. And the reason is that all of this is in a local scope. So this laser active is a local variable that does not, that is not equal to this global variable. And it's kind of a similar problem compared to the scope we at earlier, where we had to maneuver around us with the return statement and just have demonstrated we can also use to global one if we can just declare our lays act of a global variable. And now there should be working. So let's try it. And I can shoot a laser and I keep on clicking, I think can heared. We unissued once the while. We can't tell whether lasers ready, which is not great, but it comes in a second, but it is a more delayed and slower laser. And just tests is a bit more. Leds decreased as number two, let's say 200. So now I keep on clicking. We only shoot about five times per second or every 200 milliseconds. So this one is actually working quite nicely. And you could basically keep it like this. I think this will be working maybe a little bit slower, but I don't want to do that. I wanna keep it at 100. So you only shoot a laser at a very deliberate moment. But I do have to tell the user that a laser is ready, which is going to come now. So let me close our main game and offers is going to happen in our spaceship class. And let me explain the logic first. Like an any spread class self.age image is the surface that is actually being shown to the user. And in our case, we immediately assigned this to whatever file we are loading. But I want to change this. And what I want to do instead is to create two surfaces in our class that are not immediately shown. And I call them charged an uncharged, and each of them carry one surface with a different version of the ship. The uncharged One is the default one that charged one is the one for yellow outline. And if our lasers charged, we're gonna show one of the yellow outline. And otherwise we are showing a normal one. And that's what we're telling our users that a laser is charged. And that is quite a handy function for sprites. There, whatever surface you put on self dot image is going to be shown to the user. You can move this around quite easily. But again, lots of talking. Let's actually implement this. So here I'm back in the code and I want to update this line here. And let me add some space before. And I want to create a couple of new surfaces. The first one I called self.age uncharged. So that's our default one. And this is the one we're actually going to load by default. But then I also want a new file that I'll call self.age charged. And this one is pygame dot image dot load. And you can find a file into our folder. I call this one spaceship dot charged. And of course PNG. And if you want some flexibility, this one clause will be declared when you create your object. But in my case, I just want to keep it simple. So now we have two surfaces, 140 passive ship and one for the active ship. So when lasers charged, and by default, our self dot image is going to be self.age charged. So if I run the game now, nothing is going to change. We still have all uncharged ship, so this one is fine. We can still show a laser. So this one is working. And really what happens in here is that we are loading our image so far on self that uncharged. And then when we first create a sprite, self dot image becomes selfless, uncharged. So there's pride a player sees is the uncharged ship. But now, but now we can create some more methods to change this. And I want to create too. And the first one I'm gonna call it charge, does not get any arguments beside itself. And self.age damage is self.age charged? I call it charge. Yeah. And then another method that I call discharge. And this one is self.delegate equal to self dot uncharged. So if you run these methods, we're going to change the look of our ship. So now under code, we just have to implement this. And let me start by John costs going to this line. So if we shoot the laser, our ship is going to discharge. So we're going to call spaceship group, don't sprite as usual. And now we want to call discharge. And then when our lasers ready. So in our main game loop, when this is ten minutes run, we want to set our special group dots, bright dot charge, I think I called it and yeah, charge naming methods can be really difficult. Now whenever any of these if statement is true, we are changing the look of our ship. So let's try this. Let's see if it's working. Yeah. So you can see the yellow surrounding when he gets ready and I shoot a laser, we get to a normal ship. And otherwise we have all yellow outline that tells us that our lasers ready. So that's pretty good and it seems to work quite well. And we can still die and restart the game. And this works pretty well. So almost got, and we're making good progress. And in the next video we're going to add some more details to all of this. I will see you then.
25. Meteor Dodger 12: Refinement: Hello and welcome back. In this video, I'm not going to change anything major anymore. The only thing I'm really going to do is to add a custom font to our end screen. So it doesn't look like a generic object. Instead, we're getting a futuristic font. And for that, we have to talk about how to add fonts and PyGame, it's actually super easy. The first thing we are going to need is a file that actually stores the information of our fund. And these kind of files are called true type font files or a TGIF and short. And there are a couple of websites that gives you lots of different fonts. Probably the biggest one is called the fund, and there are thousands of funds on there. And from this website, I've chosen one phone called lazy by comps move. And this is a fairly futuristic kind of font. And I've put this font inside of our game folder. So it's in the same folder as our code. And that is quite important part once we have that, we are good to go. So now here we are back in our code. And right now, this is the line where we are creating our game fund. So we are initiating PyGame fond, fond. And right now our font is none with a font size of 40. And the only thing I need to get a new fund is to change this nun, the name of the font in my folder, which are my case, is laser by com, smooth dot t, t f. And with that, we're done. So let me run the code now, and that's soap. I didn't make a typo. This is good, so let me get hit. And here we go. We have a much nicer looking fund. And now again, I can just click and get destroyed again. And we're good to go. So this looks pretty good. And I think at this point, our game is pretty much done. So I hope you enjoy this game. And in our next game, we're getting to a much more fancy-looking game. I will see you then. Okay. Yeah. Okay. Okay.
26. Getting Godot: Hello and welcome back to the second major part in this tutorial series. And what we're going to start doing is to use the good dog gaming engine for game development. And we're going to learn about Godot in much more detail in the next few videos. But for this video, I just want to download it and talk about GD script in a tiny bit more detail. The first thing we need is to download Goodall because Good dog is not a model of Python. Instead, it's its own entire program. And how you get it is to go to good DO engine.org, all one word. And when you are on this website, you go to download. And once it's loaded, then you have all the options that you can download. So there's Windows, Mac OS, and Linux. And what you'll most likely want to download is the standard version with 64-bit. And when you click on it, you download the file and you do not have to pay for any of this, just to mention that. And once the download finishes, you should be seeing the file in your download folder. And from there, you just have to unzip it. So Extract All In my case for Windows, and extract it in the same folder. And now we're opening a new folder. And in there, you'll have good. Oh, you don't even have to install it. All you have to do is double-click on it, then it loads for second, and then we get the program manager. So that's all you had to do to get Godot to run. And in here, you can see a couple of things. The first one is this very large empty space that is going to show your projects later on. And if you look at the right of this, you can see scan, you project import and a few more that we can't use right now. What we want to do for now is to create a new project. And in here, we have to create a new folder. And this folder is going to contain our entire game. So all the acids we have our game are going to be in here and then go to asses what is project needs to be. So here we can select a path and I want to rename again to blade Fraga, but you can name this whatever you want. It really doesn't matter. And once you have that, you have to create on create folder to set up the game. So I click on create folder and now we get a nice checkmark that our game is ready to go. And we have OpenGL ES free and OpenGL ES two. And you don't have to worry about them at this stage in any meaningful way. All it really means is that OpenGL ES free is a more modern standard that can give you better results, but it's not as widely supported as OpenGL Cl2. So especially on websites, OpenGL tends to be more common. In our case, none of that is going to matter. So I'm going to stick with OpenGL ES 3 and click on create and edit. And now we can see an entire screen that we are going to be talking about in the next video. So don't worry about this for now. We're going to come back to this. And just to emphasize here, when we're using Goodall, we are not using Python itself. Instead, we are using g script. And what is too are very similar. There are some differences that you want to be aware of. And I will talk about them while I'm make our game. But about 95% is pretty much exactly identical. And if you're interested, there has an entire website about why GD script is made into weighted it is. And this talks and quite a bit of detail about how it is optimized for video games. And I will not go into this in too much detail. Just be aware we're using GD script and does some differences. So be aware of that. And one more thing before we get into our game at one year of good or running. You have this little thing running in the background and do not close that one. If you close this window, you also go into clothes could DO so. Be aware of that. And I'm going to ignore this window entirely, but you can use it to diagnose your game. But I am not going to worry about it whatsoever. But there was lots of stuff. Let's actually get into our video game and that's going to happen in the next video.
27. Blade Frogger 1: Intro: Hello and welcome back. Now that we have started our game, this is what we can see. We have quite a few GUI elements. So let's talk about how all of this works first before we start our game. Cause I think that's going to be really important to understand later on what we are doing. The first and most obvious thing we see is right in the middle of our screen, And that is called the viewport. And in here, we are going to see our game later on. And right now we have a 3D viewport. And if you hold down the middle mouse button and move around, you can rotate in this space, which already looks quite cool. And we're not going to worry too much about this viewport for now. Instead, I want you to look at the top of the screen. And right now we have 3D selected, but we are not making it free to game. We're making a 2D game. So let's click on 2D. And here we can see a two-dimensional space. And this is where we will develop our game for now. And our next game is going to be friday. And this is already the first major advantage of Goodall. When you create your game, you can literally see how the game would look like when you started, while you make the game. Whereas for pagan, For example, you can only see the code of your game. You can't actually see how the level would look like. And this already makes developing games so kudos so much easier. But alright, now we have 2D and 3D workspaces. And if you look one step further, you see script. And if you click on that, you can see, well right now you can't see anything. But later on in hears gonna come our code. So all the interactivity and the actual code we're writing goes in here. And there's one more tab called acid lip, but we're not going to use it. By what happens in here is that you can load add-ons to Godot, but we're not going to do that. And this is a bit more of an advanced topic, so don't worry about it. And for this game, we are only going to look at script and 2D. And if you want to switch between them a bit faster, you can use F1 for 2D, F2 for 3D, and F3 for script. So that makes it much easier to switch between them. Now we can see our game, but how do we actually create a game? And to do that, we have to cover two more fundamental concepts in Goodall. And those are called scenes and nodes. So let's talk about those. The most basic building block in Godot is called a node. And notes can be lots of different fields. In node could, for example, be a picture, or it could be a timer, or it could be a 3D object. It could also be a collision object, or I could just be some texts. There are literally hundreds of different nodes that could do has. And all of these basically create our game. So for example, a game character could consist of several nodes. So it might have a picture that represents the player, and it could have a collision box around it. And notes can do quite a few different things. We could, for example, change the properties of our nodes. And we can also make nodes communicate with each other. So for example, if we have a timer node. Timer runs out. We can tell another note that this time has run out, which is what you are going to do in Goodall quite often. So these nodes are basically what creates our game. Well, let's say all the elements inside of our game. But by default, none of these are going to be shown. And to show them, we need our second concept, and that is a scene. And scenes in Godot are basically the counterpart to surfaces and PyGame in the sense that a node is only displayed to the player if it is placed on a sea. But syncing Goodall are quite a bit more powerful than surfaces and PyGame. And they're doing quite a few different things. And we are going to go for all of them in a bit more detail later on. But the important thing for now that you have to remember is that a node and Goodall is only shown if you put it on the scene. And he can put scenes inside of each other. So you could have a scene inside of another scene. But with all of that covered, let's actually look at the GUI elements of Godot. So now we're back in our editor and we can still see our viewport. But what I haven't talked about is this tab above the viewport. Right now, it says empty. But if we saved it, we could give it any name. And each of these tabs will be a c. So this right now, but we have open is a scene that is not being saved. And if we click on this plus icon, we would add a new scene. Now we've never seen and we could also save it. So we could create lots of different scenes by just opening new tabs and McDonald's and close them because we don't need them. So this is how you create seeds. You just add new tabs and then you can save them. So now how can we add notes to the C? And for that, we have to look on the top left. And there we can see our scene tree. And this is where we are going to add our nodes. And Qdot already gives us some basic nodes. We have a 2D scene, a 3D scene, a user interface and other nodes. And if you click on over notes, you can see all the different nodes could DO has. And this becomes especially obvious if you open or a sub folders. There, it gets quite extensive. So there are loads of different nodes you can use. And we will go through quite a lot of them. But usually what you do to select nodes is to use the search function. And here, for example, if I wanted to sprite, I just type in sprite and then goto gives me a sprite. So this is the easiest way to go on about this. So from this part here, you will be adding new nodes. And an important thing here is that every scene always has to have a root node. And this root node basically determines what the scene does as an overall scene. So for example, if you put just a picture as the root node than every other element in this scene would be relative to this picture. It sounds a bit weird, but it starts to make sense quite fast. Then we get a bit more into our game. Don't worry too much about it. But let's actually do an example. But now I want to select another node. And I just want to add a picture to our game. And pictures in Godot are being added with a sprite, which I still level. So I click on sprite and I'm going to click on Create. And now we can see in the top left we have our sprite. And to add a picture, we have to look at the right. And here we can see our Inspector. And what the inspector does is that it gives us all the attributes of our node. So right now we have a sprite selected and Indian spectrum. We can see all the attributes of this particular sprite. And there are lots of different things in there. For example, if you look at transform, they would see position, rotation and scale. And he could influence all of them inside of this inspector. Or you could use code to influence them. But let's actually add a picture to this. And to add picture, obviously we need a file of a picture. And for the files in the bottom left, we have our file system. And this is where we can see all the files in our game folder. And right now because we didn't import anything, we only have an icon now P&G that comes automatically with every good DOE project. And it's just a logo of Godot. But if you want to add this icon to our sprite, We have to drag and drop this icon into the texture in our inspector. And if I do this, we can see a picture right inside of our game. And if you select this by left clicking on it, then you could even move it around just like any other element. And if you now look in our Inspector, it already shows us where the position is. And now we can also rotate it. Or we can change the scaling of it. And just compare how much easier all of this is compared to PyGame. Because I'm PyGame. To just achieve this state, you would have to write quite a few lines of code. And even better if we now actually want to run this game, we wouldn't have to write any code for that. All we have to do is click on this little icon at the top. It says play. It wouldn't work right now because we have to save our scene first. So let's actually do this. And to save a scene, just click on Control S, like in any other program. And here we can see the folder we have created earlier. And I want to create a new folder that is going to be for the player. So I right-click and create a new folder. And then we'll do call this player. And inside of this folder, I want to rename this to Claire. And then this is going to be its own file that is called T SCN, which is short for scene. So each scene in Godot is saved as its own file, which really hubs to organize our game in a modular way. But alright, let's save all of this. And now we look at the tab on the top, you can see player. So that's the name of OSC now. And now, if I click on play, Godot was going to give me one more notification that it wants us to select a main scene. And this is another interesting concept in judo. So think back and PyGame, we had one display surface that was always displayed to the player. In Goodall disk works differently that each scene could be displayed by itself. But because of that, could DO does not know which scene is supposed to be shown when we run our game. And because of that, it wants to know what's the main scene. Which basically means that what's seen as being loaded when you start running the game. And for us, since we only have one scene, there's going to be the Pliocene. So I double-click on that and node loads. And now we can see our game. Obviously right now, we can't do anything because we haven't added any code for that. But we did get to working stage of a game within a couple of seconds. And we did not need to write a single line of code. Which is really nice. So let me close this. And one important thing is that the game we have been seeing was this blue rectangle here. And you can change quite easily how large does boxes. But for now, we're not going to worry about this too much. And that's going to be one more concept I do wanna talk about before we get into the actual game. And that is that our notes inside of the scene are organized as a tree. And let me illustrate this in a bit more detail. So if this sprite selected, I click on this plus icon at the top left, which says add child node. And you can also use control a for the same purpose. And if you click on it, you are going to get to the same menu we had before. And what I wanna do for now is at another sprite node. And what we can see now, it's worth one sprite and as another sprite below it. And they're connected via this line. And if I double-click on it, we can rename them. So let's call this child sprite. And this one we can name player. So now we have a player's sprite and a child Spark. And what child spread means is that whenever we change this player sprite, this child sprite is also going to be affected in the same way. Now what does that mean? Well, let me illustrate. So today's Charles pride. We also going to add this Eigen picture. And now we can't see a difference. But now let me drag this finger away. So now we have two pictures on our screen. We have the child node and we have to play a node if the child's broke being a child of the player. And now if we move the player, we would also move the child node. And this would also apply if we rotated it or if you change the scale. So every time we are changing the parent node, we are also changing its child. So let me remove all of this to normal. And this is why it's important that what the root node is foreseen business where every other node is being influenced. But a simple reasons that every other node besides the root node we're adding to all seen, they are all going to be connected to our original root node. But alright, this was a lot of theory. So in the next video, we are actually going to start making a game character. And I will see you then.
28. Blade Frogger 2: Player character : Welcome back. In this tutorial, we are going to start creating our player character. For now. It is not going to move or not really do anything. We're just going to create a main setup for it. And in the next video, we are going to make it move. But the important part I want to cover for this tutorial is how to create a main game character by combining different nodes. And that should be quite a straightforward things. So let's jump right into our code editor and let's have a look at this. So here we are back in what we have created earlier, and it really doesn't do all too much right now. And we also don't have too many pictures that we could be using. So let's start working on these ones they want. The very first thing I want to do is to import some images that we can use for our game. And doing that is actually really easy. So here you can see the folders I have laid Fraga is our game folder. And then I have a folder called Blade Fraga assets. And this is where all the resources are. And to import these into our game, all we have to do is drag them into the folder we have created earlier. So microbes, I literally just drag it in there. And now whatever turned to good, oh, it loads all of them. And now we have Blade for gases. And if I dropped down, we can see audio car formed level player and screens. And if you have more of them, we can see quite a few different images, which is all we needed. So that's a good start. So now we have all the resources that we need. So now we can start creating our main game character. And to start that, let me first delete the child sprite because we're not going to use it. So I just right-click on it and delete node and then go double checks. And I do want to leave this one. So now we're back to our Player sprite. And the first thing I want to do is replace this icon with an actual image of the player. And for that, if you look on the bottom left, the file system, there's a whole folder with player, and there are quite a few images in here. What they basically are is a walk cycle that we have walked on one walked on to worked on free. And they're basically different images of the walk animation. And if we play them fast enough after each other, it looks like our main characters walking. But alright, now to import this one, I just have to drag this walk down into the texture sludge of our sprite. If I do this, now we can see omega and character. And there's one mistake I made. So let me zoom in quite a bit. That if you look at this, it looks very blurry and doesn't really look all too good. And this isn't because the image file is low quality. This is because we imported it in the wrong way. And to change import settings, if you look at our scene tree, yes, an input tab. And if you click on it, you can see lots of different things for importing. And one important thing is if we become preset, that says 2D pixel. And this is the one we need to have selected. So if I have this one selected and click on re-import. Now looks much better and like proper pixel art. And the problem we have right now is that we have lots of different images that all look like this. And then we would need to re-import manually, which would be quite labor intensive. So that's not good. By what it can do is if you click on preset again, now we can set default for texture and as, as 2D pixel. So let me just select it again. Set default for texture. So now every time you're going to import something, it is going to be imported in that way. So instead what I'm going to do is I'm going to delete this entire folder by right-clicking on it and clicking on delete, and then remove this entire thing. And now play has survived because we are using this picture. So let's get rid of this one and also delete player and remove all of this. So now we're back to our default. But now, if we are doing the same step again and reinforcing the folder again, like this. Now when we do import all of this, then it's going to import it in the proper way. So let's now trailed off this again. And now it looks like a proper pixel art. And even if you use a different image, they all look like proper pixel art. And this is a fairly common problem in good tool that when you import something, you have to import it in the right way. And this can really be confusing in the beginning. But alright, I hope that made sense. So now we have our player character and let me move it back to position 00 by clicking on this eigen. So now we have our player in the top-left. And on that note, actually, just like in PyGame, the coordinate system starts at position 00 in the top left. So if you want to go down, you have to increase why? And if you want to go up, you have to decrease why? This works very similar to pi it. Now we have to figure out how to create a properly functioning main player character. And to figure out what kind of notes we need, we have to figure out what our main player character is supposed to be doing. And there are a couple of things that we need to do. The first one is that our main character has to be visible. So we have to have some kind of image that we can show to the player. That part should be quite obvious. The next part is that our main character has to be able to collide with something because we wanted to be able to collide with cars. And the first one is that we can control our player and make it move around. So these things are really important parts that we have to address. And in terms of nodes that we need, the collision One is a really important one because we need a specific node that can account for collisions. And Godot has a couple of nodes that can work with collisions. The one we're going to work with for now is called the kinematic Body 2D. But there are a couple more that we are going to discover later on. But for now, since this node is going to be so fundamental to our game, we have to make this the root node. So here I'm back in our code editor. And the first thing I want to do is change this bright note to a kinematic Body 2D node. If you right-click on it, you can change type. And this is changing the spread node to whatever we want to have. And in my case, I want a kinematic Body 2D. And if I click on this, everything disappears again. Because a kinematic Body 2D does not hold any images. It also can't collide with anything. The best way to think about kinematic Body 2D is that it is an atom in a physical space. So it can be affected by physical forces, but by itself is not visible. And it cannot collide with anything because it's too small. But both of these we can address quite easily. So let's start by making all of this visible. To make it visible, I want to add another node. So I press control a, and now I add a sprite again. And you can see in a recent tab we can see sprite. So I had this one again. And now I add our player character again. So I'll walk down animation. And now we can see our player. And the important part now is that this bride is a child of our player node. So if we move our play a note around, we're also moving the sprite. And later on, when we control our player, we are only controlling this specific point in space. We don't actually control the image that the player sees. Now we have an object that can be affected by physics and that the player can see. But the one thing left is that we cannot collide. And Qdot is actually complaining about this. So when you look next to our Player sprite, there's a warning icon. And this one says that this node has no shape, so it can't collide or interact with other objects. And consider adding a collision shaped 2D or collision polygon to the child to define its shape. So let's do that. So we have to play a selected, I'm going to add another node that is called collision shaped 2D. And now Godot gives us another error message is shaped must be provided for collision shaped 2D. And that we can do really easily. All we have to do is go back to the inspector and there's a slot called Shape. And if we click on the drop-down icon, we can see a couple of options. And what we are basically trying to do is to create a shape that encapsulates our player in the most appropriate way. And in our case does is just going to be a rectangle. So let me click on this. And now we can see a faint blue icon above our player. So let me zoom in on this. This bluish box here is the actual shape of our player. So this is the box that is going to actually collide. And there are a couple of red dots around it. And you can use these red dots to change the size of the rectangle. So I can move it up, for example. And I can move it a bit further to the right. And what I'm trying to achieve is that this blue box encapsulates the player entirely. And I think this looks pretty good. And move out of the Upon than we actually have our main player. So now we have a physics object that we can move. We can see it, and it can collide with other objects. There's one more important thing I do want to talk about that the order of these nodes doesn't matter. And let me just illustrate what this means. Right now this sprite comes before the collision shaped 2D. And because of that, this collision shaped 2D is above the sprite. But if we changed it, so if I move the collision shaped below the sprite, then our sprite would be in front of it. And basically what that means is that if a node is further down in the century, it is above another node in the actual game. So it's basically inverted. But alright, there was quite a lot of different concepts. So let's do an exercise to make sure that you have understood how all of this works. And what I want you guys to do is to create a new node for the car. And what I wanted you guys to do for the car is to make it quite similar to the player. So that we have a kinematic note that collision shape and it's pride all inside of a new scene. And you can find the car images in the car folder. So it should be doable. But pause the video now and see how far you get. So let's create a car. But before we come to that, I made one mistake. And really sorry about that. That right now, if you're trying to save the scene, we're gonna get an alert. Era was saving. And a reason for that is that last time we used to play a note, we also deleted the Player folder so that good old doesn't know where to save it. But to change that, we just have to create a new folder that says player. So this is what we originally had it. And if we have that, now we can save our player. Because now it has afforded to save it. And here we can see our play a scene, the one scene we have open right now. Let's actually get to the car now. And to get the car, I have to create a new scene, which I do by clicking on this plus icon. And I'm going to add another kinematic Body 2D. So kinematic Body 2D. And to make sure you're not adding a kinematic body. So the red icon here, because this one would be a three-dimensional kinematic body, which we don't need for this game. We wanted two-dimensional one. Let's click on Create. And let's rename it to car. And let's save this one. So I click on Control S and go to our main folder. And I right-click and create car. And could do already suggests the name of the root node as the file name of the scene. So I click on safe because I like the Carnegie. And now we have to do the same thing we have done before. We have our kinematic body. And I want to add another node. So I click on the plus and add a sprite. And now into the sprite, I am going to add, you can choose any of the cars. I'm going to go with yellow one dot PNG. I drag it in there. And it's quite a large file, but for now, don't worry about it. We can change this one quite easily later on. So now we have an image and around us image we want to add a collision box. And for that, we need a collision shape. So now we have a collision shape. And what we wanna do is add a shape around it. And again, I think a rectangle is the best shape for this. So let's click on it. And now we need to use the red dots to make it roughly the same size. And yeah, it looks about right. Could actually do it a bit less because if you just touch on parts of it, that should be fine. Or if you just click on the blue box, you can move the entire thing wherever you want. And if you hold shift, you move it in one axis. So right now I hold shift and I move it up and down, or left or right. And in my case, I just want to have roughly drop it into the middle. We are going to change of this a little bit later on. But for now, this one is fine. So now we have a car that starts as a kinematic note, as a picture and as a collision shape. So that's a pretty good start. And let's say this one. And now we can also see our car folder and L are Player folder. So we're making pretty good progress. And in our next tutorial, we are actually going to make our player move. I will see you then.
29. Blade Frogger 3: Player Movement: Hello and welcome back. In this video, we are going to make our main character move. And this is also going to be the part where we're going to add some code to our game, which is another major step for Godot. But I think it's best to explain what I am doing it. So let's jump right back into our code editor and let's have a look at this. So here we're back in our editor and I have our player seen open. And what we want to do is to move this play a note around whenever we press a button on the key. So if we press right on the keyboard, we want to move this thing to the right. And the same for all the other keys. And for that, we are going to need a script. So we have to add a script to this note. This is always how cold works and good goal. A piece of code always has to be connected to a node. You cannot have code by itself. But to add code to a node, you need this gigantic top that says attach a new or existing script to a selected node. And if you click on this, we get a new menu that we can choose the language. So we can choose GD script, Visual script on native script. But we are going to stick with GD script because it's basically Python. Then it needs to inherit for something. Don't worry about this for now. Then we have a template and as default, empty and no comments. And for now default is fine. But later on you want to move to Mt. All it does is it gives us some suggestions for the code, but don't worry about it for now. Then we have built-in script. And oldest one is asking if you want to save the script as its own file or as part of the node. In our case, I leave it as off by the good switched it on, it really doesn't matter. And then we need to path. And in my case, I want to have the player script inside of the Player folder because that's where it makes the most sense. But had moved up and down. Let's click on Create. And automatically, UDL brings us to the script folder. And in here we see a couple of comments about how to declare variables. We can see a function, and we can see another function and comments. And I think for now, you don't need any of this because I'm going to explain all of this in detail. So I'm going to lead all of us. Besides the first-line, they extends kinematic Body 2D. And the line like this has to be in every single script. And basically what is happening is that whenever we are creating a script on a node, is that we are giving the node more power. But to do that, we have to start from the node. So it is white descript always has to extend from an existing node. And usually good DOE does all of this automatically so you don't have to worry about it. But right, there are a couple of things you do want to be aware of for good Door. The first one is that the naming conventions are slightly different compared to Python. Not too much dog. So for example, in Python, if you wanted to create a new variable, you just write something like a equals 200. In Goodall, This does not work because we need a specific keyword to create a variable. This keyword is called var, which basically tells Godot that we wanted to create a new variable and the value of this variable is going to be 200. So it kind of works like Python. We just need to add one more key word. But that is literally it. However, they are two different kinds of variables. In Buto, we have the normal variables and we have constants that are created by using the keyword const. Slab. Use cons b equals 200. And they're both credit and quite similar ways. And the only difference is that a variable can change its value in the duration of the game, whereas a const only be changed in court. So once the game is running, this constant is not supposed to change while the game is running. So just could be something like a gravity or some variable that never changes in our game. And domain reason why this exists is that if a variable doesn't need to change, it can run a little bit faster, which is something that is really valuable for a video game. And for our game, we actually need one constant and that is the speed of the player. So let me just call it speed. So what we're doing here is we create a constant, so variable that cannot change, and that is speed, and that is the value of an integer of 200. And since our game is so simple, this could also be a variable. It really doesn't matter for our purposes. But now what we want to do is to create a function that is being called on every single frame of the game. Because this is what we need to get keyboard input that we have to check on every single cycle of the game loop. If something is pressed, and if that is the case, then we want to move the player in that direction. And this brings us to functions in GD script and functions and gt script up basically identical to functions in Python. With the one difference is that you use a different keyword. So instead of defining test foreign, we wouldn't need to keyword Funk. And once we have that, everything works in the same way. So let me just add a pass. This would be a valid function for GD script, which left a keyword to create a function. We have the name of the function, and we could create parameters for the function. Then we have a double colon, and then the next line indented, we create some code for this function. This is entirely identical to the one difference being that we have a different keyboard would really doesn't matter too much. So now, how can we call dy