Pygame Tutorial - Creating Space Invaders

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everybody and welcome back to their PI game tutorial now it's been a long time since I've done one of these but you guys know that the foundation of tech whatin my youtube channel was really built around making all kinds of fun little PI games like I've made Tetris snake some platformer games stuff like that which you guys can check out as well if you wanted to see those and I wanted to bring another one back here to all the old subscribers and just show you guys you know this is another cool PI game we can make especially with quarantine happening PI game is just such a great module for making some fun 2d games that don't take you that long to kind of get up and spinning and of course you know we can use Python for this which is a great and pretty fast language to write code in so the game that we're gonna be creating today is a space shooter game now this is inspired or kind of based off of that old original Atari game where you have those spaceships coming down the screen and you're this big shooter and you're trying to shoot them all of the sky I know that that version is a lot different than what I'm gonna show you here but this is the inspiration now stick with me here for another minute or two I need to give you this introduction so you really have all the tools you need to work through this project the first thing I'm gonna say is these videos take me a really long time to make and I really want to make sure that you guys are able to actually create the game so please do me a favor go like the video and make sure you're subscribed to the channel if you're not just show your support if you guys really want to give me an extra big thank you and show your appreciation I'd really appreciate it if you go subscribe to my new youtube channel which is called time out with Tim that's where I'm gonna be posting a weekly podcast where I talk about tech programming finance just myself lifestyle stuff like that and I would really appreciate it even if you guys don't want to watch that you just go over and subscribe and support me over there so anyways let's demo the game and as I demo the game I'll talk about some other important things for this tutorial series so first of all all the assets you see here those little pixelated assets are available from the description down below I've made a really easy link on my website so all you have to do is just click it and it will automatically just download a zip folder that has all the game assets and the code as well I get comments all the time with common problems which I'm gonna go over at the beginning of this video to hopefully make sure you guys don't run into those but if you're running into problems just click that link the code will download you can open up that code and you can steal whatever code you need and reference it and make sure that you know it really was my mistake maybe uh-huh and not yours and that you can see if anything's going wrong but this code that I'm showing here is what we're gonna be recreating I already have it written full disclaimer on the left hand side of my screen so if you see me looking over there during this long tutorial that's what I'm doing just making sure I haven't messed anything up so the idea behind this game is that you're this ship you know you can shoot bullets and you want to just make sure that these little ships here don't get to the end of the screen and if they do you lose a life the idea behind what I've created here is this is kind of a basic guideline it's setting up the main functionality and then what you guys can do is add your own features to it and I'll talk about some extensions you can put on so you guys can make this game as custom as you want so the idea is to give you the core functionality show you how to do everything and then you guys can add and make it your own game afterwards so with that being said I think that has pretty much been it for this introduction what we're gonna do now is actually get into coding and just do a little setup for the project and then obviously start writing some code alright so the first thing we need to do for this project is actually install the module called PI game now PI game is this third party module once what we're gonna use to make this space shooter game and you do need to install it now a lot of people have difficulties with this this is probably the most difficult part of the tutorial for someone who doesn't work in Python very often doesn't understand how all this works so what you need to do if you're having troubles with the steps I'm about to show you here is click the card in the top right hand corner or click the link in the description that says how to install PI game that's an older video but it goes through exactly how to install PI game all of the common issues and problems and you should after watching that be able to come back here and follow along with no problem so what we're gonna do and just first of all obviously we need Python downloaded and installed I'm using Python version 3.7 and the text editor that I'm gonna be using is sublime text now you can use whatever you want you can use the standard Python IDE you can see I have that installed on my computer as well doesn't matter what you write in but just because I get asked all the time I'm using sublime text now obviously download Python if you don't have that 3.8 should work if you're having issues at 3.8 download 3.7 and then what we need to to do is use pip 2 and stall Piegan no pip stands for package installer Python believer Python yeah I think that's what it is anyways that comes by default with your Python installation so usually what you can do is open up a command prompt window if you're on terminal or open up a terminal window if you are on Mac or Linux and type pip install PI game like that now if you hit enter and you see something like this like requirement already satisfied or a finding module installing module you're good you install PI game you're ready to go that's all you need to do if you see an error that says PIP is not a recognized command go watch that video it'll show you how to install pip properly now if you're on Linux and if you're on Mac what you might introduce type of pip 3 pip 3 stands for pip Python version 3 because on those distributions or on those I guess operating systems they have Python 2 built in automatically so when you type pip that actually accesses the Python 2 interpreter not the Python 3 interpreter so try pip 3 try pip if this doesn't work again watch that video I have one for Mac and for Windows which I'll link in the description and once you get that what we're gonna do is just type Python in here or open up your ID le wherever you usually do your Python stuff just try to import the module of Pi game like that and if it works and you get this welcome message then you're ready to go and we're gonna get into the video right now so once we've done that what we're gonna do is actually a nun close this now set up a project directory or a folder on our computer where we're gonna store all of this stuff for this project so what I've done is I've made a folder I've called its space shooter tutorial and you can see I've already dragged in the image assets here so what you need to do if you don't have these assets which you won't use go to the description hit the link that says download image assets it will download a zip folder so you'll see I'll put this into a compressed one so that everyone can follow along here if we go what does it send to compressed zipped folder it'll be in a zip folder like this what you need to do is unzip it take this folder out so extract it and put it into the directory that we're gonna work in it's very important that when we do this the Python file we create is in the same directory as the folder that has the assets the assets are the images you can see I have things like this yellow ship which I'll bring up onto my other screen here we have the green ship the red ship and all of that ok so just make sure that you do that otherwise that's not gonna work ok so once we do that what we're gonna do is open up a Python window where we can write code so in this case I have sublime text but if you want you can open up ideally like that an ID le is perfectly fine to write code in as well but this is sublime text which is just a nicer editor so what I'm gonna do in here is make a new file and I'm gonna call this main dot pi now very very very important do not name this file PI game if you name this Python file PI game or any file in this directory is named PI game you your script will not work I learned this the hard way when I forgot to tell people that in the previous tutorial and I got a hundred comments do not name it PI game I know it's a tempting name just do not do that now again what we're gonna do to make sure everything's working here is just import PI game now fortunately for me in subline text I can click ctrl + the B key to run my script so that's what I'm doing here but for you guys if you need to run your script in your in IDL you obviously hit f5 or you can use the terminal window on back Linux whatever and do Python 3 or python the name your file when you're in the correct directory ok so once we import PI game what we're gonna do is import a few other things we're gonna import OS we're gonna import time and we're gonna import random so now we're actually ready to start writing some code so let's get into it all right so the first thing we need to do is actually load all of our image assets into our script so that we can use them and display them on the screen because the first thing I'm gonna do after we load these images in is actually start setting up the PI game window and talking a bit about some basic PI game syntax and how all those things work because obviously this is a module which means now we have some different syntax and some different tools we can use that aren't native to the Python language so notice again that this main dot Pi file is in the same folder where this assets folder is I don't have all these images inside directly with the main dot I the main dot pi is in the same level as assets that's really important and that's a big mistake if you don't have that so make sure you're listening pay attention and do that the first thing we're gonna do is load all these images so I'm gonna make a comment you don't have to do the comments if you don't want but this is just to make a little bit cleaner we're gonna load the images what I'm gonna do is use all capitals for my variable names gonna miss a red spaceship equals in this case PI game and not in all capitals hi game dot image dot load and I'll go through this after so don't worry if you're confused os path join and we're gonna do assets in here and then in here what we're gonna do is what was this file called I need to look at my other screen pixel underscores ship underscore red underscore small dot PNG okay so what this is doing this line of code and we're gonna do a bunch of these lines of code which I'll speed through in a second is we're saying from the PI game module use the image dot load method and then in here we're gonna load the image which is located at OS path join this is the name of the folder that our images are in notice that's assets right here on the left hand side of my screen and the name of the file is pixel ship read small PNG so if you look inside of here we can see we have pixel ship read small about PNG this is what it looks like a very basic you know five pixel thing and you can see that that's how we load this if we want to add a folder name to a file name cuz we're loading from a folder we can use OS path giant although note I could completely omit this line and some of you might be like well why aren't you doing this this is just the proper way to do it is to do assets slash and then the name of the file like that that works but we're gonna use OS path ajayan to make sure everything's clean so I'm gonna copy this a few times because we're gonna need to load all these files in rain they're gonna have to have all their file names so we have red spaceship we need green we need blue and we need yellow right so the yellow is gonna be our main player so I'll tab it down and say Claire ship like that just so we know and all we need to do for these ones up here is change red to the appropriate color so in this case that's gonna be green that's gonna be blue and I believe this one is just pixel ship yellow it doesn't have that small afterwards so pixel ship we can check that just by looking here yep there we go we got it and just make sure that you have that PNG extension otherwise obviously that's not gonna work so what we're gonna do now is we're going to install or not install sir a load in the bullets and the other asset so we need to load in the background and we need to load in at the bullet so let's say lasers is what I'm gonna call them and we'll say red underscore laser equals this case we'll copy this line up here paste it in and assets in this case I believe it's something like laser underscore red or something so let's look at this pixel laser ret yes okay so pixel underscore laser underscore red PNG let's copy this a few times and of course just change the colors to what they need to be so red green blue and yellow let's make sure that's all capitals let's change the file names now so pixel laser green pixel laser blue and pixel laser yellow okay so let's spell that correctly and now let's load in the background image let's say VG or background I'm just gonna call this one BG notice I spelt that comments wrong and BG is gonna be equal to in this case hi game image download OS poundage Orion assets and then what is this called background - black PNG so let's punch that in background - black PNG okay so now assuming we spelt all this correctly we have loaded in all these images to make sure this works we can run the code we don't get any errors this was successful now I'm if any of you have like corrupted images or something like that just try redownload encompasses it can't open the file even though it does exist but make sure again that they're in the correct folder their name the right thing and you're loading them in like this if you want to use your own image assets put them inside the assets folder and then you know name them what you need to name them and load them in like this okay so now that we have all of these loaded in what we're actually gonna do is set up our PI game window so the first thing we do when we're working in PI game is we create a width and height for our screen we set a name for the display and we just run it and make sure that it's working fine so the standard and the reason I've named these all cow by the way is because these are gonna be constants they're not changing and the convention in Python is to named constants with a capital what we're gonna do to make our window is we're going to say win equals PI game dot display dot set underscore mode and inside here we're gonna put a couple with a width and a height now we're gonna define the width height up here like this so width height equals in this case we're gonna do 750 by 750 you feel free to change this if you want and that's how we're gonna get started so width height equals 750 750 this just means with the 750 high to 750 we're gonna say win which stands for the window is equal to PI game dot display don't set underscore mode width height and width height just tells it this is how big our window is gonna be once we do that we're gonna set the caption or the name of our window so we can do that by saying tie game dot display dot set underscore caption and inside here we're just gonna call this space shooter and in my version I'm just gonna call it tutorial you guys can call it whatever you want so there we go space shooter tutorial now if we run the script we will see that a pie in window pops up and then just disappears because we're not doing anything else so if we've got that successfully things are looking good again feel free to change these numbers I'm on a 4k display so it's gonna look a lot smaller on my display than it is on yours if you're on 1080p right 750 by 750 will take on most of your screen if you're on a 1080p display but I'm on 4k so it's gonna be you know 1/4 the size is that how it works I think so maybe something like that alright quick water break there and now let's get into the next stuff that we need to do which is actually drawing and getting our main loop kind of set up so whenever we're working in PI game what we need to do is create a main loop which is gonna be kind of what handles all our events so it's gonna be what handles collision it's gonna be what calls things to be drawn on the screen it's gonna be what allows us to quit the game to move a character stuff like that so what I usually do is I define a function I'm gonna call this man which stands for main loop and inside here I'm gonna set up a few variables we're gonna need for the game so the first one we're gonna need is run run equals true is just gonna dictate whether this while loop is gonna run or not and then what I mean do is create an FPS which stands for frames per second and set that equal to 60 now of course you can change this to whatever you want the higher this number the faster your games gonna run the slower this number or the lower this number the slower game's gonna run now just keep in mind you don't want to make this number too low because if you do then that means that you're only gonna be checking for collision and checking for events once every whatever this number is so in this case we say 50 frames per second what that means is we're gonna show 50 frames ever sorry 60 frames every second and that means that we're gonna check collision we're gonna check if we're moving the character once or 60 times every second so the way that we can set that up in PI game is by making a clock object so we're gonna say clonk equals PI game dot time clock with a capital C like that and inside of here we're gonna say clock dot tick and make sure this is at the top of your while loop fps so we're essentially saying we're gonna tick this clock based on this frames per second rate so 60 FPS and what this allows us to do is make sure our game stays consistent on any device that we give it to so if we run this on a really fast computer or a really slow computer it doesn't matter it's gonna run at the same speed because we've set that clock speed of 60 FPS now what we typically do inside of here is start drawing stuff on the screen and start checking for events so what we need to do first is check for events and the first thing we actually want to do is check if the user has quit our window so to do that we're gonna say for event in high game dot event dot get and what this is essentially saying is every time we run this loop so once every or 60 times every second we're gonna loop through all the events that PI game knows and we're gonna check if an event has occurred if that event occurs do something right so an example of event is like pressing a key is pressing the quit button is pressing the mouse button something like that you can look up the events from the PI game website if you're trying to do something different but most of what I show you is pretty much all you'll need so now what I'm going to say is if event dot type equals equals PI game like this if I could spell correctly dot quit with all capitalist then we're gonna say is run equals false so what this means is pygame quit is if we press that top right the X in the top right hand corner of our screen quit the screen like quit PI games stop running so that's why you'll notice I said run equal to false so the next time we get to the top of this loop we won't loop anymore because we quit right and that's the idea behind that so we could check for other events in here in fact I'll show you another common type of event so if a vente type equals equals pi game talk key down what that means as we press some key downwards if we did that will trigger an event that's what this means now we're not gonna use that inside the event li because i'm gonna show us a different way to move things around but this is the basic loop that we need right now so let's actually go ahead and call this function and run it and just make sure that the quit button is working and show you what I mean so you can see that it pops up now our window we have space shooter tutorial and we can click the X button and if we do that it exits the window if you don't have this event here it will not exert the window when you press the quit button so that's just something to keep in mind you need to make sure that you make run equals false and eggs and out of our infinite loop that's gonna happen here that's running the entire game its handling collision movement all of that when that starts happening okay so now that we have that we should probably start drawing some things under the screen and the first thing that comes to mind for me is the background so I'm gonna do something that might seem a little bit confusing to you guys try to look past um you know really the inner workings of how this works and just understand that this is possible I'm gonna make a function inside of this main function that I'm gonna call redraw window now the idea behind this is that when we do things like in games and just in programming in general we typically want to separate things out into their own functions and create small pieces of logic that do things quite well they do one or two things like just one thing quite well so it rather than drawn all the different things because we're gonna have to draw a lot of different things within this while loop we're gonna put it in a function that's inside of a function and just call that when we need to use it so just treat this like a regular function but just understand that since it's indented and it's defined inside of this main function we can only call it when we're in this function and that's totally fine that's all we need to do but this is going to allow us to access all of these variables defined inside of the function rather than making it its own function and having to pass them all through as parameters which can get quite annoying when we have a lot of things that we want to pass so again yeah the idea is that this is gonna draw everything for us on the screen it's gonna handle all our drawing anything that needs to be rendered stuff like that so he can just be in its own separate piece so if something goes wrong with drawing we know right away where that is it's in redraw window so the first thing we need to do is do PI game display dot update and in fact what this does is refresh the display so the way PI game works is we have a bunch of things called surfaces now these surfaces can be drawn on we can blit things onto them which means like put an image onto them or something like that and the way that it works ideally is we have this one surface and every time that we loop so we run one of these while loops so 60 times a second we're gonna redraw everything onto the screen and then refresh it so that it has the updated version so the first thing we need to do since we're gonna be redrawing everything is draw a background image as our first thing so what that will do is it will cover any stuff that was behind or drawn before and then we draw everything on top of that background image that's gonna be shown for the next frame and you understand what I mean in a second but just bear with me here so what we're gonna do is do win job blitt BG comma zero zero now what this is saying is win is a surface right it's this PI game surface that we've set up as our main PI game window at the top of our screen so a method that's available on this is called blit now what blitt does is take one of these images so one of these PI game images it can be some other things as well which really have been turned into what's called a surface in PI game and draws it to the window at the location that we defined here now an interesting thing with PI game is the way that we actually use a coordinate system so I'm gonna bring up my drawing tablet here to show you what I mean cut some networking stuff on there and show you what I mean by the coordinate system so let's say this our PI game window and just excuse me cuz I am drawing with my mouse we know we have an x and y right so this is our x-axis this is our y-axis and typically we think that zero zero is the bottom left well that's actually wrong or different in Pi game in fact zero zero is the top left so what that means is that our x coordinates are the same as we would assume if we want to increase X we're going to the right or if we want to go to the right we increase X so X goes like that but Y actually goes down which means that if you set something at position y 0 it's at the very top of the screen and if you want it to go downwards you need to increment the Y so let's say I want to move a character down I need to increase its Y value that's what I'm getting at here now this is the same for objects so let's say we have a little square and we want to draw it on the screen well the top left hand corner is where we're gonna draw this object from so if I say I'm drawing a square at 25 25 what that means is that I'm gonna draw this square starting at the top left position of 25 25 so if the width of our square is say 30 if I can't draw a 3 this pen size is too thick let's see if we go let's do 20 that's my rough version of a 20 that's a 2 if the width is 20 and we draw it at 25 that means that this corner here right so this right corner is actually gonna be a quick math 45 right so that's what we need to understand top left hand corner is the coordinate system for pygame so just keep that in mind when I'm drawing things so when I say wind up lit background at 0 0 that means take that background image and draw it at 0 0 in the top left hand corner of our screen and since we're gonna draw the image starting at the top left hand corner it will fill the entire screen now the only thing is though we're gonna see when we run this well actually if if we wind up lit if we call this function one second sorry so let's call this function now from inside of here so redraw window so just inside this main loop we're gonna go clock tick immediately call the redraw window in here it just splits the background and updates the display so let's run this notice that the background is not the correct size so what we're gonna do is actually scale this background up you can see it's about 1/4 the size it really needs to be so we're gonna make it 2 times bigger just about said it fills the entire screen so to do that we're gonna go up to where we loaded it in on background and we're gonna use another method so we're gonna say pygame dot transform dot scale and what we're gonna do now is put this entire image so this whole line we had before as the first argument and then as the second argument we're gonna put what we want to scale this image to so the dimensions so in this case it's gonna be width height where width height is those variables we defined earlier for the width and height of the screen so if we run this now notice that it fills the entire screen because we scaled that image and then we're drawing the scaled image onto the screen now you can see we get some little pixelated stars and some fun stuff like that okay so I guess the next thing to do is to actually deal with drawing a few things else on the screen we'll get into characters and stuff in a second but like the score the level were on things like that so let's do that first we're gonna say score watch the eyes it's not score we're just gonna have level and lives so we'll say level starts on level 1 and we'll say lives starts on 5 feel free to increment that if you want doesn't really matter to me and I'll show you how we can draw those to the window so how can we actually draw text so you saw I had lives and I had level at the top right and left hand corner screen how do we do that well what the first thing we need to do is actually create a font in PI game so a font allows us to kind of render that font so for example Comic Sans is what I'm gonna use we need to create the font object and then use that font object to actually render the text to the screen so that the annoying thing in Pi game is that you need to initialize fonts for them to work so that's pretty easy but at the top of our program right after we import PI game here we're gonna say PI game fonts dot and yet this just tells PI game kick get setup get the font ready to go so that there's no issues when we want to start using it so that's what we'll do PI game dot font done it and now inside of our main here I'm gonna define main underscore font so that's a variable name is equal to in this game pi game font . sys font and here we're going to name the fonts there's all kinds i'm not going to go through them but the one that i usually use is comic sans and then the size of this font so the size i'm gonna use is fifty make it smaller bigger depending on what you want and now i'm gonna show you how we can use this to actually draw the lives and the level on the screen so here I'm gonna make a comment I'm gonna say draw you know text like that and the first thing we need to do is make a label and then blit that label to the screen so you saw how i blitt this surface which is the background to the screen what i need to do is turn some text into a surface and then put it on the screen so i'm gonna say do i guess this would be lives underscore and label is equal to main underscore font which we've defined up here which is comic sans size fifty dot render and here i'm gonna type what i want to render so in this case i want to render an f string if you're not familiar with f strings what this allows you to do is embed variables inside of brackets like this so left brace rice right brace at the curly brackets so i can do something like level : level and what this will do is take the value of the variable level here and just show that and so that's with an f preceding this string now that only works in Python 3.6 and above so just keep that in mind when you're running through this okay so then our next arguments are 1 and color so 1 stands for anti aliased you can see that's popping up here I'm not gonna explain really what that is you're just pretty much always gonna use one if you're bleeding something or rendering texturing and then color is an RGB color so RGB stands for red green blue it's a value between 0 and 255 inclusively that means you can use 0 and you can use the value 255 and if you wanted to make say red well it's red green blue so you say I'm gonna use the maximum amount of red the minimum amount of green and the minimum amount of blue that would give you red if you wanted RGB if you want to blue then you would do 0 0 255 if you want white funny enough it's 255 255 255 because white is actually a combination of all colors so that's why or combination all of red green blue that's what you do like that if you wanted black it'd be zero zero zero and you know you can look up RGB color codes and find them quite easily on the Internet so limes label will be that will say level oh I just realized I called this level it should be lives my bad so lives lives let's do level label so level label equals main underscore font dot render do an F string again not a D string and F string and we will do level colon and this time we'll do level and then we'll do one two fifty five two five two five so to summarize this has created text which is white anti-aliasing of one that has these contents and now we need to put on the screen so I put on the screen we're gonna say win double its first one what do you want the lives label okay lives underscored label and the position that we want to put it on we need to pick an XY I want it in the top left hand corner of my screen but not like directly in the top left-hand corner just a little bit offset so I'm gonna say ten ten so ten pixels down ten pixels right is where the top left-hand corner of the label will sit so it will sit just barely offset from the top of the screen and then we're gonna win da blitz be level label of course and here for our XY z-- can be a little bit different I want this on the right hand corner of the screen so I'm gonna take a guess that's actually you know what let's do the mathematical way cuz we're going through some in-depth explanations here anyways if I want this to be ten pixels from the right-hand corner of the screen what I need to do is determine the top left-hand corner of the label so where should I put that right let's say like I want the label to sit so that the edge of the label is only ten pixels from the far right hand right hand side of the screen so to do that I need to figure out the top left hand corner position well what I can do is find the width of this label I can find the width of the window and then I can take my padding whatever I want the padding to be and use some mathematical equation to figure out where that should be so thinking off the top of my head here it's gonna be width which is the width of the when to itself so whip - in this case it's gonna be level underscore label dot get underscore wit so we've got underscore width is a method you can use on surfaces that tells you the width of that surface so since I don't know the width of this level label because I don't know how big or how long this text is gonna be I need to call that method and then I'm gonna subtract another ten pixels because if I left it at this that would mean that it would be right on the edge so like the L or like whatever this level number is would be squished right on the edge so we'll subtract ten pixels to move it off and then we'll pick a y-value which is gonna be the same as what we used before as ten and blitt that to the screen so let's look at this now and notice we get lives five level one perfectly in the right position I mean say that you know we had we changed the width so actually let's do that let's change the width to be 800 so let's go like this if we change the width everything works fine and in fact I can change any numbers I want because we've done this in a dynamic fashion everything will stay consistent it will stay totally fine so we'll put him back to 750 750 but that's why I've been doing things maybe in a more tedious way rather than just hard coding because I want this to work for any width height that I choose so let's zoom out a tiny bit there let's move that over and now it's getting to some more stuff so we've displayed the lives displayed the level now we need to make a character and in fact we want to move a character around the screen so the first thing I'm gonna do is set up a ship class so I'm gonna say class ship this is gonna be what we call an abstract class which means we're not actually gonna use this class we're gonna inherit from it later because keep in mind we have enemy ships and we have player ships right those are the two parts of our game really right and they're interacting with each other so the enemy ship probably has some similar properties to the player ship so we can share that in one kind of upper level class and you'll understand how this works more but just follow along with me for now so we're gonna make in an it method we're gonna say okay so what are some properties of a ship that we want to store in this game well we need the x position and the y position the ship so where is the ship starting is it starting at the top is it on the left is it in the middle so let's go X Y like that what color is this ship that's something that's important right so what color and what about the health does this ship have a specific amount of health in fact I'll make this an optional parameter of a hundred which just says that our default ship has a health of a hundred right so the reason we need to put color here is because when we have an enemy ship we don't know what color it's really gonna be right so that's what we'll define with this color parameter when we create a new ship is it red is it green or is it blue it can't be yellow because yellow is gonna be the main ship the one that we're using to to shoot out the other ship right alright so actually what I'm gonna do is remove this color parameter for now just because since this is a general ship class for our player ship we already know what color that's gonna be it's only the enemy ship that will you know change its color on initialization so we'll define that later but let's let's just just ignore if that confused you at all the color aspect that I was talking about so we have self-taught x equals x and something like was y these are setting up attributes for the class so that each ship we create can store you know it's x value and it's y value right and i'm gonna try to go through basics of up here like give you a little bit of an explanation in case some of you aren't familiar with the syntax but just follow along and understand that what i've done is made of ship what this class allows me to do is make objects of it so i can have multiple ships that all have these attributes so they all have an X they all have a Y and they all have a health that's what the class is letting me do is later we'll create an instance of it which means that we can have multiple instances of a ship that all store their own health value their own X in their own Y and they all move on their own kind of terms right and that's the idea here we're gonna have multiple things so let's put it into objects in classes okay so we've done that I'm gonna say slash ship underscore image equals none talk about this in a second slash laser underscore image equals none and self-thought lasers equals blank and self dot cool down counter equals zero now the idea behind this is that when we start shooting lasers we want to make sure that we can't just spam the lasers so I'm going to define a cool-down counter here which essentially means we're going to count and we're going to wait like half a second before we let the user shoot another laser well get a lot more later but you know we're just starting to class these things out just so that we have that okay so we have that now defined ship and what we can actually do in here is define a few methods so the first one that I want to do is draw so actually let me go back here for a second just because I feel like some people might be confused on this so self that ship image and self thought laser image are what is actually going to allow us to draw the ship and draw the laser so we need to pick what image from the ones up here that we've loaded in are we gonna use for this specific ship since this is a general class and it's not gonna be instantiate I'll show you what I mean in a second we just define them as as none for now but when we actually set up our own ship later and start creating ships we'll define those images so that we'll be able to use them okay so we have draw so draw is gonna be important for now and what I actually want to do cuz I just want to show you guys how we can move around the ship before we get into anything too complicated is just draw a rectangle for now so I'm gonna say we're gonna take a window in the parameter so this is gonna tell us where do we draw this like where are we putting this we're gonna say window and that's no Noblet we're gonna say pygame dot Rex sorry PI ChemDraw dot rect what this says is PI game use the draw module dot draw rectangle we're gonna pick where so we're gonna draw that on the window we're gonna pick a color let's make this red for now so to 3500 for red we need to put a rect in here now this is a X Y width height which tells us how big is this rectangle and where is it on the screen so where's it gonna be well it's gonna be at self dot X self-thought Y because that's the position of this ship and how wide is it gonna be well for now since we're just testing things let's make it 50 by 50 now if we wanted the rectangle to not be filled in we could define a width so let's say we define a width of 2 that's gonna give us a hollow rectangle with two pixel size for the pen size around but if we want to be filled in we can leave it as nothing or put zero explicitly which tells us that that means this is a filled in rectangle okay so now that we have that I'm going to show you how we can use this ship and then we'll start getting into some more advanced things but I do I want to show moving around first so let's make a shift let's say ship equals ship and here we need to pick an x and a y value to start the ship at so I want to start it near the bottom of the screen so what I'm gonna do is pick like 300 by 650 and then what we'll do we don't need to define a health because that's an optional parameter right we've already had that to find is inside of my redraw window I want to draw this ship so what I'm gonna do is a ship dot draw window now the idea behind this is that this draw method draws the rectangle for us all it needs is a window so what we can do is just call that draw method if there's any more advanced stuff that needs to happen we don't need to deal with it here the ship can deal with that itself in its own draw method so let's just call it with the window now we'll see the ship so let's run this and we notice that I've made a mistake let's see what this make window is not defined my bad we need to put capital win in their window is the parameter name I'm messing it up so let's do win we run this we get this red red rectangle popping up at the bottom of the screen so if I want to much start moving this rectangle around now I need to modify its X&Y position based on what keys I press let's do that now so to do that we're gonna set up a way to track what keys are being pressed by the person now I could show you how to do it inside this event loop but the issue with that is it only registers one key press at a time so let's say I press like the side key and the top key at the same time it won't move both ways it will only move one of them whatever one you hit first I want it so I can move diagonally as well so I can move at the same time by just holding down keys so we'll be allowed to do that by pressing both keys at the same time with this method so what I'm gonna do them SI keys equals PI game key don't get underscore pressed what this does is return a dictionary of all of the keys and tells you whether they are pressed or not at the current time so since this runs once or 60 times every second I'm gonna mess that up every time I say it so just get used to it we'll check you 60 times every second if we're pressing a key if we are we'll move in a certain direction if we're not we so let's say if keys and here tie game dot k underscore so k underscore is just the prefix for what keys you can use so you do PI game and then there are keys since it's a dictionary we're gonna access the value and see if it's true pi game dot K underscore and then whatever key it is that you want so if you want a you type a lowercase a if you want to check if the left arrow key is being pressed you do left if you want enter it's actually gonna be returned if you want space it's all capital space you see I have this nice autocomplete that's telling me but ideally you can kind of guess with just lowercase letters and anything that's like a full word like enter or something or return is gonna be all capitals so if one move left we're in say if keys PI game can underscore a and then we'll go hash tag left I'm just gonna do a comment so that tells me we're moving left and to move left I need to subtract from the x value of my player so I'm gonna say ship dot X minus equals one now minus equals one means we're gonna move one pixel to the left now ideally what I should do actually is define a velocity variable which tells me how fast I'm allowed to move in every direction so let's do that at the top here I'm gonna say player underscore Val equals and let's pick some number I'm gonna pick five what this means is every time I press this key I can move five pixels so you can you'll figure out how fast that is when we start testing the game but that will also be dependent on your clock speed right so if you had a lower clock speed you probably want a higher velocity because this loop is only running so often so if I held down my key with a higher clock speed I'm gonna move more because this is gonna trigger and happen more times and move me more to the left right so let's do minus equal ship on your score Val or player underscore Val like that and now let's do the other key so I'll go a little bit faster here if keys as I say I'm going faster makes a bunch of mistakes pi game K underscore D so this is to the right like that make sure I don't forget that cool in there then we'll say ship dot X plus equals player underscore bail if keys pygame k underscore and this is gonna be double use for up we're gonna go up like that and then ship oops ship dot y minus equals player dot velka's remember moving up so we need to subtract the velocity because the starting position is zero zero and the top left and we're gonna say if keys pi game k underscore s which is gonna be down notice I'm using WASD you could use the arrow keys if you want by changing this to be all capital left all capital right all capital L capital down but let's do this we'll do it down then ship duck y plus equals player under squared bail okay so now that we have that what this will do is move our player so let's run this and let's have a look so if I use my WASD you can see that this cube now moves around the screen so let's now start restricting how this cube can move because notice I'm gonna go completely off the screen I can go any direction of I want right and maybe you might think this is a bit too fast as well so let's make sure that we can't move off the screen so to do that what I'm gonna do is say if keys PI game duck a underscore s and ship dot y plus player bail is less than height so what this is saying is if I add sorry not Val what am I saying player underscore bail if I add this player velocity value to the current value of my why will I be off the screen if I'm not off the screen let me move because I'm less than height which means I'm not off the screen so I'm trying to move down right otherwise don't that's what that's saying so that's that's that line so now let's see the other ones and ship got Y minus player underscore bail is greater than zero because we're moving up so we want to make sure that we're not going to be less than zero when we're doing that and for right we'll say and ship dot X plus player bail is less than width right and we'll say and ship dot in this case x- player underscore bail is greater than zero so now if we run this you'll notice that I can't go down while I can but it stops me I can't go left right if I try to go up I can't go up if I try to go right though I can go all the way off but just not like only here now the reason why I can go this far off is because the top left-hand corner is what I'm checking so right now technically the constraint that I've plugged in here that's in my code is valid because the top left is still in a valid position what I need to check though is if the edge of this cube is hit so the way I do that is by getting the win right so what I can do is a quick fix here is say if I'm moving to the right let's add 50 because that's the wick of the cube and make sure that the top left-hand corner is further enough to the left such that you know even if I'm adding this width it won't go off so that's the idea here with going rights and now same thing with the bottom so if I add 50 to the bottom so when I'm going down I want to make sure that the bottom edge doesn't go off the screen so that's how you do that is you just add the width to that equation so now notice I can't go any further than that and if I go to the right I can't go any further than that now obviously we're gonna change this because we're gonna use like proper graphics in a second but I wanted to show you how to move first in a more fundamental aspect so you understand the mechanics behind what I'm doing okay so now that we've done that let's actually make a proper ship so let's make a proper player ship rather that that has the proper graphics rather than what I've just done right here so in draw what I'm actually gonna do here is go window blitz and I'm gonna say ship or self dot ship underscore image this is just how I reference the attributes that are specific to this ship so the one that's being drawn I'm gonna draw this at self dot X self dot y like that so draw window tuplets self that ship self that excel taught why we'll get into the laser stuff later but that's like further on once we have the graphics working okay so we'll do that and now what I'm gonna do is to find a new class and then call this flare now the player is going to inherit from ship which means that it's gonna take this initialization it's gonna take this draw method and use it we're gonna add more stuff to the ship class later that will make this make more sense this inheritance but for now just understand that any methods in here because I've defined this inheritance means I can now use them inside a player so what I'm gonna do is to find the net inside of player so define undescribed square net self XY health like that health will be a default parameter of 100 once again and what I'll just do immediately is called ish this initialization method from inside of here so to do that I'm gonna say super dot underscore underscore net underscore underscore self XY health like that I don't know if this takes self I don't actually think it does I think it's just XY health what this says is super is this parent class ship let's use ships initialization method on this so we define our own initialization method because we're gonna need to change a few things in here which I'll show you in a second but let's use the super method so it creates all of these different variables that we need and it initializes things right it just runs that code and now let's add our extension we're gonna say self dot ship underscore image equals yellow ship and self the laser underscore image equals yellow laser so we've defined how these two non parameters so now we have those we're good to go and what we need to do next is create what's called a mask so what a mask is gonna let us do is do pixel perfect collision so you may notice in other games where there's like weird hit boxes and if you hit like the edge of something but there's actually not a pixel there it still counts because it just does a square hit box well pygame has this thing called masks which lets do pixel perfect collision which we'll get into later but we need to define a mask so we're gonna say a self dot mask equals Pi game dot mask dot from surface from surface self dot ship image now what that means is okay take this surface which is the ship image and make a mask of it this mask just tells us where pixels are and where they aren't in this image so that when we do collision we know if we actually hit a pixel or not then what we're gonna do is say self dot Max underscore health because we're gonna add a health bar later is equal to 100 are not hundreds re is equal to hell so whatever health we start with is the maximum health we can have as a player now the reason we need that is because we're gonna decrement the players health rate because we define health up here but we need to still store what it started with so that we can figure out what its maximum health was when we want to draw the health bar and figure out the percentage to decrement it by so there we go we have the player and now I think that's actually be okay for drawing so let's just change everything from ship now to player now an easy way to do this and sub-line taxes do command each and find any ways to ship make sure it's case sensitive and replace that with player like that so we're gonna say ship player which means now all these things that are highlighted or and you can see them it's not highlighting the capitals will change to player so player will be equal to well that'll have to change by names you get the idea so let's hit replace all and now all of those are changed to player so player dot x player doubt why all that and let's now change instead of ship the Xena State player so we're gonna initialize a new player which is equal to a player objects starting at three hundred six fifty and then we've changed all that so now we'll draw the player so let's run this and notice now I have the ship and it's moving around now no fancy animations here but that's fine we're I'm gonna do an animations in this specific video let's fix this now so that we can't go off the screen of the ship so to do that what I'm gonna define in ship is actually a way to get the be height and the width of the ship so I'm gonna define inside a player actually let's do it inside a ship because this will be fine let's define gets underscore width like that so this is a method and what we're gonna do is return in here self-thought ship underscore image dot get underscore whip so remember whenever we have a surface we can call get width and get height on it and it'll give us that so here also define get underscore height self return self dot ship image gets underscore Heights like that okay so these are two methods there's getters they're literally just turning a value to us because we're gonna want those in the main loop I've defined this in ship not player because player inheritance from ship and we're gonna want to use these inside of the enemy ships which we create later so let's just go ahead and add them to this you know base class that we had above okay so now that we've done that rather than +50 all we need to do is go player dot get underscore in this case this is height and player dot get underscore wit so before we had fifty there because fifty was the height and width of our rectangle but now since we have the actual image we need to get the height and width of that image and use that as the offsetting value in this equation right so that's why we're adding those into there so let's run this and now notice that I can no longer go off the screen to the right I can't go down can't go left cannot go up you may be a global why is it only like on this sides a little bit different than this side all of that you can modify those numbers like I had a few pixels if you want it's just based on where you start so like says start at some location right well moving to the left I don't really it's hard to explain this but if you start at pixel value eleven and then you can move back five right so you're at six but if you go so you can move back even more from six and you go to one pixel you can't go any further than that but if you're going to the right say the boundary is at like 20 then you can go to sixteen but you can't go further than that because if you're at sixteen and you add five which is the velocity you'll be greater than the width which is 20 pixels in that example so you can't move that far over so I get that question sometimes like why is it different on the left and right side I don't think it's a big deal but some people do it's just based on where you start the object and you're subtracting a certain pixel value of like five or four so you're only gonna be able to move in a certain direction so far I hope that makes sense that explanation okay so now that we have that the ships moving around like we're we're making pretty good progress here let's do the enemy ship so let's let's get that one running so we have player so let's define enemy so class enemy ship like that it'll inherit from ship and in fact we don't really need to call it enemy ship we just call it enemy like that and inside of here we'll say define underscore underscore net underscore underscore self X Y we're actually gonna put a color parameter here remember I was talking about that before and then health equals behind so inside here we're new same thing we've done before I'll go through this slowly after but I just like to type it so that you don't hear my keyboard the entire time that I'm talking and then we'll pass X Y hello okay so what I've done is I've defined a new initialization I've said this time we need to pass a color because our enemy ship will be different colors or it'll be red green blue I won't not BL and will pass the health as well and we'll call the super constructor so this one right here to set everything up and then we will add our own images and stuff after so what I'm actually gonna do in here is make a class variable and I'm gonna call this ship I'm actually gonna call it color underscore map now the idea behind this is that what I want to do is make a dictionary where a specific string because what I'm gonna do is pass a color as a string so like will pass the string like red green or blue based on what color it is we want so if they hit red I need it so it gives me the red images so this enemy will have the red images right if they give me green I need them to have the green images so I'm gonna make a map which is just a dictionary that says okay if we type red right so if we do red then what that maps to is the red spaceship image and the red laser so if we have the red ship it's gonna use the red spaceship image and the red laser right if we have green then what this is gonna give us is the green spaceship and the green laser right and same thing for blue so if we go blue so be blue spaceship and blue laser now that's like pretty straightforward I'll you make sure I add commas here because it's a dictionary let's hit enter one more time so that's proper and now what I can do is just use this map so I can say something like self dot ship underscore image self dot laser image is equal to self dot color map cut so all I need to do is just pass that color the parameter that we passed in to this map and then that will return to me the images that we're gonna use so that's what we have so we'll do self dot ship image self the laser image is equal to self the color map it's not really much more I can do to explain that that that's the basic concept behind that okay so once we have that we need to make a mask so to make the mask gonna say self dot mask is equal to in this case tie game mask dot from surface like we did before except this time well actually I using me the same thing self dot ship image like that so we have the mask we have the color setup we have the images and all we need to do now actually I don't even think as much we have to do here we're gonna implement a method that allows us to move the ship but I think that's all we really need for the enemy so let's hop move and let's have Val and what this is gonna do because the enemy ship will only be moving downwards right it's gonna start at the top of the screen and move down this is just gonna say okay self thought why plus equals Val so if we pass a velocity to this move method we'll move the ship downwards okay so looking at my other screening that's all we need for the enemy ship so let's now figure out how we can start spawning enemy ships and have them moving down the screen and then we'll do lasers will do collision a main menu and I guess an end screen like if you lose and will pretty much be done with this application although that is in a little bit because the lasers are the more complicated part of this so let's start moving the enemies so what we're gonna do is make a list here I'm gonna call this enemies I say enemies equals blank list what this is gonna do is store where all of our enemies are and in fact I'm gonna another very well I'm gonna say oops not staticmethod I'm gonna say wave length is equal to five so we're going to start with the wave length of five and then we're gonna increment that every time and in fact I'm gonna set level equal to zero because I didn't do something cool in the second you'll see why I'm doing that but what I want to do is every time that we get to the next level generate a whole new batch of enemies and have them start moving down the screen so every level we generate a new wave that wave will be in random positions and then they'll start moving down slowly based on a certain be lost which is gonna be called the enemy fell I set that equal to one pixel so they move quite slowly downwards on the screen and what we'll see how this works so that's the idea here what I'm actually gonna do is I'm gonna get ahead of ourselves a bit inside of the redraw window function I'm gonna say for enemy in enemy's enemy dot draw win the reason this works Rex you like well I don't have a draw method insan enemy the reason I can do that is because this inherits from ship ship has a draw method where it draws the ship image and we've defined a ship image here so we can draw them before the enemy right based on whatever color it is that that enemy is so for each enemy let's draw it onto the screen that's what this says in fact I'm gonna make sure that I draw them behind the player just let's say an enemy and a player in the same position the players overtop and the enemy because ideally you want to see your own character not the enemy if you're overlapping so that's the idea behind that okay so now that we have that we need to move the enemy and spawn them so the first thing I'm gonna do is actually move this redraw window to the bottom we might be moving around quite a bit throughout this but let's put at the bottom now to keep it kind of out of the way and at the top I'm gonna say if the Len of enemies equals equals zero level plus equals one so essentially as soon as no more enemies are on the screen because once they hit the bottom once they're off the screen this list is gonna be empty that represents our enemies because we're gonna delete them and I'll show you how that works in a second let's increment the level because we beat the current wave of enemies let's increment the amount of enemies we're gonna have so let's say cur underscore wave or wave length ya plus equals five so if we start with a wave like the five every time let's add five more enemies that's what I'm gonna go with but you guys can add as many or as few as you want and then let's now create this many enemies so let's say for I in range wave length like that let's spawn some new enemies and append them to the enemy list and start moving them down so what I want to do when I spawn these enemies is pick positions for them so they don't all come down at the same time ideally I want them to come down so I want to spawn all of them here I want to create all of them here but I want them to move down and look like they're coming at different times so to do that I'm gonna pick random positions for them that's way above the screen so the idea is I'll go to my drawing tablet here to show you quickly if this is our screen right and I want my enemies to all be moving at a consistent rate I want to spawn them all at once but I want them to look like they're moving at a different duration I can put them above the screen in a negative position and move them down slowly so what happens is these will all move at the same time right they'll move at the exact same velocity downwards but since they started at different heights it will look like some of them started coming down before the other ones when in reality they just started higher up so that's the concept that I'm gonna use here is I'm gonna randomly spawn them at different heights and different xvalues they might overlap with each other that's just the principle of random there is ways to fix that but we're not gonna do that here so that they look like they're coming down at different speeds or different areas right so that's the idea so let's do that so what I mean new is I'm gonna say enemy equals enemy here we need an X and a Y so random rand range remember I imported random at the top the range that I want for the x position is gonna be 100 and width minus 100 so this is pretty much saying I want to spawn my enemies at a maximum left side of 100 actually let's make this 50 and a maximum right side so they're top x position or top left x position at with minus hundred that's just to make sure they don't go off the screen right and then we need a Y value so soo random dot R and range in here we need a Y so I want these to start in negative so they start off the screen so my first value is gonna be the smallest value that I want them to start at which is gonna be 1500 and the next value will be the closest so I want them to start between negative 15 hundred and negative 100 now you could in theory have the possibility that they all start at the same level because this is random but the idea is that they probably won't do that because it's such a large range so some will be up higher some will be down lower and they should be in kind of relatively different positions so that they come down at different times now you can change the way you spawn these if you want but this is my idea this is what I want to use but again guys do whatever you want this is your game so random because now that we've done the X&Y position we need a cutter so let's do random dot choice and inside of here we're gonna make a list of color so in this it's gonna be red blue green now what random not choice does is randomly chooses one element from a list pretty straightforward so this is the list of colors that we want that are valid red blue green so randomly pick one from that for the that's just cuz I want some variety I want some different ship colors if you want to have like red ships have more health or something go ahead feel free to do that but I'm not gonna do that for this I'm just gonna make them all the same but just different colors right so it spawns them and now what I need to do is just add them to the enemy list so enemies dot append enemy like that and now that I've done that they're in the enemy list and I can start accessing the enemy list to move my enemies so we've done that we've spawned them in if the enemies the letta enemies is zero we'll increment the level increment the way by five spawn all the enemies that we need and then you know move forward now you could say all right well if we get to a really high up level this might be slightly flawed because you can have so many enemies within this smaller range so you could do something like negative fifteen hundred times level over five or something like you can change this value if you want a level over five will be a bit of an issue but you can do like a more dynamic approach to this range if you want to multiply by some constant value or something like that but that's just I'm just starting that idea out there in case you guys want that so if you want to move these enemies essentially what we're gonna do is every time that they're on the screen so there's any enemies in our list well move them down by their velocity you're pretty easy we're gonna say four enemy and enemy's enemy don't move and in this case it's just gonna be enemy velocity like that now you see how neat and nice our code is reading right now because we've implemented these methods keep that in mind that you know that's the nice thing about making classes and methods is that when we use a main line like this it's really easy to read because we have these nice methods that literally are reading out and telling us what it is we're doing so I think that your work let's run this code what's the issue here what have I done wrong uh to do random dot choice kierra green ah so it would help if I spelt everything correctly so the green needs to ease the issue there was I spelt that wrong so when it tried to greet an enemy that was gren not green it couldn't do that let's run this now and see that if we wait a second cuz it is they spawn quite high right now all these enemies start coming in now you know we got unlucky here they kind of came in a batch but we can again do whatever we want if we want to spawn them like every 100 pixels upwards you guys can figure out how to do that but the issue we see we're seeing immediately is we're not losing any lives when these enemies go off the screen and they're not actually being removed from the list which means that we're never gonna make new enemies once all the enemies are off the screens what we need to do now is every time we move the enemy make sure that they are not off the screen and if they are decrement the lives and remove them from the list to show hey this enemy is gone so to do that we're just gonna check the position of the enemy so if enemy dot y + enemy dot get underscore height notice we've used this method now that we needed plus actually it's not plus because we already moved them so we'll just check is greater than Heights then what we'll say is lives minus equals one because we lost alive they hit the checkpoint at the end of the level let's delete them then so if we want to delete them since we're looping through this list I need to make this a copy of the enemy list and just do enemy dot remove or not enemies or enemies start remove enemy what this does is remove the object which is this enemy from the enemies list I've made a copy here so that it doesn't modify the list we're looping through because sometimes that leads to issues and that will mean that then once all the enemies have gone off the screen there'll be none left in the list so we're able to hit this Len equals zero you know condition increment the level and ink the wave so let's do that and let's run this and let's see if they actually go off the screen I guess I'll fast forward and we'll go through this okay so we can see that the lives now obviously we're going negative because you know we've lost at this point but just notice that once we get to negative five because we started with ten the level increments and now more enemies start coming onto the screen in different positions and these seem to be working fairly well now obviously what we need to do is make sure that we don't have a negative live square so we'll implement something that will fix that for us which is just gonna tell us if we lost and then we'll get into shooting the lasers and after we do the lasers and the collision with the lasers I think that's pretty much all we'll need for this game so let's let's do the thing if we lose down so essentially if lives is less than zero or I guess less than or equal to zero and in this case I'm actually going to say or Claire dot health is less than or equal to 0 because we are gonna implement a health bar that's the doctor about we'll need to do that next with the with the player then we'll say that we lost so we'll just a loss equals true we'll define a lost variable up here we'll say I lost equals false like that and now forgets about lost correctly what we'll do is if lost is equal to true we're gonna increment some kind of counter system that essentially says we're gonna show a lost message on the screen for a certain amount of time and then once that lost message is done we'll go back to like the main menu which we're gonna create later so lost equals true let's actually just do something inside of redraw window here so we'll say at the bottom if lost so if lost is equal to true we can access that because it's up here what we'll do is we'll say lost font which we're gonna make need to make a new font for so so the main font will say lost font like that make this a font size of 60 s there's a bit bigger a bit more emphasis and we'll say lost underscore label equals lost font dot render in this case the text is gonna say you lost exclamation point exclamation point one color that'll be white 255 to five to 85 then say wind judge blitz lost label and if we want to put this perfectly Center in the screen I'll show you some math magic to do that that's gonna be width / 2 - explain this in a second don't worry lost underscore label get underscore width / - so the idea behind this and let's put it at a Y position of 350 is that if we want this to be in the center the center of the screen is the width / 2 but since this has a width like the text itself and we draw from the top left we need to make sure that we're drawing so that B width right when we include that width will still be Center so if we do with / - and then we subtract from that to go left so that we account for the extra width half of the width of the text that'll be perfectly centered because that's like I don't know a really great way to explain it but essentially if we have Center here if we draw it's gonna come all the way over to one side or all the way over to one side so if we can move this position over slightly so that it's half of where the width is then it'll be perfectly Center in the middle of the screen that's my somewhat visualization using my hands hopefully that made sense but that's the math there - put that in the middle and there you go so now we'll check what happens if we do lose I'll show you that the game is gonna still run when it says you lost which we'll fix in a second but the idea here is that it's just like you know it's gonna say that we lost so let's speed this up we'll get through it and I'll show you case we're coming out in one life we see you lost now pops up in the middle of the screen obviously the game keeps running but I'll show you how we fix that now so to fix this we need to increment some kind of like timer that tells us how long to show the lost message for before we just reset the game and also pause the game right so it doesn't keep moving and decrementing the lives once we lose we want to just pause the game once we lose so we're gonna say after lost we're gonna say a lost underscore count equals zero and what we're gonna do now is if we've lost write lost equals true will say lost lost underscore count + equals one so increment one every time and then down here was say if lost like that say if lost underscore count is greater than in this case we're gonna do 60 because that's our FPS so actually will do FPS multiplied by five so if we wanted to say show the message for five seconds we would do FPS multiplied by 5 because FPS is how many frames we show per second you know and then how many seconds who want to in this case let's do three so if it's greater than that then what we'll do is we'll break this while loop so set run equals false and we'll quit the game otherwise so else we'll continue now what this is saying essentially and we're gonna have to move this redraw window to actually be at the very beginning of the loop so I show left it there but that's okay what this is saying is if we've lost so if lives is less than you go to zero or playerhealth is less than zero loss equals true lost count plus equals one and then we say if lost so if we have lost if the lost count is greater than FPS times three then run equals false which means we've now got past our three-second timer let's quit the game if it's not so if it's still looping we're still waiting to hit three seconds continue which means don't do any of this don't let us move don't move anything go back to the beginning this while loop and keep running and then we're redrawing the window every time so we'll look like that lost just sits there for three seconds and nothing else happens let's run the associate what I mean so again I'll speed up we'll get to when we lost and I will show you okay so we're getting down to it here we can see two one you lost boom level freezes wait two three boom game ends okay so that is how that works we've got the lost counter going here we can add a main menu pretty easily later on but now time for collision and lasers now the lasers and the bullets are a little bit more complex in terms of how they move because we need to shoot them from the enemy ship we're from the player but we'll get into that I guess right now alright so the first thing we need to do if we're going to be shooting lasers is we need to create some kind of laser object so in this case what I'm actually gonna do is make a new class called laser so let's type this out class laser we're gonna do in a knit and what this is gonna represent just one laser object now the idea is that we're gonna have multiple lasers being shot from each player right so if I shoot a laser going upwards I need to make sure that it keeps going in that same upwards angle right it's not following what the player is moving cuz a common issue people do is they'll make like the laser follow the exposition of the player which means that if I press the left arrow key once I've shot the laser the laser moves to the left which is not what we want to do right we want to make sure each of these items are independent of the person or the player or the enemy or whatever it is so that they can kind of act on their own they can collide with things on their own and they're their own entity so that's the idea so what we're gonna do here is have a laser it's gonna have an X Y it needs an image we're gonna pass that image from the ship class so the idea is that when we make a new laser object so when we shoot this laser the player will create the laser object add it to it it's Laser list you guys we have lasers here and then it will control how those lasers are moved so that's kind of the concept but we'll get into that sighs so let's say self that x equals x self the y equals y self-thought IMG equals IMG and of course you need to make a mask for this as well because this is what's gonna be colliding with different things so self dot mask equals Pi game mask dot from surface self IMG note you could put IMG there as well doesn't really matter but we're gonna do that so now what we're gonna do is make a draw method so the draw method will take self.window like before and we'll say window judge belitz self dot IMG and then self dot x self dot y now what we'll do is we'll do define move so define move self Bell which will move this with the velocity so the velocity will be going upwards or downwards based on what we pass in here so in this case we'll just say self dot y plus equals vel if we want to go down will give a positive l if you want to go up will give a negative L as the parameter and if we add a negative value obviously that means we go up so we have move let's define a few our methods we're going to find underscores screen which is gonna tell us if these lasers off the screen based off the height of the screen so we're just gonna return from this return self-thought y is less than height and yeah and self-thought y is greater than zero I will do greater than equal to less than equal to as well I guess and that should be good for this right now we're gonna find one more method which is gonna say collision which is gonna tell us if this collides with an object so laser collide object and what this is gonna do is call a function that we've yet to define but we'll define in a second called collide so all this will do is return the collide of object itself now let's actually go ahead and create this collide method because our yeah collide function I guess because what we're gonna need to do is check if things are colliding when removing the lasers so it makes sense to do that before we start actually moving the lasers but essentially what we're gonna do with the collide is use these masks to determine if two objects are overlapping if the pixels between them are overlapping and if they are then we'll say yes these two objects are colliding so I'm gonna define a function here called collide it's gonna take object 1 actually we'll just do obj one and obj two and what we need to do here is use something in PI game or use this mask property called actually I got a look over here to see exactly what it's called because I'm blanking on its right now I believe it's like overlap yeah that's what's called it's called overlap so what we need to do when we call an overlap and actually let me go to my drawing tablet if I give you my beautiful drawing skills with my mouse again to show you what I mean so what a mask is is essentially if we have like this right so this is my object an object has a width and a height now we know that when we're drawing these objects only some of the object is actually taken up with pixels right so in the example of our ship we have something this is going to be my very crudd ship right this is like my rocket ship say it looks something like that maybe it has like a little tail but the idea here is that these are where the pixels are and all of this blank space here is not where any pixels but based on the way that we've loaded this object in if something hits like right here we'll say that it's hit the object because it's inside of this width height hitbox like this WH hitbox I'm not sure if if I explained this before but essentially let's say we bring in a circle like we left it's really hard to draw with this mouse let's say we bring in a circle right well what actually happens is it makes a square around this circle and that is what the surface of the circle is it's rectangular because it's very difficult to have circular objects in computer graphics like when we're rendering and drawing things or creating services so the idea is that we have this circle but really it's represented by a square where all these other things are here a transparent but the actual circle itself is the pixels right so we want to make sure that when something hits our object we're not saying it hit unless it actually hits some of the pixels of our object not the transparent background that may exist that's a part of that object and you will see this quite often when you load in sprites as it'll load in with with height right like say we load a little character it'll load in like this like this will be our character and if you hit this side like anywhere on this box it will say we hit the character even though it's not touching the pixels so it's misleading to the player so the way that this mask thing works is if we have two let's say objects like this and they're overlapping like this what we do is we ask pygame we say okay so if there's like pixels here here here here here here and there's pixels here here here and there's pixels in the same area so there's pixels inside of this inside of this overlap in both objects we'll say that this collided if there's not we'll say it didn't collided or we it did not collide because these two objects are not overlapping where their pixels exist I think that makes sense but like the idea is if we have you know stickman right and he has his thing like this and then we have you know I don't know say a laser like that maybe the lasers hitbox is something like that even though these two boxes are colliding we're not gonna say they collide unless the pixels hit the other pixels so the way that we need to do this though is we have these two masks which represent where pixels are that's why we created that mask object but in order to determine if they're overlapping we need to come up with something which that's called an offset the offset essentially tells us the distance between the top left hand corner of both of these objects we need to know that because given that information we'll be able to determine if they are actually colliding with each other and where their point of intersection actually is because what the overlap method will do in masks which we'll use in a second is tell us where these two objects collide so the point of intersection between them now we don't really need that but we're just gonna see if we get a point of intersection and if we do we'll say yes these objects collided if we don't they did not but the idea is we need this offset which tells us how far away object 2 is from object 1 based on their top left-hand corner coordinates so to calculate that what we're gonna say is obg 1 actually have to say offset underscore X equals obj 2 dot X - not - equal sorry - obj 1 dot X this will tell us the distance from object 1 to object - it's fine if this value is negative which it may be sometimes depending on the coordinates but that's how we do that for offset X now offset Y is gonna be equal to obj - why - obj1 obj2 I so again that just tells us the difference between them since this is X Y I mean you can consider that a vector with two components we need to do these separately and subtract like that so now that we have that what we can just do is return obg 1 dot mask dot I believe this is overlap yeah I've said that so many times dot overlap and then here we're gonna say obj - so is object 1 overlapping object 2 with the offset of offset X offset Y so that's what this collide function will tell us is given two masks right so give an object one and object two if they both have a mask so mask here and sorry this needs to be Audra - mask if these masks are overlapping based on the offset that we've given between the difference of their top left coordinates then we'll return true otherwise we'll return false and actually what this needs to be is return does not equal none because if they're not overlapping this whole thing that I'm highlighting here will return none if they are it will return to us actually at a polar tuple that looks like this XY that tells us the point of intersection so hopefully that wasn't too confusing and I didn't go too crazy facet is kind of hard to explain masks without my drawing tablet out which I don't really want to get out right now but I think that's good enough explanation for the collision so if we go back to where we actually called that which is here we can see that all this is doing is returning the value of this collide function now the reason I've called self here is because I want to see if the object is colliding with myself right and I could call it in the other method or the other order which is self obj but all self does is give access to this specific instance so in this case it'll be a specific laser so we'll just pass those two things in so the self which is this object and then the object that's giving us here that we want to check if there's a collision with and then that will return to us if it's collided or not okay so now what we're gonna need to do is implement a few things inside of the enemy and player class in terms of creating a laser as well as creating a cool-down for the laser so we can't shoot it too fast so the first thing I'm gonna do is implement a shoot method inside of this base class ship because both of our methods or both of our classes will be able to use this so define shoot self we're gonna say Val like that is it felt no I think we literally just need so I think we literally just have shoot self and then what we're gonna do is say if self dot cooldown counter equals equals zero which means we're not in the process of counting up to a specific cooldown or keeping track of how long until the next shot then what we will do is create a new laser and add it to the laser list so we'll say laser equals in this case laser we'll give it our XY value so XY and then what else does the laser need it needs an image so the image will pass is self dot laser image because laser image is what we're storing here as the image for the laser then we'll say in this case self dots oops lasers dot append laser like that and the next thing we'll do is reset the cooldown counter so that it starts counting so I'm gonna say or not reset will start the cooldown counter so it starts counting up so self dot cooldown counter equals one so the idea behind this is that we will make sure that we are at zero for the cooldown counter so it's not as certain value like waiting to go down are waiting to go up or whatever it's gonna be and if it is will create a new laser at this current location which will move later on we'll add it to the lasers list and then we'll set the cooldown counter to start counting up now what I'm gonna do here is say define cooldown and what this is gonna do is just handle counting the cooldown so we're gonna say if cooldown counter so if self cool-down counter is greater than or equal to in this self cool-down all capitals I'm going to define that as a class variable up here so cool down equals 30 so that's half a second because the FPS is 60 right so if that's greater than self a cool-down self the cooldown counter equals zero say else self the cooldown counter plus equals one and we will only increment this cooldown counter if sorry not else say if self cool down counter so LF self-taught codec on earth greater than zero so essentially if this cooldown counter is zero we're not doing anything right because it's not greater than or equal to self duck cool done and it's not greater than equal to zero but if it is greater than zero and it's not past the time limit incremented by one okay so now we need a way to draw and to move our lasers so the idea is that we're gonna call this shoot method that creates the laser from down here so essentially if we hit the spacebar we'll call shoot which will create a new blazer object so actually let's implement that now let's say if keys in this PI game dot K underscore space we're gonna use the spacebar then we'll say is player dot shoot so I will call that method and we'll create new laser now remember this is only gonna create a new laser if the cooldown counter is equal to zero otherwise it just won't do anything that's fine we can hit space as much we want but if we're on cooldown it's not gonna work so what we're now need to do is have a method that can move these lasers because right now if we do that is just gonna make them and they're gonna stand still and in fact right now we don't even see them because we're not drawing them so first actually I'll just draw the laser so inside this draw method I'm gonna say for laser in self dot lasers like that and then we'll literally just do laser draw window so that will draw all of our lasers we have a draw method on our lasers that just draws them here so that's totally fine to call that no issue there now we're gonna define a new method this will be called move lasers so define move lasers self Bell and then OBJ's now the reason I've had obj is here so vel makes sense because that's like how fast are we going to move the lasers to the velocity but obj stands for objects and the idea here is that when I move these lasers I want to check for collision with all of these objects so to do that I need the objects that I want to check collision with which are here so we're gonna move all the lasers by this velocity so I'm gonna say for laser in self dot lasers and before we do that we're actually gonna increment the cooldown counter by calling self up cool down so every time we move the lasers we're gonna call this once a frame which means that we'll increment the cooldown counter when we move the lasers right so we can track if we can send another laser or not and then we'll loop through all of the lasers and what we'll do in here gonna check here is go laser move the velocity so we'll move it by the velocity and we'll say if laser dot off-screen which we've made that method here will delete the laser with laser it off screen height will say if that's off the screen then we'll go self thought lasers don't remove laser like that and it shouldn't be a problem with that now otherwise if laser dot collision with an object and watching need to implement another for loop in here in a second I'll tell you that guess take a step back here so I think I'm gonna confuse myself a little bit so I just want to step back and make sure everyone understands so first of all I've changed this parameter from OBJ's with an ass to obj the idea being that actually what I'm gonna do in this specific move lasers method is check if each laser has hit the player so the idea behind this is that this is gonna be used for the player and for the enemy but inside the player what I'll actually do cuz this is the base class right we're inside a ship is I will implement a new method called move lasers but rather than checking if we hit the player will check if we hit any enemies so that's kind of the idea we need to separate move laser methods one for checking if all of the lasers shot by the enemies have hit the player and one for checking if all the lasers hit by the player have hit the enemy so that's the idea since there's only one player we only need one object here which means for each laser we can do if laser dot collision object then we can reduce the health of that object which will be our player so we can say obj dot health minus equals let's say they lose ten health so we can change this value to be whatever we want but I'm just gonna keep it at ten for now and I think that that is pretty much good except that we're gonna need to delete this laser so self-taught lasers Dutch remove laser like that so yes so that's what this is doing call the cool down which goes through and says okay you know we're gonna increment this cool down based on what we've defined here so if we can shoot or not then we're gonna for each laser that we've shot that exists currently in our list we'll move it down the screen by the velocity we'll check if it's off the screen if it's off the screen we'll remove it if it's not the screen but it's collided with one of our objects in this case this object will be the player that we pass to it will do object l - equals 10 which is the player right - equals 10 and then we'll say self dot lasers don't remove lasers so remove that because when it hits them we don't want it to keep going down afterwards and it potentially hit them a bunch of times if it keeps colliding with the player so that's the move lasers here I'm gonna copy this and we're gonna change it a bit inside a player so let's put this inside a player this is gonna override that parent class 1 and we'll do the same thing so it'll call self cool down again and we'll say for laser and self dot lasers laser don't move but now what I'll do is I'll say L if actually yeah laser to off-screen height will change this to OBJ's then we'll put an else and inside of here we're gonna put another four loops we're gonna say 4 in this case obj in OBJ's then do this and say if laser collision obj and then we could do obj dot health - equals 10 but since what I'm gonna pass in here is a list of all of the enemies because we want to check if the player's lasers have hit any enemies we're just gonna remove that enemy from the OBJ's list so we're gonna say we'll remove the laser obviously we'll say Oh BJ's don't remove obj okay so I think that makes sense so we have the player what this is doing is I'm gonna pass to here and this gonna make a lot more sense when I start actually passing from the main loop it's just I always confusing now cuz it's kind of an abstract concept but for each laser that the player has move the laser lasers off the screen remove it if it's not off the screen for each object in the object list if the laser has collided with that object remove it so delete that object otherwise remove the late or not otherwise but remove the laser after that happens as well so that's all we need for player and ship for moving the laser so now what we need to do is for each player will our player and for each ship or each enemy ship we need to move their lasers each loop so for enemy and enemies we also need to call enemy dump move lays right with a velocity which is gonna be the I guess what was the velocity the laser velocity do we have laser velocity as a as a variable we do not so I'm gonna define that and I say laser underscore Val equals four then here we'll do move it by laser underscore bail and check if it's hit the player so we pass the player object there that's the idea behind that then down here we're gonna say player don't move lasers pass in this case the laser Val and the entire list of enemies so self dot enemies so this will now check if the laser has collided with any of the enemies so that's the idea behind this is that what is the move lasers method is doing there's easier ways to do this probably but this is the way that I came up with it that seems to make the most amount of sense so let's run this now and say self is not defined so so this shouldn't be self that I mean I've had this should be enemies long session of recording starting to get tired here so let's run this in check now so if I press space okay so name X is not defined where is that so I've made a mistake somewhere here let's have a look so laser XY self dot laser image okay so that should be eighty three and shoot so I know what the issue is immediately but I'll break it down for you so I made a mistake here in the shoot method by calling XY when really this should be self dot X self dot why won't be surprised we get a few more errors like that so let's run this in press space when I press space nothing's happening aha so I determine the issue so you saw that none of the leases were showing up now there's a few problems I'm gonna go through I want to summarize what we've done so far and then fix this issue so what we just did was create these move lasers and I'm sure I apologize in advance if this was really confusing because I was kind of confusing myself was well I was going through this but the ideas again these are moving the lasers so we call this every loop on all our enemies and on all our players or art player so that they can handle the movement of their own lasers notice that in the draw we're drawing all the laser so this should show up on the screen what we do is inside of cooldown we're making sure we're not shooting too fast and that we have at least a half a second delay before we can shoot that's what this does here we make sure that the cooldown counter is equal to zero then we make a laser and add it to the list if we press space right if we call this method if we shoot so then we set the cooldown counter to 1 the cooldown counter goes through does its loop and then it lets us shoot again once it resets to zero so here this is the move laser for the player this is a little bit different what this is doing is checking if the laser collides with every single enemy which we pass in as OBJ's right if it does we remove that objects remove that enemy and we remove the laser now the issue I was having is this right here if laser off-screen Heights then remove the laser what I did in off-screen was a little bit of a mistake so this actually needs to say not this so what this is telling me here is if this is on the screen that's what this value is so I need to negate that to not to make sure that I actually get what I'm looking for is if this is off the screen I get true and if it's not off the screen I get false whereas before if it was off the screen I was getting false and if it was on the screen I was getting true so just immediately being deleted so let's go ahead and run this now and notice and I'll show you this mistake as well when I press this bullets going backwards now the issue with that and let's just actually just test if this even works so it does if I if the laser hits them it deletes them the reason that's happening is because I haven't made the velocity negative to make it go upwards so what I need to do is here in laser valve for players I need to make that negative the reason for that is I want to make sure that I'm going up not down because if I pass a positive velocity and I add a positive velocity to my bullet or my laser it's gonna go down or it's not upwards so let's negate that or change that to negative and now notice my bullets are going up now if you don't like the speed of these bullets you want to increase them I I agree with you I think they might need to be a little bit faster let's make them 5 like that and we will notice a slightly substantial difference in terms of the speed of these bullets but notice that that collision was working and now all we need to do is make it so that the enemies start shooting at us once the enemy starts shooting at us we'll implement the health bar and then will pretty much be done with with this well we obviously need to do though we have you lost screen actually but we need to add like a little bit of a menu and stuff but we're pretty much almost done once we do that so let's do that now I let's make the enemy start shooting Anna okay so what we need to do now to actually have the enemy shoot a bullet is pick some probability that they're gonna shoot each frame so ideally what we're gonna do is something like if random thought rand range between zero and some number is equal to one then have the enemy shoot so what number do we pick though is the question so let's say you want every second your enemy to have a probability of 50% of shooting so every second you want a 50% chance that your enemies gonna shoot so in theory every two seconds your enemy should shoot a bullet and that's gonna apply to every single enemy well you need to take that probability which is one over two right which would mean you just put two here and multiply it by sixty because you have 60 frames per second so if you want the probability to be that they have a 50% chance of shooting every second then you make this number 120 because 60 times two is equal to that and in fact if you want to keep this easier for yourself you can do something like four multiplied by 60 even though we know that's 240 just so you can change this to have it equate to the amount of seconds before you want the enemy to shoot now you can hard code like every two seconds have the enemy shoot but I just like to have some degree of randomness to make the game a bit more difficult I don't know if this probabilities gonna be too low or too high let's leave it on to for now and just mess with this number and see if it's good or not for you right so now that we have that though let's run this and hopefully our enemy should start shooting once they get on to the screen so let's have a look at this and they do you can see that they're starting to shoot some of them are shooting more frequently than others of course obviously this is rent right now notice that I can run through my enemies so we're gonna fix that so that we can actually if we hit the enemies we lose health but also I can be hit by the bullets or disappearing these things can hit me and you might notice that the bullets are shooting slightly offset from the center of the enemies it's quite easy to fix that you can just subtract Oh fix it for you guys right now you can just subtract the x-value of where you're gonna start shooting the bullet from so in this case if we go to enemy hmm where are we here and shoot where shoot shoot to mean to find the shoot method if we override the shoot method in enemy so let us take that and move that here what we'll do is we'll just offset where this is being created so I'm overriding this in the enemy I'm gonna say self dot X minus like 10 pixels so now if you look at this it they shouldn't be or they should be shooting more from the middle because we just offset it where the bullets start by 10 pixels so that one clearly didn't do that much for us let's move it over even more let's move it over like 20 pixels and see if that makes a bigger difference let's have a look here waiting for some enemies come on the screen it's wait for this guy to shoot his green bullets so that's slightly to the left that's okay with me I'm fine if they're like that far to the left I want to see these blue guys shooting now though give me the bullet okay so that's fairly in the center so for me that's fine I mean if you wanted to be perfectly centered you have to use a little bit more math there but this is the probability of them shooting I think it might be a little bit too high right now but again we can mess with that number and change it around but now let's do the collision between the spaceship and the other ships and then a health bar a main menu and we're pretty much done so to do the collision between a the player and all the other ships all we have to do inside of here is say if enemy actually sorry if collide enemy and in this case this is gonna be player then we'll just say player dot health minus equals 10 and then remove the enemy so enemies remove and a me like that and me if we spell that correctly okay so let's put that at the top though because we want to make sure we don't remove the enemy before we check that so we'll do that right after the enemy shoots like that and then we'll put this as an L if actually just to make sure that we're not gonna check if you know the enemy is off the screen if it's already collided with the player so that's the idea there we have this random sha we have this collision with the player that will remove the enemy and will reduce ten help from our player now we need to add a health bar which is pretty easy to do actually and then the main menu and we're pretty much done so let's do the health bar to do the health bar what I'm gonna do is just implement a function inside a player so I'm gonna say define health bar like that human takes self and all I'm gonna do in here is draw rectangles that are red and green based on the health of my player so the first rectangle I'm gonna draw is gonna be red it's gonna be the length of my player and then I'm gonna draw a green rectangle that goes on top of that red rectangle but will be only the length of the health right so if it's like say we have 50% health we have 50 out of 100 health it'll be 50 percent of the length of the red rectangle but on top of it so that it shows like half green half rent it's kind of a cool trick I'll show you exactly how that works let me just get this because there is a little bit of an equation that goes into doing this that I had to come up with so here what we're gonna do is gonna say PI game doctor all dot rect we're gonna draw that so we need to draw the health but I guess so it's gonna be a window let's take that on the window rectangle we need a color we're gonna draw a red first to pay five zero zero then we need the rectangle so self dot X self dot Y if I get suppose self-taught y plus self dot image so self that ship image dot get underscore height Y is my typing so horrible today so if that height plus ten let's finish off those brackets there so the idea behind this is that we want to make sure the health bar is below our player so we want to get the Y value of the player add the height of the ship add ten pixels and then start drawing that there and the self dot X can draw where we usually draw the X and that's fine now for the width what we'll do is self thought ship image right dot gets underscore width so it's the same width as the ship and for the height I'll just make it ten pixels and you can make that as much as you want but we'll just do ten now let's copy this and we'll do the exact same thing now in green except just a little bit for the rectangle whip so it's gonna be the exact same stuff except the only thing that's gonna change is the width and the color so zero so red green blue so 0 255 zero and what we need to do now is essentially determine what percentage of the width we should draw so if we want the width to be this or self-thought ship under square image don't get with we're gonna multiply this by some fraction that will essentially tell us how much width we want to put so to do that we're gonna multiply that by 1 - in this case max underscore health - self dot health and actually think that should be self dot health and then that's gonna be divided by here self dot max health now I think I might have made this math equation way more difficult than it needs to be but let's just think about this for one second so I want to multiply the width by 1 - this don't need as many said oh yeah I think these brackets are correct 1 minus the maximum health - the self dot health would you'll essentially tell us okay so how much difference is there between the maximum health and the health we have right now and then divide that by the max health to get the percentage health that we're down and we're gonna subtract 1 from that although I think an easier way to do this would just be to multiply by self dot health yeah this is gonna be easier by self dot health over self that max out so I'm glad that I took the initiative to fix that there yeah so this is the image width multiplied by the health over the maximum health which is just telling us what percentage of health were currently at so since we know this is gonna go in increments of negative 10 this is fine to do like we won't get a decimal value here but you know sometimes we might so just keep that in mind but yeah I think that's the equation I think that makes sense hopefully that makes sense to you guys I'm just trying to figure out what percentage of width that we should draw the green rectangle at so that if we lose 10 health that goes down a little bit right and we can do that variably using that kind of equation that I just drew so we have health bars so let's implement that now into the draw method of the player shifts so let's define the draw again so define draw do self.window we're gonna call the super draw method so super dot underscore underscore sorry one peg done it super draw will pass that the window and then we'll just call self dot health bar so self that health bar with the window so I'm just overridden the method from the parent class which is this one here which has the draw I called the parents draw method with the super and then I'm calling the health bar for the window or with the window which now should draw the health bar for me so let's have a look what's the issue here let's see has no attribute get ah so I've added an extra dot accidentally here this should be a get underscore height gets underscore Heights I'm sure most of you probably noticed that so get underscore height let's run this now what's the issue here I made another mistake rect argument is invalid I think I forgot to add the 10 yes I did so multiplied there let's see if this is the correct bracket yeah so I think I'm just messing up a bracket here I think that goes there and I think now we should be good no we're not let's see what's going on with the brackets here give me one sec guys okay so I did fix it yeah issue as I just had all these brackets messed up in here I just need to add two at the end there the code will be in the description if you guys are getting confused with what I'm doing because we're here well you can see when we load in the health bar is off the screen we can fix that if we want quite easily in fact let's actually do that now just before we forget go down to where we're allowed to sponsor first of all where we spawn the person in and make it so he spawns at six-thirty and let's just add 10 pixels to where this guy can move so if we go player get height plus 10 this is just to make sure that the health bar will be able to be shown if we add 10 pixels there will insure the health bar will be shown up so let's do that now we can see the health bar shows up in fact it cuts off a little bit so let's make this 15 pixels and now let's run this and we can see that the health bar will stay perfectly on the screen so there we go the health bars on the screen let's watch what happens if we one of these guys you can see the health bar does decrement it goes down and that is a strategy I guess in this game if you want to waste your health and hit one of the things to like sacrifice yourself for that you can do that so yeah that's uh that's how the health bar works so I guess now all this really left to do is the the main menu so let's go ahead and do that okay so main menu what we want to do essentially is just habit so it says like press any key to begin and when you press that key you can begin and that way if you die it'll bring you back to the main menu and you can choose when you want to start playing again I'll do the nap though the main functionality of this game is pretty much done so let's implement a main menu so let's define main underscore menu this is gonna be quite simple I'll go fairly fast we're gonna say run equals true while run try to say for event in PI game dot event get if vent dot type equals equals PI game so I quit like that then we will say is run equals false okay and then in here we're gonna say just draw this on the screen and actually sorry I need today if event type equals equals PI game stop mouse button down colon me so what this is saying is if we press any of the mouse buttons enter this main loop and start playing the game if we press the X button set run equal false we're gonna quit here so let's say hi game talk quit like that in fact we can actually just use the quit method - it's up to you whatever method you'd like to use but this is saying if we press any mouse button call the main function if we press quit quit but what I want to do is just draw like some text that says press any key to begin or press you know the mouse button to start something like that so the first thing we'll do is also say win top lit BG notice I'm just doing it in line here because it's just gonna be short for the main menu so we'll blit the background will say pi game dot display dot updates and then we'll create a font up here so we'll say title underscore font go spy game it's off font dot sys font Comic Sans let's do size 7d and then we'll render something onto the screens will say title label equals title font dot render press the mouse to begin dot dot try to that one let's render that white so two five two five two three five and then let's say win da blitz title label let's split this in the middle of the screen we remember that shortcut I showed us so that's width / 2 - title label dot get underscore width / - that'll put that in the middle and then here for the Y let's put that at 350 and then that should be good so now that we have that what this loop will do so rather than calling main we need to call main underscore menu and let's have a look at how this works so we're getting an error it's funny enough + 15 s so I've accidentally pressed s that's what happens when I try to save too frequently apparently what's the issue now tie game duck quit mean menu let's have a look here PI game duck quits inconsistent use of tabs and spaces love when I get that issue so for me to fix that I usually just do this converting donaciĆ³n to spaces so that should work now and let's run this win is not defined so win needs to be capital that's let's run this and there we go okay so I'll go through this in a second I'll summarize I just want to show you now it says press the mouse key to begin if we exit out so press the mouse button to begin if I hit X it brings me back here I'll show you how to fix that if you don't want that to be the case but when I press the mouse the game begins we can start playing and you know when we exit it'll reset like it should normally do so that's how that works if we want to fix it so when we press the X it doesn't bring us back to the main menu what we can do is just in so saying run equals false in here we can do quit what that's gonna do is quit the entire Python program which will just end this whole thing for us if we press the X so that's the idea now main manual summarize quickly what I did here literally just setup the exact same thing that we had before except for a main menu so I made a main loop with a run equals treat variable I defined a font I said in here we'll draw what's gonna be on the screen for the main menu which is just these two things right so the label and the background then I'll do an event lupus okay so for each event notice I didn't put a clock in here because I don't care about the clock speed for the main menu that that's irrelevant we're not moving anything around that's fine so I don't need a clock so we just have an event loop you press quit it and it ends the game and if you press the mouse button down it starts the game and it will always bring you back to this main menu function because since we call main here without setting run equal to false when main exits right when main is done we exit out of this while loop here we go back into main menu and wait until we hit the X button to stop playing the game so that's the idea behind this and that is pretty much this game okay so we ran into an issue here at least our remove X X is not in the list so let's just fix that here so 111 in move lasers so we ran into a quick bug let's try to find that 111 111 in removed laser if laser doc collision object objects are removed obj self-taught lasers don't remove laser so I guess what we should do is make sure this laser is in the list before we remove it because I guess it could have been removed in a different situation so in that case we'll just say if self dot laser I guess we'll say if laser in self thought lasers then we'll remove it otherwise we won't so this is the fix here just to make sure that if this laser is in the list but you can remove it otherwise we will not so let's run this and see now cuz I hit something and I ran to that bug so I want to make sure that we don't get that again okay so that seems to be working you know one thing to note is if you hit a if you hit something and has a laser shooting that laser will disappear just because we delete the object itself there's not really an easy way to fix that the way that we've implemented it I don't think is a huge deal I think that's part of the strategy the game is like if you want to remove someone's laser go in and shoot them like I think that is a decent strategy or that's something that can be incorporated and yeah that is pretty much it for this tutorial so again I hope you guys enjoyed if you did make sure you leave a like go subscribe to my podcast YouTube channel time out with ten that would really mean the world to me if you guys did that and of course although code everything isn't available in the description and if you need help let me know in the comments down below
Info
Channel: Tech With Tim
Views: 392,260
Rating: 4.966805 out of 5
Keywords: tech with tim, pygame tutorial, pygame space invaders, pygame space invaders tutorial, python pygame, python pygame tutorial, python space invaders
Id: Q-__8Xw9KTM
Channel Id: undefined
Length: 116min 2sec (6962 seconds)
Published: Wed Apr 15 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.