Learning pygame by making Flappy Bird

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello there for this tutorial we are going to be creating this flappy bird game it is almost an exact replica of the original I just like some slight updates and we are going to be doing the entire thing in Python with the PI game module which is ultimately quite a simple thing and the entire project takes less than 200 lines of code and I am going to go through these specific steps and I will be starting at the very beginning of game development so if you already know something I game it's quite safe to start a bit further down and skip ahead but if you don't let's start talking about how games work on a theoretical level because that's what we need to understand how PI game works to create any kind of game you need two foundational concepts number one is that you are able to draw a picture and update the picture and this is how any game works that you stop by drawing one picture and then you update this picture so for example if the player moves to the right then you draw the picture of the player a little bit further to the right on each different frame and if you're doing this fast enough then this looks like a fluid motion but if you are just drawing things then you have a movie you don't have a game and that brings us to the second part that you need some kind of game logic that informs where stuff has to be drawn on the screen and in here you want to take something like player input or get timers or enemy logic or the input from other players if you're playing a multiplayer game and these two concepts have to work closely together so that you are pressing a button to the right and you have some code it updates the position of the player and then the game draws the new position on a new frame so these two concepts are the foundation of any video game and you are going to see them in basically any game development and this is basically all we need to implement all of this in code but there's one more problem by default - isn't good at I've of these things when you use Python you're mostly constrained to the console and outputting information and for the input you only really have the input method which stops the code when you try to get player input which is terrible for video games so for both major steps that you need for game development vanilla Python does not work all too [Music] okay it's not that bad because you have lots of different modules that can help you with that the three most famous ones are pi game piglet and Python Parque and they all work on roughly similar lines although they ask some differences the one I'm going to use a spy game because it's the most popular one and two one I got used to to be honest but the other two libraries would work just as well do check them out I would really recommend them all of them are quite fun to develop on and you could also use something like Godot which isn't just a module for Python it's an entire game engine and it doesn't feel vertically use Python but it uses GD script we'll just basically Pyfrom of suspicious sunglasses and a trench coat if you can write Python you can write GE script and to kodoku Imogen has lots of convenience features that you can use but none of that really matters we are going to use PI game and it's quite a straightforward library so let's start talking about that and obviously the very first one we need for pi game is to install the module because it's an external one so if you're on Windows open the PowerShell if you are on a Mac open the terminal and in either case type pip install PI game and you should be seeing animation that PI game is being installed this should be quite a straightforward thing but with that part cover let's talk about how to start up PI game before you can use PI game you always have to initialize it and this happens with PI game dot in it and once you finish with your game and you want to quit PI game you have to uninitiated and that happens with PI games that quit so any game logic has to be between these two lines and they're quite simple it's literally just that so how can we draw stuff in between well the most fundamental concept is a display surface and this is basically a canvas we can draw on and once you have this canvas you could actually run your code and see a black screen for just a second but it would close immediately because at this stage you only told PI am to create a canvas you did not tell it for how long to keep it open so pi again creates a display surface and then our next line of code it doesn't know that's supposed to keep it open so it's closing it again and ends your program and to keep it open what we need is called a game loop and in this game loop is what I explained earlier this is what the actual logic of the game happens and also by the end of this game loop we are drawing whatever frame was created by our game logic so everywhere to create in here let's say a game character and move it to the right then we would create a new frame with different information and draw it at the end of this loop and that brings us to the first part that we need to cover in this game loop that we need one line of code that draws whatever frame was created inside of this game loop but besides that we are also going to need a second part at a very minimum and that is called the event loop and what this one does is it looks for events and events in most cases a player input for now we are not going to draw anything so our resulting frame is always going to be black but we can add lots of stuff to this later on but now let's go to the code and let's actually implement all of this so here in my code and the very first line is that I have to import PI game and if you're executing this code this should work and give you this message at PI game one point nine point six and hello from the Pagan community and the link if you get this one you have installed Piegan correctly and one point nine point six is the latest stable one now as I said before the first thing we need is PI game dot in it and this one initiate spy game and at least for now you don't have to know what that means in detail so now we've initiated PI game worth that one done we have to create a display surface and this one needs to be stored in a variable that is usually called screen by convention you could call it something else but screen is what you do see everywhere so I would recommend using this one as well and to create a display surface we need peg M top display ad set mode and you could pass in quite a few arguments in here but the one that you absolutely need is a tuple or list with two pieces of information and that is the width and the height of the screen I'm going to go with 576 and 1,024 so the canvas we are going to draw on is 576 pixels wide and 1024 pixels high and the reason I've chosen those dimensions is because they work really well with the size of the files so the background image for example is exactly half the size of these two so we can just scale it up twice and have a perfect background and since flappy bird was designed almost a decade ago for phones all the image files are quite small so I have to scale them up to have at least some kind of decent resolution but you could basically pass any kind of number in here depending on what you need for your game but all right now we have a canvas to draw on and if I run the code now we can see a black screen for just a second and this is what I explained earlier that if you run the code at this stage iëm creates a display surface for just one line of code and after this line it doesn't know what to do with it so it just finishes the code and closes all of this so to maintain it we are going to need our game loop and this is literally just while true so at the code runs perpetually and we have to break it from the inside and the first time we need in here is pi game dot display dot update and what this one does is it takes anything that was drawn in this while loop before it and draws it on the screen so if we're drawn here let's say image or layer 1 and background image if those two were actual images update would take both of them and draw them on this display surface obviously right now we don't have any of them so it's just going to be black and also if you were to run this code right now you would not be able to close it you would have to go to the task manager and close it from there the X button at the top of the screen would not be working so be aware of that and to make it work we need our event loop and this is literally just a for loop that runs on every cycle of the while loop so this really looks like for event in PI game don't get so basically what happens in here is that pygame looks for all the events that are happening right now and this could be something like you moving your mouse are you pressing a button or are you closing a window it could also be a timer for example that only triggers every second or so and pygame catches all of these and then inside of it we can work with all of these events and look for specific events you have to look for a specific type of event and for now the one type we are going to look for is PI game dot quit which is shortened for closing the game with the X button at the top of the screen so I need PI game thought quit all uppercase letters oh and I need an if statement so if this is the case then we want to run some code and the code we want to run the spy game not quit so we're doing the exact opposite we have done here we are uninitialized our game and this is literally the most basic setup you can have a PI game if we run our code now we are getting error message because I made a typo being double equal sign so we are checking if they are equal okay let's try this again now we can see a black screen it is 576 pixels wide and 1024 pixels high and it's just black because we're not drawing anything and I can close this and if I close this we're getting another error message but that is expected and the reason for that is that when we are calling pi game that quit this while loop is still not completely ending and we need another line of code to end properly and for this one we have to import this and this is giving us some access to system modules and the only line we need from it is cyst dot exit and this line basically make sure we shut down our game completely no matter what happens so if this one is run our code most definitely is going to end so now if I run it again we have the same output we see a black screen with the same dimensions that kills it now then we are properly ending the game so now you have learned how to draw a basic black screen congratulations but there's one more element we need it is going to get quite important and that is that right now we have no control over how fast this game runs and let me run it again so right now what it looks like is that we are saying one solid black image but as a matter of fact we don't instead what we see is that pi game draws a black screen multiple times per second and I have no idea how many times per second it does that and we do need some control over that and that is really important for video games and you might have heard of it it's called a frame rate and frame rates for video games are actually really important because they influence how fast our game runs and our fluid motions are and let me explain what this means imagine you have an image that you want to move from the left of the screen to the right of the screen so on every single cycle of our game loop we are moving at five pixels to the right and now how fast our game move updates is really important if it updates a hundred times per second and we move five pixels on every single cycle and we are moving 500 pixels in this one second however if our game loop only runs ten times in a second then we only move fifty pixels so effectively are we moving only one tenth of the speed which would give us very different experiences depending on what kind of computer we are running our game on and later on when our game becomes more complex we might end up in one part of a game where it's really busy where the game slows down and another part where the game runs really smoothly and the game speeds up immensely and then the player speed would be very different and everything would run at different speeds which would be incredibly confusing so what we have to do an hour game is to limit the frame rate so at our game can never run faster than a certain amount of frames which in my case is 120 frames because this is quite a high frame rate and looks very fluid but anything over 30 frames should be fine and to implement this kind of logic need a clock object and I'm going to create up here with clock equals high game thought time thought clock geordie of uppercase letter for the clock and this club object can help us to lots of different things the one thing we need for now is to limit our frame rate and this happens down here and what we need is clock dot - tick and into it we have to pass the amount of frames you want per second which in my case is 120 so when this game runs it is never going to run faster than 120 frames per second it can run slower though which is something we can't immediately control because this one is influenced by how much stuff is on the screen and how well your computer can cope with it so in your code you have to make sure that your game never runs too slow which basically means that not too much happens on the screen at the same time but in our case since flappy bird is so easy you are not going to have problems with that if I run off this again we still see the same black screen which well looks boring so let's actually put stuff on it and that brings us to the next topic and that is to put images on the display surface with regular surfaces and here's how that works in PI game you have two kinds of surfaces one is called the display surface and the other is called just the surface or regular surface it's usually just called a surface and these two are kind of similar and they have lots of similar methods that you can apply on them however there are two major differences number one is that you only ever have one display surface however you can have as many regular surfaces as you want and number two is that only the display surface is shown by default you can have all the regular surfaces as you want unless you put them specifically on the display surface they would not be visible but generally what surfaces do is they give you new layer that you can put stuff on so for example when you import an image this image we created on a new surface and then this surface you could put on the display surface and then it would be shown to the player and let's actually do that right now and this is bringing me to my game folder and in our game folder we have two files and two folders one has images the other a sound file and you can find the same folder in the description for this video and I am also going to put a link in the description on where I found all of these files and it is important that all of these are in the same folder just to make it easier to import them but let's import our very first image and all the images on the asset folder and when we import an image is going to be put on a new surface and this surface just like the display surface is stored in its own variable and the first image I want to import I am going to call BG surface short for background surface and how to import something is with pygame image thought load and now you need to file destination in my case this is assets / backgrounds - they dot PNG so now we have a new surface with this image on it and if I run the code you would not be able to see it because we didn't put it on the display surface and all of that happens in our game loop and the command we need is first our display surface variable so this screen here and the method we need is called lit and I have no idea why it's called lit but what this one does is suppose 1 surface on another surface and we need 2 arguments for this the first one is the surface we want to put on the screen surface and my case this is BD surface and now we - location where we want to put it but this is an x and a y position and this is going to be confusing so let me first show what I'm doing and that I'm going to explain so I'm going to put this file at location 0 and 0 so if I run the code now we should be able to see something exactly we can see the background image and right now it's exactly half the size of our screen and we are going to double the size in just a bit but for now let's talk about what we have done here the first thing you have to realize is that when we place this surface on the display surface is that we are moving the top left of this surface so I put it on position 0 and 0 we put the top left of the surface on the position 0 zero on our screen surface and this is always the point you move when you move surfaces you always control the top left but that brings us to the second question that y is zero zero the top left of our screen which is kind of confusing but in PI game this is where the origin point is and to better understand this think back of your high school days where you had a coordinate system it has an accent y axis and the origin point in high school was always the bottom left so that when you increased X you moved to the right and when you increased why you moved upwards in PI game this is kind of similar but slightly different the x1 is still the same that if you increase X you move to the right however the y1 is inverted because the origin points in the top left so if you want to go down you have to increase Y and if you want to go up you have to decrease Y and this is immensely confusing for basically everybody and it is going to take us some time to get used to it but usually people get used to it in a couple of days so just be aware of that but let's talk in a bit more detail about the dimensions of our screen so right now the top left is point 0 and 0 so the left side is point 0 and the top side is point 0 and if you were to go all the way to the right you would get to 576 exactly the point we have specified earlier when we called setting mode and the bottom of our screen is 1024 so these four points are the boundaries of our screen and we can move around on any point on the screen so when I go back in my code and let me close this and change any of these points I can move around in this coordinate system quite easily so let's say let me go to point 100 and let's say 200 then I go 100 pixels from the left and 200 pixels from the top and if I run the code now we can see we have moved a bit from the left and quite a bit more from the top and here's the thing we increased Y but we went downwards which really is a confusing thing and if I would set this to minus 200 we would be moving slightly outside of the screen so now the top left of our screen would be 100 pixels from the left but minus 200 pixels from the top and this is all we need let me put all of this back because we want to keep this at position zero zero so this is how you position something on this screen but right now this thing is only half as big as it needs to be so we need to take this surface and scale it up by two and pi game has a specific method for that and that left foot is called pi game the transform trends form and it's called scale to X and now we pass in VD surface in here so this entire method here takes one surface and it doubles the size of it and then it's going to return a new surface so we are going to need a variable to store this new surface and this one can also be BG surface so let me explain what happens here we first import our surface and we stored in this variable in our next line we take this surface and double it in the size and overwrite this variable with the scaled surface because we only disk ailed up version and with these two lines and i run the code now we should have a proper background picture so this one's working quite well and you could actually combine these two lines quite easily so if I just copy and cut this entire thing and paste it in there this one would also work quite well but I think this one looks cleaner there's one more thing we do need and that is got convert at the end of our import line and convert isn't strictly necessary but what it does it converts the image into a type of file that is easier to work with for pygame which basically makes it easier for pi camp to run our game and it allows us to run the game at a faster pace but when I run the code you are not going to see any change but if the game became more busy this convert would help him to run the game at a more consistent speed but all right now we're able to put images on our screen which is a pretty good starting point to move stuff on the screen and they're gonna start this by moving the flow on our screen so when you look at the original flappy bird on the bottom you have a floor that continuously moves to the left which is what we're going to take care of now and let's start by just importing the image and I've called this one floor surface and we're importing it in just the same way so I game that image download it is also in the assets folder and it is called based dot PNG and also just as before we have to convert it to make it easier for pygame to run and let's put this thing on the screen first so when it's green dot lit again and this time I want to put our floor surface and just for start let's play that position zero and zero so this line is exactly the same as this one and if we run the code now we can see the flow of right at the top and just like the background picture it is half the size it needs to be so the first thing we need is to scale this thing up which is the exact same logic just this again my game dot transform to scale to X and floor surface so I run it now we can see a properly sized floor and we have to move it downwards so in this line I'm going to put the floor at position 900 so if I run our code now we can see the floor in the bottom but it is entirely static right now so how can we move it well it should be quite obvious because all we do is update this point by a tiny amount on every single cycle of this while loop so let's I write now zero on the next cycle I wanted to be at position two then I want to be at position 4 then position six position eight and so on we move it by tiny increments and because these increments are so small and all of this happens so fast then to us that is going to look like a fluid motion a hand to get this kind of logic I'm going to create a new variable that of lower x-position and by default this is going to be zero and let me replace this one down here with floor x position so this is going to get us the exact same result because in the variable we have the integer zero then we had before so no change but what we can do now is before the line low X plus equal one and if I run the code now it is slowly going to move to the right and this is something you really have to understand about video games that on every single cycle of this while loop we are drawing all of this over and over again this image is never static it is always redrawn and what effectively happens here is that at the start this flow x position is 0 but on a next cycle of this while loop is going to be 1 and then it is going to be 2 & 3 & 4 so every time we are drawing this line again this position increases by a tiny amount and then the outcome is that to ask it looks like it's moving and just to illustrate this a little bit better let me increase this number drastically and let me lower the frame rate to let's say 1 and now you can see quite a bit better how it is good to look now you can see a very slow movement that every single cycle of this loop is going to move a bit further to the right so let me remove all of this to normal so this is the basics of animation and in our case this one here would move to the right but I want it to move to the left which in my case is the exact level direction so minus 1 let me run this again and this looks like a decent speed but obviously the flow is disappearing which is not ideal so we can work on that one now and here's the logic how I'm going to fix this I'm going to have two floors right next to each other and both of them are going to move at the same speed to the left however if the right floor is at position 0 so on the left side of the screen and I'm going to move the first one to the left side of the screen and the right one even further back and how this looks to the human eye is a continuous movement and I'm going to put all of this into a dedicated function just to keep this game loop a bit cleaner and I'm going to call this function draw door and at the top of our game I am defining draw floor and it does not need any arguments and in here I want to draw or put the surface on the screen but I want to put two surfaces on the screen so let me copy this entire line and I'm going to add plus 576 on the x-axis so what does that mean you might already see the similarity 576 is the width of our screen and the width of this floor is also 576 so we're drawing this flow on the left side of our screen at position zero and we're putting this floor on the right side of this initial floor surface so that both are right next to each other and since floor x position is still decreasing both are going to move at the same speed to the left and let's try this now we should be able to see a longer moving floor for quite a bit but it is still going to disappear at some point there we go so this is what we have to fix and how I'm going to fix this is after the draw flow function I warned if floor x position is smaller or equal to negative 576 which basically means if the left surface is too far to the left we are going to do something and what we're going to do is flow x position is going to be 0 again exactly where we started and if I run is now we should be able to see a continuously moving floor because once this flow is going too far to the left is being reset to this point here on the left side of the screen and since after this happening so fast to us it just looks like it's continuously moving we don't ever actually see the transition and with that way for a basic animation so that's a pretty good start and now that we have a background let's start talking about our bird and we are going to import the bird in just the same way as we imported the background and the floor however when we put the bird on the screen we are going to need a different process although it's not too different but there are a couple of reasons why we need to change the process a little bit number one is that for our bird we're going to check collisions and surfaces by themselves cannot check for collisions reason number two is that we want to have more control over how we place the bird because when we are going to rotate it we want to rotate it from the center but with surfaces we always move the top-left point which wouldn't allow us to rotate from the center and because of these two reasons we can't just use surfaces they're going to be part of it but we are going to need another tool to implement these two functionalities and the tool to get both of them is called a rect short for rectangle and a rectangle is quite a simple but really powerful thing and well it literally is just the shape of a rectangle but this shape of a rectangle can do quite a few different things number one is that you can use lots of different rectangles to check for collisions between the rectangles and later on in our game both the pipes and our bird are going to be surrounded by a rectangle that you can't see but we are going to use them for our collisions and number two is that when you place a rectangle on the screen you have lots of different points that it could place on the screen here are all of them so why we always place the top left of the surface for a rectangle we can place the centre or the mid left or the bottom right lots of different points that we can place on the screen and all of these points have an X and a y-coordinate so you could literally place them anywhere on the screen and there are two ways to create rectangles number one is that you can use pygame to direct and implement an X and the y position and the width and a height and then you have a rectangle in a certain position but you don't use them that way all too often instead what he would rather do is that you are taking a surface and he put a rectangle around it so at this rectangle is going to get the exact same dimensions of the surface and then it can place this rectangle somewhere on the screen and then you could put the surface on top of the Z rectangle and if you approach it like that you can check for collisions and you can rotate this surface in any way you want and this is exactly what we are going to do so let's actually get into our code and implement all of this so here I am back in my coat and the first thing I'm going to need is to import the actual picture of the bird and I'm going to call my invert surface and we are going to import this just as usual hi game image to load it is in the assets folder and in that folder they have three different versions of the image for different cycles of the animation of the bird flap for now we are just going to use the mid flap but later on we are going to animate the bird but for now I'm just going to use blue bird - mid lab dot PNG and as always I'm going to convert the entire thing and then our next line same as before again it's PI game transformed scale to X and we pass in our bird surface so so far exactly the same process no change here but now we're going to do something new I will create a new variable that I called bird right short for bird rectangle and this one is going to be bird surface get rekt and what this one does is that it takes this new surface and puts a rectangle around it and the argument we pass into it is what we want to place this resulting rectangle and the first thing we have to do here is to grab one point from the rectangle in my case this is going to be Center and now this needs a tuple with an X and the y position and for now let me put it up to 100 pixels from the left and now we're going to put it in the middle of the screen so literally half of that dimension which is 512 so now we have a rectangle it has the width and the height of the surface and the center of this rectangle is on this coordinate point we can't see it right now because we first have to draw it in our game loop and let's do that so in the game loop under to add screen delete just as before and again I want bird surface but now instead of putting it to PO I just put in our bird rec tank and this should be working and yeah here we go we have our bird but instead of just having a bird we also have a rectangle around the bird and we can use that rectangle to check for collisions and also to rotate this image but before we get into that let's first give it an animation so it falls down and we can jump or flap or however you want to call it and let's start by making it fall down and to make something fall down we need gravity so in let's do it up here I'm going to create with a comment section that I'm gonna call behavior variables and the first thing I need in here is gravity and gravity for now I'm going to put at 0.25 and this has no resemblance to the real world I am literally just picking numbers that look good on the screen and besides gravity I want a second variable that I'm going to call bird movement and by default this is going to be 0 and this is the variable I'm actually going to apply to the bird later on so effectively what we're going to do later on is we're always going to add this gravity on every frame to this bird movement and then this bird movement is going to move this bird rectangle down and then if this bird rectangle goes down then this bird surface is going to be put on different positions on the screen sounds complicated but as actually implement this and let me first put some white space in there so the first way I want to do is bird movement plus equals gravity so bird movement on the first cycle of this while loop is going to be 0.25 on the next one's going to be 0.5 then 0.75 and 1 and so on so this number is slowly increasing which is a pretty good stuff for gravity and now we have to apply that bird movement to our bird rectangle and this we can do with a different point that I haven't shown yet because rectangles have quite a few more points and you can see all of them on the screen right now and what of these points have in common is that they only move in one axis so for example Center Y is only up and down and Center X only goes left and right and they only use the X and the y position so you couldn't use these points to place the rectangle but you could use them to move the rectangle and if you move any of these points you move the entire rectangle and this is exactly what I'm going to do because what I want is Bert and that's correct not Center y plus equals bird movement so if I run the code now we can see our bird falling down and well we don't have anything to counteract it so the bird just keeps on falling down and we can never see it again and at some point PI game starts to have bugs and the bird starts at top again but that is not going to be a problem for us I'm going to fix that one later and let's actually work on that for now that we want to give our bird the ability to move upwards and for that we have to check for keyboard input and this is going to happen in our event loop and we are already checking something in here that if the player closes the game and in here we now want to check something else and that is if event dot type is equal to PI game dot key down which checks if any of the keys of your keyboard have been pressed down and now we have to check for a specific key which you check with event dot key so this event when it's triggered by a key down is going to have another attribute that is key and PI game has lots of different names for different keys and the spacebar is called pi game dot key space and this is the one we want to check so now if you press space let's not just test if this is working I want to print let's call it flap so we run this again and if you look on top I press space and we can see flap so this one is working well so what we have to do is replace this one with some actual code MX or bird jump and to make our bird jump all we really have to do is make this bird movement negative because if it is negative or bird is going to move upwards and it's only going to move upwards because at some point this gravity since it's continuously increasing its going to move the bird downwards eventually again so what we want to do is spread movement minus equal and let's say 12 for now and let's test us so this is kind of working but there's one problem with that and let me press you can kind of see what happens that let me try to get the bird on the screen okay it doesn't work so the problem here is that disparate moving right now doesn't really work and there's a fairly straightforward reason of why it doesn't work and your reason for it is that this bird movement has to be 0 when we are triggering this line here and let me just illustrate this let's say we're moving gravity for a few seconds so our gravity is something like 20 now when we press our space button and we just subtract 12 from this our bird is still falling down it is just falling down to slower pace and only if we press space again then we're at a negative speed so we're moving upwards over now if we press it again we are jumping even further upwards so the faster we are pressing space the higher we are going to jump and at the same time if gravity's been running for quite a while then if we press space we're not going to jump at all we just fall to slower speed and all of this can be prevented by just turning third movement to zero before we are going to jump so that effectively we are going to jump we disabled all the effects of gravity so far and just apply the speed of the jump so if I'd start this now this should be working much better so now every time the jump height is going to be exactly the same which is exactly what we wanted but we still have our effects of gravity and this seems to be working quite well cool and now that we have our basic bird let's add the pipes and then we have a basic game and then we can refine things after that and the pipes are going to be put on the screen in a similar way compared to the bird we are still going to import a surface we are putting a rectangle around the surface and then we place the surface on the screen wherever the rectangle happens to be but there's going to be a bit more logic because we don't just want one pipe we want the pipes to continuously move from the left and we also want to spawn new pipes every couple of seconds and we can implement this fairly easily but we are going to need a couple of new things but let's go for the step by step and let me start by just importing the pipes so here we're back in our code and what I want is to import what I'm going to call pipe surface and just as usual pygame image load and the pipes are also in the assets folder and they're called pipe green dot PNG and let me just copy this entire line and this is going to be my surface and pipe surface again same process as usual but now it would be kind of pointless to put this surface into a rectangle because we don't just want to put this one surface on the rectangle we want to continuously put it on the screen and here's how I'm going to approach this I'm going to create a new list that I'm going to call pipe list and enter this pipe list I'm going to put lots of rectangles that are continuously moving left words and then in our game we are using these rectangles to place a new surface on each of these rectangles and since all of these rectangles are moving left words it looks like the pipes are moving left words as well and we're also going to create a timer that is going to create a new pipe every second which we are going to create injustice but let's start by just creating an empty pipe list so pipe lists and for now it is literally just an empty list and into this later on we are going to put lots of rectangles and how we are going to create one of these rectangles is by using a timer and timers and pygame actually work fairly simple the first thing we need is a new variable that I need to call spawn pipe and somehow by convention these are always typed in uppercase letters you don't have to do it but it's just good practice I suppose and what we want here this pygame dot user event and this also has to be in uppercase letters so now we have a user event and this user event kind of works like the events in our event loop except this one is not being triggered by clicking a button or by moving the mouse instead is going to be triggered by a timer and this time I we're also going to create here and we're going to create a Swift pygame the time or set timer and now we need our event which is spawn pipe and now the length of the trigger so how much time we want to pass since it's going to be triggered and in my case I'm going to go with 1200 and this is a milliseconds and one second has 1000 milliseconds so what we're looking at here is 1.2 seconds so now we have an event that is going to be triggered every 1.2 seconds but we don't have any code for it and this is also going to happen in our event loop so I have to create a new if statement here that if event dot type is equal to spawn pipe and just to check if this is working let's print pipe and yeah that we can see a bit over once a second we can see that - Prince pipe in the console so this one is working quite well we are making progress so now every time this event is triggered we want to create a new pipe and add it to this pipe list and this I'm going to do for now with pipe list dot append and in here I'm going to use a function that I'm going to click create pipe and what this one is doing is it returns a new pipe with the dimensions of a surface so let's create this function here and for that we're going all the way up and create a new function that I'm going to call create pipe doesn't need any arguments and let's create a new variable here that I'm going to call a new pipe and this one is going to work just like this line down here but we use a surface then getrekt and then place two resulting rectangles somewhere on the screen so what I want in here is pipe surface dot get wrecked and now we have to place this somewhere on the screen and for now what I want to place is mid top so we take the middle of the top of this rectangle and place it somewhere and for now let me place it right in the middle of the screen so X is 288 and Y is 512 literally half of these dimensions and once that's done I want to return new pipe so now when ever we are using this event it is going to create a new pipe and it's going to store it in this list and let me actually print the entire list every time this is running just to check if that is working so we can see one rectangle we can see a second rectangle then we can see a third rectangle and so on so here we can see we have one rectangle and we have two rectangles and we're free rectangles they are on the same position for now but we are going to work on this in just a bit but for now we do know it is working but we don't just want to keep all of these rectangles in the list we actually want to use them it's let me get rid of this and I'm going to create a new function that I'm going to call move pipes and well this function moves pipes it's quite obvious I think and this function is going to get a parameter that I'm going to call pipes so what I'm going to pass in here is the list of all the rectangles of the pipes that is going to get new pipes every time we are running this event and what I want to do is four pipe and pipes so for each rectangle of a pipe inside of this list and what I want to do is pipe dot Center X - equal let's call it five so basically what this function does is it takes all the pipe rectangles and moves them to left by a little bit and once all of that is done we want to return pipes so what basically happens is that we are taking a list of pipes then we go for every single one of these pipes and move them to the left by tiny bit and then we are returning a new list of pipes so all this function really does is it influences all of the different rectangles and then creates a new list of new rectangles and in our game loop let me give some space let's do it below the bird and let me actually give some comments about what we are doing because that is going to make it much easier to see what's going on let's just call this bird so and let's call this actually floor now I want our pipe list is going to be move pipes and pipe list so we tagged all the pipes in this pipe list and we're going to move them by a tiny bit and then overwrite this existing list and with that we have moving rectangles but we still haven't drawn them yet and that I'm going to do afterwards and this is going to be happening in a function I call drop pipes and well it Rose pipes just like it moves pipes so we create a new function that I called draw pipes and again I'm going to pass in pipes and now kind of like the logic before we want to cycle through every single pipe in this pipe list and draw it on the screen so this happens again for pipe in pipes we want to go screen split and now we just take the surface we've created earlier so this one here which is pipe surface and now pipe and now we should actually be able to see all of our pipes and we cannot because I forgot to pass in our pipe list here quite an easy fix now we can see that the pipes are spawning in the middle of the screen obviously it's right in the middle of the screen that doesn't help too much so what we have to do is spawn am further to the right and let's actually do this right now and this is going to happen in here when we create the pipes they are going to be spawned at position 288 so in the middle of the screen and instead what I want to do is to go a bit outside of the screen let's say positions 700 so we have some wiggle room and if we run the code now we can see our pipes coming in from the right they all have the same height right now which isn't great but we do have a start also well we need to top pipe as well so let's work for all of these points and the first thing I want to work on is that we have pipes with a different height which means we need two random numbers which means we have to import the random module and I'm also going to create a new list that I'm going to called hype height and these are all the possible Heights that our pipe can have and I'm going to pass in fear 400 600 and let's say 800 so these can be the positions of our pipes and every time we create a new pipe we want to pick a random number from this list and this is going to have them all the way at the top when we create our pipe and what I want is random pipe position let me start in its own variable and what I want to do is to pick a random item from a list which happens for random dot choice and here we have to place our pipe how do I call it hi it is really hard to name variables for me okay so now what's happening is that we are picking a random number from this list and when we place our pipe we want to pick that number so instead of having 512 you want random pipe position so let's try this now and we should have different height for our pipes this one there's number one this seems to working yeah there we go now we have pipes with a different height so this is pretty good start already so now we can work on having a second pipe on top and how I'm going to approach this is that in this function I'm not going to create one pipe I'm going to create two pipes with one pipe being in this random position and one pipe being above that position so this rectangle here effectively becomes the bottom pipe and let me rename this just to be clear on the variables and now I want to create a top pipe and this pipe is going to work in quite a similar way compared to this other pipe with some key differences the first thing is that we don't replace the top instead of going to place the bottom of this rectangle so that we make sure it's moving upwards from that point not downwards and then I don't want it to be on the same Y position instead I want it to be a little bit higher so I just subtract that safe 300 from this so there's some space between the two and once this is done I want to return both the bottom pipe and the top pipe and this is going to need another change that now since we're returning to variables separated by a comma we are returning a tuple so we have to unpack this tuple or at least do something else with it we couldn't just append it to another list instead what we're going to do is use extend which is taking this list and extends it by whatever is returned by this which is a tuple with two elements and with that one this should still be working so let's try and is working and we can see two pipes and obviously the top pipe is facing the wrong direction but we can work on this in just a bit but we're ready doing quite well so we can see the basic outline of our game so let me close this and now let's work on reversing the top pipe and this is going to happen in our draw pipes function and let me minimize all the other functions so we have a bit more space so in here we have to add some extra logic to flip the pipe if it is in a certain position which we can do quite easily so what I want to do is type dot bottom is greater or equal than 1024 and if this is the case we know the pipe is on the bottom so basically what happens here is if the bottom of this pipe is outside of the bottom part of the screen so it is greater than this 1024 then we know it is on the bottom of the screen because the top pipe would never reach that position so if that is the case then we want to draw it in this way as we have done before but if that is not the case then we want to do something else and what we want to do is to create a new surface that is being flipped so I gonna call this flip pipe and pygame as a specific method to flip a surface which is pygame the transformed flip flip underneath the surface as before and then we need two more arguments both of which are boolean the first one is if we want to flip it in the x-direction which we do not so this one is false and the second one is going to be true because this one is flipping it in the y-direction so this one is what we actually want so now that we have a new surface we want to put this new surface on the screen so we want to use screen droplet and there's gonna be pipe surface and pipe and let me try this and know it is still not working or the simple reason that I passed in the wrong surface this has to be flip pipe not pipe surface let's write again here we go this looks much better so now we have proper pipes I don't know whether all the bottom okay just a bad roll so now they're more varied so it is working so let's work on collisions now and collisions are quite an easy thing to do once you have rectangles because right now on our screen we have a rectangle around the bird and with a rectangle around each of the pipes and all we have to do is to check if any of these rectangles are colliding with each other and the method we have to check for collisions between rectangles is called collide wrecked and this one ever returns true or false false if there is no collision true if there is a collision and this we can use to run some code if a collision happened so let's implement this and in our code I want to create a new function that I'm going to call check collision and again I want to pass in our pipe listing here and now again I want to go through all of the pipe and pipes so just as before we're looking at every single rectangle inside of this pipe list so we can work with every single rectangle inside of it and now we have to do something new of these pipes we want to check if any of them are colliding with our bird so what we want to do is purge wrecked Dodge collide wrecked pipe so what happens here is that we are taking your bird rectangle and we checking if this bird rectangle is colliding with any of the pipes in this pipes list and if that is the case this is going to return true so we can use it in an if statement and for now let's test if this works let's say collision and obviously right now it is not going to work because we're not calling the function which I am going to do let's do down here so now let's try this and let me hit the pipe and there we go we have collisions so we know when our bird hits a pipe and I also want to add something else in here and let me demonstrate why we need another if statement in here so I run the game again and I can just go outside off the screen and fly above all the pipes and could basically play the game forever although it just doesn't make sense to play like that so what we want to do is if the bird gets too high or too low then we also want to trigger a collision and for this we don't actually need collisions we just need to check if the top of the rectangle of the bird is too high up off the bottom of the rectangle is too far down and generally it is pretty good practice to use collisions as little as possible because calculating collisions is quite difficult and takes some processing time whereas if you just check for specific position this is much easier to do and especially in our case since we don't need to calculate collisions we shouldn't do it and this is something that makes our game more efficient in our check collision function I just want to check if bird rect top is smaller or equal let's go with minus 100 so that you can go a tiny bit outside of the screen but not too much and if you get this far up you're probably gonna hit a pipe anyway and we want our statement if third-ranked does bottom is greater or equal and here we do have to be a bit more precise because we are putting our floor at a specific position and what I want to do is whenever we hit the floor the game is over and we put the floor at position 900 so this one has to be 900 and if that's the case that's for now just print oh so collision and let me try this so I just fall down and we have collision here and the same should be if we leave the screen at the top so this one is working and now we have some collisions and there's another thing I do want to talk about that I have used smaller than and greater than not equal to and this is really important that in videogames you very rarely get exact pixel measurements and it is really unlikely that for example the bottom of our bird rectangle is exactly on position 900 instead it is much more likely going to be at slightly below or above that point so it might be at 895 and on an extra med 902 so it doesn't exactly hit it so if we were checking for strict equality this would not be triggering our bird would be falling down because the two points are not exactly the same but inside if we use greater than then is going to trigger every time and this is a general principle in video games that pixel measurements are never that precise and you always want to have some wiggle room when you move something on the screen or when you check for collisions and this is why I use greater than and smaller than not equal to and I actually did the same when I moved our floor so here flow x position is smaller than minus equal 576 but in our case since we always move by one pixel this should be okay with equal sign but this one is safer to work with but all right and now we actually have to do something with these collisions and basically what I want to do is to turn the game on and off so I'm going to create a new variable and I am going to call game active and if this one is true our game is running if this one is false our game is not going to run and then our Czech collision function triggers this and turns it on or off and this would already be the starting point for our game over screen so let's implement this one so here I'm back in my code and the first thing I want to do is to create a new variable that I'm going to call game active and by default this one is going to be true and now in our game loop let me minimize this well we don't the event loop we want to run all of this only if game active is true the floor is always going to be there same as the background those two can always be on the screen but these two the bird and the pipes should only be on the screen when the game is active and this is a simple if statement so if game active is true then we want to run all of this and else we want to do something later that's gonna come in a bit so overrun the game now there should not be any change so this still works the same way we see that collisions but now if we put game active two faults we're not going to see anything we can just see our background and our floor so this one is working for now now in a way for this check collision to influence this game active variable and this I'm going to do with return that if I have a dis or this happens then we're going to return faults and store dis faults in this game active variable and if neither of these trigger then we're going to return true so what we want to do in our game loop when we check for collisions here I want to get the return value and store it in our game active variable so in here is sure to return defaults and this should also return false but if neither of these trigger then I'm going to return true so essentially what's happening when this function is running Python first looks at this line here and if this one is true is going to return false and enter function if this is not happening and it is coming to this line and the checks if the bird is really high up or really far down and if I've of this is true and it's also going to return false and if I've of these are returning false then we are storing all in our game active variable and if this one is false the game loop or this part of the game loop is not going to run anymore so we are effectively stopping the game however if neither of these are true then we are returning true and the game continues so let's try this and we can still see our pipes and this one worked and now we're disappearing so this one is working but we can't restart the game which is kind of annoying so let's work on that for now and to work on that we will need to go into our event loop let me open it again and add some more code in here and I'm going to do this right below where we check for key down and here we want to check for another key press and I still want to use the space key so this is before I let me actually copy this entire line I still want to check for the same button however this time I only want this to be true if the game is over as well though I need to add another statement that if and game active is equal to false and then I want to execute some code so this entire if statement is only going to run if I press the space button and if the game is over and we can actually change is key space here and game active just to be sure so this space button press is only going to trigger if our game is active and this one is only going to work if the game is over and how in here if this is true we want to set game active to true again however let me demonstrate why this by itself doesn't work just yet so the game for now it is going to work but it's going to be buggy so you can see that you can kind of see what's happening that it should be working in a second again there we go and you can see lots of pipes so basically what is happening here when the game is over our bird and the pipes are still in the same position so when we start the game over again or a bird immediately is colliding with a pipe so the game stops again and we're having a bug and only if you press space multiple times then eventually the bird moves the tiny bit forward every time and gets forward over because the bird is moving so slowly now we are creating more and more pipes on the right so once the web is moving normal again we have a ton of pipes so it's a start but it's not working greatly yet but we can fix all of this super easily because all we have to do is put the bird back in its normal position and de-spawn all the pipes which just means we empty the entire pipe list and this we can do really easily all we need is pipe list not clear and we are going to need our bird rectangle dot Center is going to be wherever it was when we created it is positioned here so now when the game is over and we are restarting it then we are emptying the entire list and we are also going to put the bird in its original position so let's try all of this now and this was this before and now if i press space again i let me show this so now we can't see anything if i press space again this is working again and we are restarting the game but we did get an arrow there towards the end and basically what happened here is that we never cleared bird movement so when the bird is restarting and we are still applying the bird movement which can be quite a high positive number so all we need to do is when we are restarting the game we also want bird movement to be zero and now this should be working let's try now and let's wait a couple of seconds and now it looks like again now bird movement is still going to be zero and we have a basic outline for the game that is just as infuriating as the original and I have no idea what people really like this game alright this is working and now we actually have a basic outline of the game now we just need to add lots of different details to make it look prettier and I'm going to start with our bird and what I want to add is a rotation and a bird flap and let's start with the easier one the rotation and I actually made an entire video about rotations of Pi game by itself but there can be a tiny bit tricky a really important thing you do have to be aware of that when you rotate something in pygame it loses a tiny bit of quality which is fine if you rotate something just once and the way around it is that you have two different surfaces one that is the original that is not rotated at all and then another surface that is rotated and every single rotation always starts from your original point so you effectively only rotate something once and you don't really have any kind of loss in quality but check out the other video it explains rotations in much more detail but all I want to do for my game is to create a new rotated bird surface and then put this on the screen so all I want in our Earth's section of the code and let me do it after gravity then I want a new surface that I call rotated bird and this one is going to be returned from rotate bird and I pass in the original bird surface in here so we have to create a new function at X our original bird surface rotates it and returns a new rotated bird that then is going to be put on the screen so we don't put bird surface we want to put rotate it bird on the screen and that's going to be here and never function that I called rotate bird and the tags Evert and in here I create a new surface that are gonna stall in new bird and to rotate something in pygame the function is called row to zoom which we access with pygame dot transform toward row to zoom and row to some can do two things it can scale and rotate a surface but in our case we don't want to scale functionality so we only use the rotation part but the first one as always is a surface which in my case is bird and then I want the angle by how much I want to rotate it and in my case I'm going to use bird movement because this one starts at zero and if we go down it increases if we go up a decrease it which we can use for the rotation it's quite simple so I just want to pass in bird movement in here and I think the scale is the third argument and this is just going to be one and once that's done I don't return the new bird and you could simplify this entire thing quite a bit you could even use a lambda function to do all of this but I think in my case this is the most obvious way of doing all of this and this one should actually be working let's try so there's one thing that is a bit weird we have a black thing around our bird but you can see a rotation except it's very small so let's increase it so bird movement let's say we go times three and let's try it again so now the bird is rotating but it's rotating in the wrong direction so all we need to do is that a minus here and this one should look a bit better already and here we go this looks much better and this this yeah this is a proper rotation but we do have a black square around a bird which isn't great and the reason we have the black square around our bird is that when we are creating this new surface it doesn't have any other values which basically means that if Python sees something that is not supposed to be drawn on it just draws it as black but we don't want it to be drawn at all and to do that we are going to need when we create our bird to convert it to convert alpha and now this surface to be working there we go so we just have to give it an alpha value and it's working and that's a pretty good progress so yeah I'm really not good at this game but never mind doesn't matter so now I have a rotation that is actually working quite well we can close this one and never look at it again next up we want an animation of the bird flap and this one is going to get a tiny bit more complex and let me explain how animations work and pygame basically what we have to do is import multiple images and put all of these images into a list and then in our game we just want to cycle through these images consecutively so we use image one image to limit free and then go back to image one and each of them is at a different stage of a bird flap so effectively what we want to do is import multiple surfaces put them into a list and then cycle through this list at a certain speed which we can implement actually quite easily so I'm back in my coat and for now let me just comment out all of this because we are going to change it quite a bit and there's going to be some typing and I already prepared all of this before so let me paste it in and here we have four lights we have bird down flap bergman flap and bird up flat and each of them loads an image and converts it with alpha so kind of what we've seen before in this line here but then immediately it scales up the image by two for each of them so what we have done in this line here and once that is done it puts all the three surfaces into a list so there's nothing complex happening in these four lines we just import free surfaces scale them up and put them into a list and I also want to create a new variable that I'm going to call the bird index and this one starts at zero and I'm going to use this variable later to pick a specific surface from this list and since we need a bird right from the start I actually have to do this already so I'm going to create a third surface just to keep the same name it's going to get purged reims and bird index so we just take this list and we'll pick a certain item from this list depending on what this number is going to be and then I also want the rectangle around this which I'm going to call bird rect is same at the form so we can keep the other names and this is just going to be birch surface don't get rekt and I can literally just copy what I had in here and pass it in here so all of this should result in the exact same thing we have before let's try it so we can see any change except that now our wings look slightly different because now we're using down flip we don't use Smith flip anymore and if I change this to two we'll be using the up flip so now all wings are upwards so all we really have to do now is cycle through this list at a certain speed and to do that I'm going to use the same approach like I have done before with spawn pipe I'm going to create a new user event that I'm going to trigger every couple of milliseconds and every time this is triggered it's going to increase bird index by one so I'm going to call this bird flap and this is going to be PI game user event and this has to be plus one so we don't create the same kind of user event we want a different one and if you want to create another one this would have to be plus two and so on and just as before I want PI games or time dot set timer bird flap and let's go with 200 milliseconds that seems okay so we are going to change the index here every 200 milliseconds and I think it should be fast enough so now we have to go back into our event loop and let me minimize this other stuff and I want if event dot type is equal to red flap and if that is the case I want to increase bird index plus equal one however this is going to get us into an error message really fast because this number is going to get quite large really fast but our list only has it only goes until - so we have 0 1 & 2 so if it gets greater than 2 then python is going to throw us an error so we have to make sure that this list never gets greater than two which fortunately we can do really easily with an if statement that if bird index is greater than 2 then we want to run this one and else bird index is going to be 0 and basically what happens here is that the start bird index is going to be 0 so this one triggers and the actual bird index is going to be 1 then on the next frame but index is going to be 1 and when we add put index plus 1 we got bird index is equal to 2 and then on the next frame since birth index now is going to be 2 this one is not going to be triggering anymore instead we get this line here where bird index is going to be 0 and then the entire thing starts again so this loop always goes 1 to 0 1 to 0 and so on and I could be running this now but it would not be working because we have to apply this bird index actually to this list when we come into our game loop and we could be doing this in here as well and what I want to do is purge surface and bird rect is going to get values from what I call bird animation and all that this function does is that it takes an item from this list and it puts a new rectangle around it and putting a new rectangle around it is kind of important because these might have different dimensions I actually didn't check but the rectangle has to have the same dimensions as the surface its surrounding otherwise my game would frozen arrow so we have to do both but this kind of function is actually quite easy let me create it down here the third animation I hope that was the same name yeah there we go so the first one what you do in here is to create a new surface that gets from third frames and we pick from bird index so this one actually updates our bird and then I also need a new bird rekt and this one is just as before new bird but get rekt and the center is going to get slightly more complex so the expert of this is quite easy it is always going to be 100 so the center of our bird is always going to be 100 pixels from the left however the y part can change quite a bit because this one has to be aware our previous bird was and this one we can actually get we need bird rekt dot Santa why so what effectively happens here is when we are creating this new rectangle we take the center Y of the previous bird rectangle so that we don't change the position of the bird when we are updating our bird but that is all we need now we can just return both so it's new bird and new bird rect and now let's try this so now we can see a bird with flapping wings and everything else still works fine and yeah there we go it's really starting to come together I'm still terrible at this game dog all right and with that one done we've actually finished all the really difficult parts now we just need to add score in the game over screen and we are pretty much done so let's start with the score and I want two kinds of scores the score for our current game and a high score and then whenever the current score is greater than our high school we want to update the high score and the first mean I'm going to need for that these two new variables that I call score which starts at 0 and high score which is also starting at 0 but we have to put both of these on our screen and for that we have to understand how PI game handles text and it's not too complicated but there are couple of steps towards that so let's go through them one by one the first thing you need for text and PI game is to create a new font and this font has a style and a size so what the font looks like and how large the fund is and all of this goes into the first big step the second step then is to use this font render it and what that means is that you are actually writing something with that text and then this step he also beefer text the color and whenever you write text and pygame you're putting this on a new surface so once you have read the text you have a new surface with some text on it and from here you can put a rectangle around the surface and put it somewhere on the screen just like we have done before and let's follow through on these steps and create our score and the first thing we need is to create a font and I'm going to do this right at the top and our code below in it and I'm going to call this game font and you create a font we PI game or font dot font and make sure this one has the uppercase F and now we need two pieces of information we need the size of the text and the font we want to use the text size is the easier part let us go with 40 which is a fairly large font size now we need to fund style and font styles are stored in a very specific kind of format is called TTF and flappy bird has the father's code 0 for B underscore 19 I have no idea who gave the name but he can't find the font in the game folder and it has to be in the same game folder but I what I want to do is import that font dot TTFN so now we have a font with this style and this size now we need to use that phone to write some text on the screen so I'm going to create a function that I'm going to call score display and for now this one is only going to show the score for our main game we don't worry about the high score just yet and and here we first have to run our text which is going to be stored on a new surface so we first need a variable that I'm going to call score surface and we need game font go to render and in here we need three pieces of information the first one is the actual text we want to render and for now let us go with test I just go to score then will you tell PI game if this text is going to be anti aliased or not and anti aliased text just looks a bit sharper so I'm going to go with true but this could also be Falls it doesn't make too much of an impact and now you to cut off our screen and Amycus gonna move 255 255 and 255 so what does that mean well this is an RGB tuple and RGB stands for red green and blue so this is the amount of red we have this is the amount of green we have and this is the amount of blue we have and for each of them we can choose between 0 and 255 and then pygame is going to mix these free colors together and give us an output color and if you max out all the three different colors you're going to get white if you go with zero for all three colors you're gonna get black and if you only want with something like 255 0 and 0 then you get red because you only have the red color you have nothing of the two other colors that's basically RGB with just three different colors and you mix their intensity together so now we have a new score surface next step is to put this surface on the screen and to do that I'm going to put a rectangle around it just to make it easier to put it in the middle of the screen so I'm going to call this score rect and this is going to be score surface get rekt and let me fix the typo and Center is going to be 288 so half of our X space and then I'm going to put this roughly at the top of the screen which is going to be 100 so 100 pixels from the top of the screen and now I just need to screen to applet score school or surface and score rect and this is all we need to put some text on the screen so now we have to called score display and let's put it at the end of our game active screen so I called it score display and this should be working so now we have score at the top of the screen doesn't do anything yet but that's going to come in a second let's work on it now actually so right now we are only drawing score and I don't want that instead I want to print where score this one here so I won't score in here but this one pagan would not like because this render needs a string and this one is an integer so we have to change this to a string very easily done and if a run is now we can see zero because we're not updating the score but that we can do right now so in our game loop yeah I am drawing our score and I just want to update the score plus equal one and this is going to get a bit crazy let me show so now our score increases way too fast which isn't good and instead I just want to increase it by 0.01 but if I run the code now we're getting a float which is gonna have a very silly outcome let me show and this is what floats are a bit weird they produce really long numbers so we have to convert this new number into an integer first and then into a string which fortunately we can do very easily and I have my score up here so this call right now is going to be a float and I want this to be an integer and this is gonna fix the entire thing and now we have one two three and so on so this one is working quite nicely so now I have a score but I also want to display a high school but I only want to display this high score if we on the game over screen so I have to change this function a tiny bit to accommodate for that what I'm going to do is I'm going to give this a parameter that is going to get a string later on and this string could either be game or game over and if it's game over it's going to display a high score if it's game it is only go and display the score so if game state is equal to let's call it main game and we are doing this and let's do another if game state is equal to game over then we are still going to draw our current score but we are also going to draw a high score and for that I can just copy the entire thing because we're still just working with text and just add high score in front of everything so this is gonna be ice corrected ice correct I score and high score surface and high score rekt and yeah this looks good and then in our game loop that it's going to be down here and when we call score display this one's gonna get game called it main game I think main game yeah this one main game there we go so now we are showing a score in our main game but I also want an else statement that if our game is over I still want to display the score so now we have score display and this is going to be game over so now if our main game is active we are only going to show our current score however if that is not the case so if the game is over then we're going to run this function in a slightly different way and before running this there's one thing I just realized that I forgot and let me go all the way up again to our score display function and right now we put in this line here we put our score surface and our high score surface on the same position which wouldn't be good so I have to change the Y position for the high score and by trial and error I found eight hundred and fifty works best so let's try now and let's see how this looks this one works fine if I run against something we have to at the top this is our score and we have zero at the bottom which is our high score or it's going to be our high score in just a bit and I think in our game over screen we don't just want to display the number we want to put text next to it which we can do with f strings so let me get rid of this part here and create an F string and what I want in here is score and then curly brackets and pass in our score in there and then I can copy the entire thing and change this one to a score and this one should also be high score and if strengths basically combined enormous string with any other kind of variable that we can pass into curly brackets quite useful so let me try this again and this one seems working if I die now we have scored the top and the high school at the bottom but our high score doesn't update so let's work on that and this I'm going to put into a new function that I call define update score and updates court doesn't need to do anything complicated all need to check is if our score it is greater than our high score and if that is the case then our high score is going to be our score so if the score is ever greater in high score than the high school is going to get the value of the score and since this high score right now is in the local scope of this function we have to return it so return high score and I actually have to pass in score and high score as parameters to make this work properly and now this should be working so let's go to our game loop down here in the eltz and before we are calling the score display we want to update our high score so high score is going to get update score and we want to pass in score and high score so let's try this now and if I crash to get something now we have our scores - I know high score is two as well it's not let me try to go higher I all right we don't reset the score so now if I play again scores gonna be four and high scores Oscar before there's one bug right now that if I start again we don't reset the score so it's always increasing which doesn't help too much so let's work on that actually and that is super easy to fix because just as before when we are calling I think it was in here yeah so if we call key space and game activist Falls so restarting the game then we also want score to be 0 because otherwise disco is always increasing so now let's try this again so we go 0 1 and we die now we have to now it starts at 0 again and let me try not to die and now we have score free and high school also updates because our new score was higher than the previous high score and if I try this again and we get to 5 now we have 5 as the high score so the high schools working we are making a ton of progress now for the final part all we have left to do and that is going to be to make the game over screen look a bit better and to add some sound-effects to it and then we are done with the entire game so let's start by making the game over scream look a bit prettier and I'm going to make this quite easy all we really need to do is to take an image and put it in the middle of the game over screen and you're going to see in a second what that means specifically so here we are back in our code and all the way at the bottom of all of our game variables I'm going to create a new variable that is going to go game over surface and for this one it's just an image by game dot image load and this one is also in the assets folder and is called message dot PNG and as always I want to convert it and I also want to scale it up and by now I guess we can just put all of this into one line to save us some writing space and now we just want to put this in the middle of the screen and do that we need a rectangle so let's call it game over rekt his game over surface get rekt and the center is going to be 288 and 512 so the exact center of our screen and now when the game is over we want to display that which I'm going to do in the out statement and just going to be screened out blech game over surface and game over wrecked and let's see if this is working and let me just destroy myself and now we can see that we should have used the alpha value because right now anything that's supposed to be empty is going to be black so let's try this again with convert alpha let me die again now this looks much better so now we see a message and we press space again this one is working again and we can also get our high score and here we go this all works much better now so making good progress now the last thing is to add some sound-effects to this and that actually brings us to a new topic and PI game and that is to importing sounds and for that we are going to need the mixer and the mixer can be a bit of a tricky thing to work with but let's go through it step by step I think this is going to work best in code the first thing I want to do is to import a sound that when we press our space button or a bird is making a flap so I'm going to call the new variable lab sound and to import a sound file we need my game don't mixer mixer notes sound and now we need to file location which in my case is sound / SFX underscore winged dot wav so this is a sound file and we want to play this sound file whenever we are jumping or flapping our wing and this is let me open it this case here so all we have to do is flap sound not play and this should be working let's actually try this so I execute the code and we can hear sound but you probably noticed that this sound is massively delayed and that is for reason and the reason is that pygame tries to account for all the computers that are really slow so it first buffers the sound and then place it once it's ready to play the sound in high quality but this takes quite a bit and as a consequence the sound only plays a few milliseconds after we have done the action which is really confusing so let's fix that one and to fix this one we have to pre init our mixer so remember about a billion years ago we initiated pygame well this one also initiated mixer and we can customize this initiation for mixer and what we need is high game thought mixer dot Cree in it and what Priya does is it tells this initiation method to initiate mixer in a certain way and now we have to give it some arguments to initiate it in a specific way and here we have a couple of arguments we need the first one is the frequency and by default this one is 44100 and we're gonna leave it at that and the second one is the size of the file and this one is 16 also by default then we have channels and by default this one is 2 but I only want this to be 1 and then we have a buffer that is really important for quality and I'm going to put this as 256 and this is all we need and I think it's gonna be a bit of an overkill to explain all of these in detail and pygame explains this on the website and quite a bit more detail check this one out if you really care but if I run the code now this should be working much better and maybe you can hear it but it sound quality went quite terrible and this is because this buffer size got too small let's switch it back to 512 and this works much better so now to some place immediately and it sounds kind of alright so wait for a basic sound so now we need two more sounds the first sound when we hit a pipe it's like an sound this when the score updates and to do that we first need to import a couple more sounds the first one I called def sound I just want a spy game to the mixer sound and we sound and and SFX underscore hit dot wav and then finally I have score sound and that it spy game dot mixer got sound it is also nice sound folder and this one is called sfx underscore point wav so this is the sound when we get the pipe this is the sound when we update this score let's start with the def sound so if you hit a pipe and this one we just have to get to our check collision function and if this one is true then we want to play the sound so quite an easy thing to do so def sound the play and if I try this we're getting an error message that score sound is not defined because I made a typo right now and we can hear a sound from your pipe and we still go to our game over screen all of this is working so for the final thing we want to play a sound when our score updates we're just going to get slightly more complicated and let me minimize the event loop so what we want is if this score gets to a full number then we want to play a sound but this is kind of difficult to measure so instead what I have done I have created a new variable that I called score sound count on and this one starts at a hundred and then in our game loop I reuse this one by one score sound count on I'm going to reduce this by one on every cycle of the loop and if it is 0 so if scores sound count on is equal to zero or said before smaller equal than zero just to be sure then we want to play this sound so score sound play and then we want to set score sound count on back to a hundred so effectively this one is 100 of 1 and this one is 100 and we are changing them at the same speed so this one is 100 cycles to get to 1 and this one is 100 cycles to get to 0 so they're basically trigger at the same time and that's all we need let's try this now and we hear sound when we get a score and yeah that is actually working and with that I think we have our entire game I hope you enjoyed this tutorial and I'll see you around
Info
Channel: Clear Code
Views: 239,955
Rating: 4.9641623 out of 5
Keywords:
Id: UZg49z76cLw
Channel Id: undefined
Length: 100min 51sec (6051 seconds)
Published: Thu Jun 25 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.