- 00:00:01 he's not answering it do you want to
- 00:00:04 tell it to each other
- 00:00:05 I'll do it finally what's up guys
- 00:00:08 welcome back to another program you do
- 00:00:15 my intro ok cool hey what's up guys and
- 00:00:21 welcome back to another programming
- 00:00:22 tutorial in this video we're gonna build
- 00:00:24 off my last one and we're going to see
- 00:00:26 how we can restructure code to use
- 00:00:27 classes and overall make code a lot
- 00:00:30 cleaner and more professional so start
- 00:00:31 this video off I recommend opening a
- 00:00:33 blank folder that you can write all your
- 00:00:36 new code in and then also opening up the
- 00:00:38 original code for this game and to find
- 00:00:42 the original code you can go to my
- 00:00:44 github page which is linked to in the
- 00:00:45 description it's this game dot py file
- 00:00:48 so you can either just look at it here
- 00:00:50 or if you want actually play around with
- 00:00:52 it locally you can fork or download it
- 00:00:54 by clicking these respective buttons
- 00:00:56 once you've done that I recommend
- 00:00:57 looking at this old code original code
- 00:00:59 for a little bit and just as a reminder
- 00:01:02 the game that it builds looks like this
- 00:01:04 so your the red block and you're trying
- 00:01:06 to dodge these blue blocks the score
- 00:01:09 goes up as you dodge them and if you
- 00:01:11 ever get hit then the game is over
- 00:01:13 there's a little bit of context to this
- 00:01:15 code when I made the original tutorial I
- 00:01:18 wanted to show people how to make a game
- 00:01:20 as quickly as possible and also not
- 00:01:23 using too too complicated of Python
- 00:01:25 skills and so as a result of that you
- 00:01:28 know the game looks good but the code
- 00:01:31 here this is all the code it's not
- 00:01:34 terrible but it could definitely be
- 00:01:36 restructured better and so that's what
- 00:01:37 we're gonna do so the task here is to
- 00:01:40 take all of this code and restructure it
- 00:01:43 in such a way that it's you know cleaner
- 00:01:46 to read the different components of this
- 00:01:49 code are broken up and broken up into
- 00:01:51 classes and it's easier to see the
- 00:01:54 separation between different parts if
- 00:01:57 you want to add additional code it's you
- 00:01:59 we want to restructure this code in such
- 00:02:01 a way that adding additional features is
- 00:02:04 a lot easier right now adding additional
- 00:02:06 features this codes kind of brittle and
- 00:02:08 a simple change might break multiple
- 00:02:11 things
- 00:02:12 so how do we restructure this the first
- 00:02:15 thing I recommend doing is to scroll
- 00:02:16 through this code and identify what
- 00:02:18 parts of the code should be grouped
- 00:02:19 together so kind of immediately we go
- 00:02:22 down I see these colors maybe should be
- 00:02:24 grouped together I see all this player
- 00:02:27 and enemy stuff that probably should be
- 00:02:28 grouped together I see some kind of game
- 00:02:31 control logic so maybe like the width
- 00:02:33 and height the speed game over the
- 00:02:36 screen etc maybe all that should be
- 00:02:39 grouped together some of these functions
- 00:02:42 can kind of hit one of those groups so
- 00:02:44 like you know maybe we separate out
- 00:02:47 something that draws things on the
- 00:02:49 screen and something that actually
- 00:02:50 controls the logic and like drops the
- 00:02:52 the actual enemy on the screen you know
- 00:02:58 we have this probably main loop that we
- 00:03:00 could kind of pull everything out of so
- 00:03:02 there's a lot of different things we can
- 00:03:03 do so the thing I'm going to start with
- 00:03:05 is these players instead of making them
- 00:03:09 just kind of single objects that have an
- 00:03:13 x and y coordinate in a list let's make
- 00:03:15 a player class and we can define our
- 00:03:18 human player as a subclass of that in
- 00:03:20 our enemy player as a subclass of that
- 00:03:22 so over here in our new folder let's
- 00:03:25 create a new file and we'll call that
- 00:03:28 player dot py and to initialize the
- 00:03:33 player class we can do class player and
- 00:03:36 then we need to start it with some
- 00:03:38 parameters so if we look at the player
- 00:03:40 over here it has a size and it also has
- 00:03:43 an x and y coordinate to start off with
- 00:03:46 so we'll put that in our knit method and
- 00:03:49 if any of the things that I'm showing
- 00:03:51 right now are foreign to you definitely
- 00:03:52 check out my classes tutorial because
- 00:03:54 that will get you up to speed on what
- 00:03:57 we're actually doing in this refactor
- 00:03:58 video so in it we're going to pass
- 00:04:01 itself we'll pass an X will pass in Y
- 00:04:04 will pass in size and then we'll set
- 00:04:07 those accordingly
- 00:04:17 so now one thing that is immediately
- 00:04:20 nice when we start using this class is
- 00:04:23 instead of in our methods down here
- 00:04:25 needing to like index by 0 and index by
- 00:04:29 1 when we want to get X and y
- 00:04:30 accordingly now we'll be able to do
- 00:04:33 player position X player position dot Y
- 00:04:36 and it'll be a little bit more clear
- 00:04:38 what we're doing in our code okay so
- 00:04:40 what else should we add to this player
- 00:04:42 class well looking through this code
- 00:04:45 over here on the right side let's see
- 00:04:47 how players are used okay going through
- 00:04:51 this one thing I immediately see is
- 00:04:53 collision collision check so in the
- 00:04:56 collision check it's just comparing a
- 00:04:59 player position in an enemy position so
- 00:05:01 we definitely can move that over to this
- 00:05:03 player function is there anything else
- 00:05:08 ok I see something here it might be in a
- 00:05:11 couple spots but oh yeah draw enemies
- 00:05:14 and this pygame draw dot rect
- 00:05:17 so this pygame draw a rectangle right
- 00:05:20 here I'll make this a little bit bigger
- 00:05:21 all this stuff in this function right
- 00:05:24 here that is drawing our human player
- 00:05:27 and it's not really clear in the current
- 00:05:30 code over here on the right side that
- 00:05:31 that's what it's actually doing so let's
- 00:05:34 make this a draw method of our player
- 00:05:36 class so we can do def draw then we can
- 00:05:41 pass in self and we also need to pass in
- 00:05:45 as you can see here at a screen so I'm
- 00:05:48 going to pass in a screen to this method
- 00:05:50 and everything else that's the color
- 00:05:53 maybe we have the color as a property of
- 00:05:56 our player so we'll say the default is
- 00:05:58 red self dot color equals color and
- 00:06:07 talking about draw it at rect and then
- 00:06:10 this looks like X this is y and then
- 00:06:13 these last two things are player size
- 00:06:15 and player size so we can use self to
- 00:06:18 get all this information so this is what
- 00:06:20 the new function is going to look like
- 00:06:22 we're gonna have pi game dot draw dot
- 00:06:27 rect
- 00:06:29 whenever you use the screen that we pass
- 00:06:31 into this class method I'm gonna do self
- 00:06:35 dot color and then we're gonna pass in
- 00:06:37 self dot X self dot Y self dot sighs
- 00:06:43 self dot sighs and with this right here
- 00:06:49 we've completely replicated the behavior
- 00:06:53 and this method down here on the right
- 00:06:55 but now it's gonna be a lot simpler when
- 00:06:57 we're drawing our actual player because
- 00:06:59 we can just do dot draw instead of Pi
- 00:07:02 game draw rect etc and one thing I'm
- 00:07:04 gonna do I think it might make things
- 00:07:06 more clear as we go along to figure out
- 00:07:08 what our remaining items are is I'm
- 00:07:09 gonna comment things out that we've kind
- 00:07:11 of addressed in our new refactor alright
- 00:07:15 next let's add I guess the detect
- 00:07:19 collision method that I mentioned
- 00:07:21 earlier into our player method over here
- 00:07:24 on the left so I'm going to draw make
- 00:07:27 another class method so we have def
- 00:07:30 detects collision and it's gonna take
- 00:07:33 itself and then it's going to now take
- 00:07:37 in instead of an enemy position will
- 00:07:39 actually take in an enemy and so because
- 00:07:42 we don't know if it's necessarily gonna
- 00:07:44 be an enemy we want this kind of be
- 00:07:45 generic to any player I'm going to just
- 00:07:46 call this other and so what it's gonna
- 00:07:50 look like now well these initial px
- 00:07:54 player act player y enemy acts enemy y
- 00:07:57 these now are encapsulated in our
- 00:07:59 classes right here so we don't need to
- 00:08:01 actually set these like we did here and
- 00:08:02 then this method down here it can be
- 00:08:05 replicated exactly but we just will need
- 00:08:08 to reference our classes instead of the
- 00:08:12 variables here so what does that look
- 00:08:15 like well we have if so if enemy X in
- 00:08:22 this case is other X is greater than or
- 00:08:24 equal to self dot X so we're just
- 00:08:28 basically replacing enemy acts with
- 00:08:30 other node X and player X with self dot
- 00:08:33 X well I'm gonna run through this kind
- 00:08:35 of quickly and if you don't understand
- 00:08:36 why what this collision method is doing
- 00:08:39 again of a good excellent
- 00:08:40 in the original video so check that out
- 00:08:42 right so if other dot X is greater than
- 00:08:46 equal to self dot X and other dot X is
- 00:08:51 less than self dot X plus self dot size
- 00:08:56 that's the first condition or self dot X
- 00:09:00 now we're just doing the reverse is
- 00:09:02 greater than or equal to other dot X and
- 00:09:06 self dot X is less than so it has to be
- 00:09:10 one or the others for the collision
- 00:09:11 happened other dot X plus other dot size
- 00:09:15 okay that's our first if condition and
- 00:09:18 then we need not one of those conditions
- 00:09:20 to be true so the x's need to overlap
- 00:09:23 now we also need the Y's to overlap
- 00:09:25 other dot y is greater than or equal to
- 00:09:29 self dot y and other dot y is less than
- 00:09:34 self dot y plus self dot size or self
- 00:09:43 dot Y now it's the reverse greater than
- 00:09:46 equal to other dot Y and self dot y is
- 00:09:50 less than other dot y plus self dot size
- 00:09:56 if that's the case we want to return
- 00:09:58 true and otherwise we return false
- 00:10:11 and so just to be clear these if
- 00:10:14 conditions are checking to see if we
- 00:10:16 have both an x overlap and a y overlap
- 00:10:18 if you have both overlaps then we know
- 00:10:20 the objects collide otherwise they don't
- 00:10:23 and we return false and now we can go
- 00:10:26 ahead and comment out this stuff here
- 00:10:30 because I can't fit everything on the
- 00:10:32 screen always here I also have the
- 00:10:35 finished refactored code I'll put that
- 00:10:37 on my github too so check there if you
- 00:10:40 kind of are getting annoyed that things
- 00:10:41 are getting clipped off in this video
- 00:10:43 all right next we're going to extend our
- 00:10:45 player class to include enemies as well
- 00:10:49 so we'll make a subclass of the player
- 00:10:51 class so this is going to take from the
- 00:10:55 player class enemy and we'll initialize
- 00:10:59 this with some parameters so sell X Y
- 00:11:05 size we can say let's define two types
- 00:11:08 of enemies that's defining normal enemy
- 00:11:10 which will have size equal 50 and a
- 00:11:13 color of blue and real quick I just
- 00:11:16 realized that I don't think I listed
- 00:11:19 these colors as like plaintext they're
- 00:11:21 listed in RGB form so let's pass in the
- 00:11:25 RGB forms and even actually taking in
- 00:11:28 another aside let's actually create a
- 00:11:30 class for these colors and we can always
- 00:11:32 add to this class that we need to just
- 00:11:34 going to make another new file real real
- 00:11:36 quick and this is gonna be called color
- 00:11:40 dot py I was going to make this class
- 00:11:43 class color and I'm just basically
- 00:11:47 pasting these values here and I'm not
- 00:11:53 actually going to initialize anything
- 00:11:55 because this is kind of a static class
- 00:11:57 but okay so we have these colors and now
- 00:12:00 in this player class we can read these
- 00:12:03 colors by doing from color import or
- 00:12:07 sorry from lower case color because the
- 00:12:10 file name is color with lower case c
- 00:12:12 import the color class and so now we can
- 00:12:17 do color dot red here
- 00:12:27 and when we want to do the super class
- 00:12:31 or the sub class you new color blue and
- 00:12:35 this just makes sure that we don't
- 00:12:37 accidentally type in the wrong value if
- 00:12:38 we're like moving these colors around in
- 00:12:41 different spots and to finish the
- 00:12:44 initialization we don't have really you
- 00:12:46 know the draw and the detect collision
- 00:12:48 are gonna be the same as the normal
- 00:12:52 player class so we can just do super dot
- 00:12:54 a knit X Y size and color and actually a
- 00:13:11 quick update I want to make is I want
- 00:13:13 you only to be able to specify X&Y here
- 00:13:16 so by passing in these to the init I
- 00:13:19 allow you to also specify the color
- 00:13:20 Anatomy but really what we wanted me to
- 00:13:23 be is a more restricted version of the
- 00:13:28 player class so that all you can set is
- 00:13:31 the x and y parameters so I'm gonna
- 00:13:34 actually set in the super init the
- 00:13:37 required colors of the super class
- 00:13:40 player color dot blue and we can make
- 00:13:45 another one of these let's say we wanted
- 00:13:47 to have in addition to an enemy we
- 00:13:49 wanted to have a large enemy class so
- 00:13:55 maybe all the changes between the enemy
- 00:13:58 and large enemy is that the size is 100
- 00:14:01 if a large enemy but the color is the
- 00:14:03 same and then finally let's make a human
- 00:14:06 player class and we'll have that be the
- 00:14:09 same size as the normal enemy but we'll
- 00:14:13 have the color be defaulted to red so
- 00:14:16 now we can call these in another file
- 00:14:18 and just specify the x and y and get
- 00:14:21 them to build a player class through the
- 00:14:24 super class all right so now in our
- 00:14:27 refactor code we have our player in
- 00:14:29 enemy classes we have a class for color
- 00:14:31 so I'm going to just comment this out to
- 00:14:33 let me know
- 00:14:34 I have done it what else do we need to
- 00:14:36 add while looking through our code here
- 00:14:38 on the right side we need to add all the
- 00:14:41 visuals for a game so the width height
- 00:14:44 screen etc and we also need to add all
- 00:14:48 the game logic so let's create two new
- 00:14:50 files so I'm gonna do the first file I'm
- 00:14:53 going to call it screen dot py and so
- 00:15:00 that's going to handle all the visuals
- 00:15:01 so we'll create a screen class and also
- 00:15:06 while we're at it let's define another
- 00:15:10 new file and we'll call this up this
- 00:15:13 next new file the game py file and this
- 00:15:18 will encapsulate all the game logic so
- 00:15:21 in things that actually make the game
- 00:15:23 work but not are not visual so we'll
- 00:15:26 call this class game and now basically
- 00:15:30 we're going to go through our code and
- 00:15:31 figure out what should be in screen or
- 00:15:34 what should be in game so let's do that
- 00:15:37 well first off our screen is going to
- 00:15:40 take in these width and height so let's
- 00:15:42 set the anit here and also I just want
- 00:15:46 to say real quick I'm kind of going
- 00:15:48 about this in a way where I'm
- 00:15:49 refactoring everything then testing
- 00:15:51 another way you could do this is kind of
- 00:15:53 make smaller factors so maybe you change
- 00:15:55 player and then you actually update your
- 00:15:58 game to use that newly created player
- 00:16:01 class but what I'm going to do in this
- 00:16:03 video is just go through all the changes
- 00:16:06 at once and then kind of adapt my final
- 00:16:11 game loop to use all those changes and
- 00:16:13 fix any bugs I might have run into along
- 00:16:16 the way at once at the end so class
- 00:16:20 screen and we're going to knit when you
- 00:16:23 start with self and now let's start with
- 00:16:25 width and height
- 00:16:32 what else does our visual have so I also
- 00:16:35 might just define these to start as 800
- 00:16:39 and 600 does the adult default
- 00:16:41 parameters maybe we give everything in
- 00:16:43 our screen default parameters so that
- 00:16:45 all we have to do is call screen but if
- 00:16:47 we wanted to specify different things we
- 00:16:49 could and that will make sense kind of
- 00:16:52 once we actually start testing what else
- 00:16:55 does this screen need okay so it does
- 00:16:59 some initial so it does some additional
- 00:17:04 initializing here so if I want to
- 00:17:06 incorporate that into our class has a
- 00:17:09 font that probably will want to be
- 00:17:11 incorporated draw enemies will need uh
- 00:17:15 probably make this method part of the
- 00:17:16 screen so maybe I can just do that right
- 00:17:18 now I'm going to just write this down
- 00:17:22 but we'll pass for now
- 00:17:31 and I'm going to start filling in this
- 00:17:33 class self dot with equals with we're
- 00:17:36 just setting the class parameters self
- 00:17:40 dot height equals height okay so what
- 00:17:44 else does our screen need going down to
- 00:17:51 the game loop well it fills in a
- 00:17:54 background color so maybe we should give
- 00:17:55 our game a background color and we'll
- 00:18:02 give that the color you give it this
- 00:18:05 background color color but I'm actually
- 00:18:06 named this black because it's a little
- 00:18:08 bit more clear so in our screen file
- 00:18:12 we'll want to import or from color
- 00:18:18 import color and our now background
- 00:18:23 color so the default will be color dot
- 00:18:25 black
- 00:18:32 and all right that's the game I think
- 00:18:35 the only other thing I might specify in
- 00:18:37 the screen is to specify the font so if
- 00:18:41 you remember when I played the game the
- 00:18:43 followers in the bottom right corner and
- 00:18:45 it was the text that was keeping track
- 00:18:47 of the score so we'll add to the net
- 00:18:50 font type and we'll give that the
- 00:18:54 default that it has here of mono space
- 00:19:01 and we'll have a font size and that will
- 00:19:05 default to the 35 we have on the right
- 00:19:07 side okay I think that's everything we
- 00:19:11 need to have in there now it's just a
- 00:19:14 matter of actually initializing things
- 00:19:15 properly so the screen needs to use the
- 00:19:18 width and height here so do self dot
- 00:19:20 screen equals PI game dot display dot
- 00:19:25 set mode with alma height so we've taken
- 00:19:34 care of this line basically
- 00:19:43 self dot font is going to equal PI game
- 00:19:48 font assist font of this stuff and I
- 00:19:52 guess this is not within heightened
- 00:19:54 words just width that we defined here
- 00:19:57 and height that we defined here and now
- 00:20:03 mono space we can pass in font type so
- 00:20:07 it's whatever you pass into the class
- 00:20:10 creation method across class
- 00:20:13 initialization method and font size
- 00:20:17 right here okay so we're taking care of
- 00:20:24 this line and I think the only other
- 00:20:27 thing I can think of that we might want
- 00:20:29 to handle on the visual side is this
- 00:20:31 clock it's going to just say self dot
- 00:20:33 clock equals PI game time clock and then
- 00:20:43 maybe we also pass in the refresh rate
- 00:20:45 of that clock so I'll just say self dot
- 00:20:49 clock tick equals clock tick and so
- 00:20:53 maybe this is something we you can
- 00:20:56 specify on our screen so I'll say clock
- 00:20:58 tick and the default of that is thirty
- 00:21:01 okay so what class methods will we need
- 00:21:04 to add to this screen well we need to
- 00:21:07 draw the enemy so that's one we need to
- 00:21:09 refresh the background so that's two
- 00:21:12 we'll want to draw this score label so
- 00:21:15 it's three and we'll also want to draw
- 00:21:19 the player so that's a fourth so what
- 00:21:23 did I just say so I said def refresh
- 00:21:26 background that will just need self and
- 00:21:32 so how did we refresh the background
- 00:21:35 over here well we just do screen dot
- 00:21:37 fill background color so now our screen
- 00:21:40 is accessible through self dot screen as
- 00:21:42 we set here so we do self dot screen dot
- 00:21:46 fill dot or fill and then we pass in
- 00:21:49 self dot background color
- 00:21:52 we can duplicate this behavior in this
- 00:21:55 refresh background function okay now I'm
- 00:21:59 gonna move that above draw animes so I
- 00:22:04 think it's a little bit more clear if we
- 00:22:06 keep drawing enemies in draw player next
- 00:22:09 to each other so draw enemies how we're
- 00:22:14 going to do that so we have the drawing
- 00:22:16 of each function here and what does that
- 00:22:17 do it iterates over the enemies and it
- 00:22:21 does the PI game draw command well we
- 00:22:25 can utilize our player class to help us
- 00:22:28 out here so for enemy in enemy list we
- 00:22:38 can instead of doing PI game about draw
- 00:22:40 direkt now if we assume that this is a
- 00:22:43 enemy type that we defined in the player
- 00:22:46 class here we can do enemy dot draw and
- 00:22:51 pass in the screen to easily draw this
- 00:22:56 so we do enemy dot draw and then we just
- 00:23:00 have to pass in self dot screen and that
- 00:23:05 will take care of the draw enemies
- 00:23:06 function that's cool so now let's do
- 00:23:09 draw player that's going to take itself
- 00:23:14 and then the player and for this one
- 00:23:16 it's pretty straightforward it's
- 00:23:17 literally just player draw self dot
- 00:23:21 screen because we only have a single
- 00:23:22 human player this is a human player
- 00:23:25 we're assuming okay and what else did I
- 00:23:28 say we needed to do I said we wanted to
- 00:23:30 draw the font or the score label that
- 00:23:35 we'll need to take in self and a score
- 00:23:39 value and what does that look like over
- 00:23:43 here but we can probably just copy this
- 00:23:46 in and change it as needed to account
- 00:23:50 for the fact that we have our own font
- 00:23:52 I've already set up so my font that's
- 00:23:56 actually now just self dot font the
- 00:24:00 score is passed into this function and
- 00:24:03 we can do score like this or
- 00:24:05 string not score what might be a nicer
- 00:24:08 way is to use f strings and pass it
- 00:24:12 through like this but the functionality
- 00:24:15 is exactly the same the last thing is
- 00:24:18 now with is self dot width and height is
- 00:24:24 self dot height I don't love that these
- 00:24:32 are just kind of magic variable or magic
- 00:24:35 numbers they're called they're just kind
- 00:24:36 of unclear why they're defined as
- 00:24:38 negative 200 and negative 40 but I'm
- 00:24:41 personally okay with leaving them
- 00:24:43 because I don't think there's a great
- 00:24:46 alternative and this yellow should be
- 00:24:52 the color of the score label so maybe we
- 00:24:55 passed this in as a optional parameter
- 00:24:57 so I'm going to say color and we'll say
- 00:25:01 that the default color is color yellow
- 00:25:03 okay so our score label should now be
- 00:25:06 all set and maybe let's make one more
- 00:25:10 function that we just kind of put all
- 00:25:15 these things together so kind of like we
- 00:25:18 do in this loop we'll just lump all
- 00:25:20 these into a update screen method so
- 00:25:25 this is going to take itself an enemy
- 00:25:27 list player and the score and it's going
- 00:25:31 to just call each of these methods in
- 00:25:34 the correct order so to call refresh
- 00:25:39 background we do self to refresh
- 00:25:41 background to call draw enemies we do
- 00:25:44 draw enemies and then we pass in the
- 00:25:46 enemy you list
- 00:25:50 ha player will be next and will pass in
- 00:25:54 the player that we have to find in our
- 00:25:55 function self dot draw scorer label next
- 00:26:02 we'll pass in the score and then the
- 00:26:09 last things we do in our update screen
- 00:26:11 over here is we do clock tick 30 so we
- 00:26:16 have a clock now so we'll do claw self
- 00:26:18 dot clock dot tick and we'll pass in
- 00:26:22 self dot clock tick because that's the
- 00:26:25 30 value we defined and we'll also call
- 00:26:28 the PI game dot display to update so now
- 00:26:38 we've kind of handled this stuff in our
- 00:26:41 new code I think we've kind of defined
- 00:26:44 handle draw enemies we've handled this
- 00:26:49 in our updated code and I'm just as a
- 00:26:52 reminder I'm commenting stuff out that
- 00:26:54 we've kind of handled in the new
- 00:26:57 refactor code just to kind of remind me
- 00:26:59 of where we're at progress wise all
- 00:27:02 right now that we've finished up our
- 00:27:03 screen the last class we have to
- 00:27:05 implement is our game class so that will
- 00:27:07 take care of all the like speed logic it
- 00:27:10 will take care of these functions that
- 00:27:12 we have left over etc so let's start out
- 00:27:15 by initializing it so the first things I
- 00:27:17 think we should initialize to our game
- 00:27:19 class are probably the speed and the
- 00:27:20 score def NIT
- 00:27:29 the new self speed score we'll start
- 00:27:36 with that and we'll probably have to add
- 00:27:38 additional things as we go so
- 00:27:39 self-taught speed equals speed and
- 00:27:43 self-taught score equals score okay so
- 00:27:47 when we're playing our game the first
- 00:27:48 thing is to actually drop an enemy from
- 00:27:50 the top of the screen so I think the
- 00:27:52 first function that we should fill out
- 00:27:54 is drop enemy's so we'll make this a
- 00:27:58 class method so drop enemy's it's gonna
- 00:28:02 take himself it's gonna need to take in
- 00:28:04 this enemy list and what else will it
- 00:28:09 need to take in with so maybe the screen
- 00:28:14 width so self enemy list and the screen
- 00:28:19 width start with that so this uses the
- 00:28:25 random library to stagger things a bit
- 00:28:27 so we'll use that too so we can import
- 00:28:30 that to our game so import random and we
- 00:28:36 can start filling this out I want to try
- 00:28:37 to do this as quick as possible delay
- 00:28:38 equals random random cool and then I'm
- 00:28:43 going to just copy in this code and
- 00:28:44 tweak it as needed so you can see this
- 00:28:48 we're going to copy in this code okay so
- 00:28:51 if length enemy list is less than 10 and
- 00:28:53 these primaries you can play around with
- 00:28:55 so if you wanted to maybe make the
- 00:28:57 number of enemies a parameter maybe we
- 00:28:58 could also pass that in so max enemies
- 00:29:03 equals 10 by default but that could be
- 00:29:07 changed so self dot Max enemies equals
- 00:29:11 Max enemies so if length enemy list is
- 00:29:17 less than self dot Max enemies and delay
- 00:29:21 is less than zero point line so this is
- 00:29:26 kind of how what percentage we're
- 00:29:28 staggering it so the lower we make this
- 00:29:30 the more staggered they probably will be
- 00:29:32 because this is kind of dependent on
- 00:29:34 this method here so if we wanted to have
- 00:29:39 flexibility with that we can all
- 00:29:40 bring it up into our class
- 00:29:42 initialization self dot delay equals
- 00:29:49 delay okay so what we're doing is we're
- 00:29:59 picking a random exposition that's
- 00:30:01 within the screen size so now instead of
- 00:30:03 doing with minus enemy size we can do
- 00:30:05 and I'm going to simplify this a little
- 00:30:07 bit just because we don't know what the
- 00:30:09 enemy size is going to be in our
- 00:30:10 function based on how we initialize
- 00:30:12 things so I'm just going to say that
- 00:30:13 this is screen width so it might have
- 00:30:17 some stuff a little bit off the screen
- 00:30:19 depending on where it places that
- 00:30:21 top-left corner of the enemy but I think
- 00:30:23 this is okay Y position zero that's fine
- 00:30:26 and now an enemy list instead of
- 00:30:29 appending just an x position in a Y
- 00:30:30 position what we want to do is create a
- 00:30:33 new enemy so I'm going to say enemy
- 00:30:35 equals enemy X y or x position Y
- 00:30:43 position and from our player class we're
- 00:30:47 gonna have to import enemy so from
- 00:30:49 player import enemy the new enemy and
- 00:30:55 we're going to end append that enemy to
- 00:30:57 the enemy list and just because we're
- 00:30:59 going to want to be able to pass this
- 00:31:00 enemy list around throughout our game
- 00:31:02 I'm gonna take out this enemy list and
- 00:31:05 just initialize it to be empty at the
- 00:31:08 start of the game and then you can just
- 00:31:10 directly modify that empty lists
- 00:31:13 throughout the game so now this is going
- 00:31:15 to be self dot append enemy list or self
- 00:31:20 enemy list snot append to enemy and to
- 00:31:22 clean this up a little bit I might just
- 00:31:24 call this random X because it's a random
- 00:31:28 X position so we're creating a new enemy
- 00:31:30 with a random X and we can comment this
- 00:31:33 out now that we've taken care of it next
- 00:31:36 we might want to do update enemy
- 00:31:37 positions so I'm going to just kind of
- 00:31:40 copy this in and we'll tweak it as
- 00:31:42 needed to use our class so enemy list is
- 00:31:47 now not needed but we still probably do
- 00:31:49 need to pass in that score actually what
- 00:31:51 we don't because that's
- 00:31:52 parameter here too so this can just take
- 00:31:54 itself for index enemy position in a new
- 00:31:59 marine enemy list well we don't need to
- 00:32:00 do this anymore we can just simply do
- 00:32:03 for enemy in self dot enemy list any
- 00:32:10 position one that's now replaced by
- 00:32:13 enemy dot y so this is basically if it's
- 00:32:17 off the screen and I mean position Y and
- 00:32:20 this should be kind of Y is less than
- 00:32:23 height well the height is going to be
- 00:32:25 the screen height so we'll have to pass
- 00:32:28 that and because we're you don't have
- 00:32:29 knowledge of the screen height in our
- 00:32:31 game class we have that in the screen
- 00:32:33 class so screen height any position dot
- 00:32:37 y plus equals speed so this is basically
- 00:32:40 changing the enemy position enemy's
- 00:32:45 y-coordinate by the amount of the speed
- 00:32:48 so the speed is high the enemy position
- 00:32:50 will update a lot if it's low then it'll
- 00:32:52 be slower movement it will update the Y
- 00:32:54 position a little bit and one thing to
- 00:32:56 note here someone brought up in my last
- 00:32:58 classes video is how do you do getters
- 00:33:00 and setters with Python well the nature
- 00:33:03 of Python is there's no like distinguish
- 00:33:05 and there's no distinction between like
- 00:33:08 public and private attributes so this Y
- 00:33:10 is accessible by everyone using the
- 00:33:13 enemy class so we can just directly edit
- 00:33:16 this y value we don't have to do like
- 00:33:18 set Y we can just do enemy dot y plus
- 00:33:21 equals speed directly here in the method
- 00:33:25 and that's us setting it it's fine to
- 00:33:27 just directly do that if you need to be
- 00:33:30 a little bit more specific with logic
- 00:33:33 that's happening when you get or set
- 00:33:34 something there's this property
- 00:33:35 attribute which I'm not going to go into
- 00:33:37 now but I'll link a video on that
- 00:33:39 property attribute for more complex
- 00:33:41 getting and setting but this is what we
- 00:33:43 can do to to set the value here and we
- 00:33:47 can always just get things just like
- 00:33:48 this without having to do a specific get
- 00:33:51 Y method I just wanted to mention that
- 00:33:53 quickly okay so if it's on the screen
- 00:33:56 update the speed if it's off the screen
- 00:33:59 that we want to remove the
- 00:34:00 me from the enemy list so instead of
- 00:34:02 popping things off what I'm gonna do
- 00:34:04 instead is just call this new enemy list
- 00:34:09 and anything that stays in the screen
- 00:34:13 I'll add two new enemy list and anything
- 00:34:23 that's off the screen will just update
- 00:34:24 our score by one and this is just a
- 00:34:29 little bit easier because the whole
- 00:34:31 indexing on lists can get a little bit
- 00:34:33 complex so I feel like this might be a
- 00:34:35 better method myself to have score plus
- 00:34:38 equals one and now we need to update the
- 00:34:42 enemy list and that is that method we
- 00:34:49 don't need to return anything now before
- 00:34:51 we return the score we don't need to
- 00:34:53 actually return the score anymore
- 00:34:55 because we've directly set the score to
- 00:34:57 be one higher in this method by this
- 00:35:01 setter method here okay this is done all
- 00:35:07 right collision check we can do that or
- 00:35:09 set level next what makes more sense I'm
- 00:35:11 going to go ahead and do the set level
- 00:35:13 next so let's paste that in as a class
- 00:35:17 method okay and this one is pretty
- 00:35:21 straightforward to change instead of
- 00:35:23 passing in score and speed we just
- 00:35:25 really need to pass in self and self has
- 00:35:27 access to score in speed it's a self dot
- 00:35:29 score is less than twenty self dot speed
- 00:35:32 equals five and this was just kind of an
- 00:35:35 arbitrary increase in speed as you get
- 00:35:38 higher in higher score you could rewrite
- 00:35:41 this set level method to however you
- 00:35:43 please and one thing that's cool too
- 00:35:48 with the use of classes you could do a
- 00:35:51 game subclass that rewrites this set
- 00:35:54 level function to be whatever you want
- 00:35:56 without changing any of this other logic
- 00:35:58 which is also a very nice feature of
- 00:36:00 classes self dot score is less than
- 00:36:04 sixty
- 00:36:16 and we don't need a return the speed
- 00:36:19 anymore because it is directly updated
- 00:36:22 in our game class I said that set level
- 00:36:25 we can comment that out and look at this
- 00:36:28 we're getting very close to having kind
- 00:36:30 of everything good and actually I just
- 00:36:35 these can have default if you don't want
- 00:36:38 to have to set the speed in score you
- 00:36:40 can set these as default values too so
- 00:36:42 I'm just taking what they were defaulted
- 00:36:44 to in this code that I just commented
- 00:36:46 out all right so the last method I think
- 00:36:50 we had was collision check I'll paste
- 00:36:53 that in and this is just basically
- 00:36:56 figuring out for all enemies in our
- 00:37:00 enemy list whether or not there's any
- 00:37:02 collisions with the human player so we
- 00:37:05 can just take itself here and maybe the
- 00:37:08 the player for enemy positions so for
- 00:37:13 enemy in enemy list if detect collision
- 00:37:16 between the well now we can just do how
- 00:37:20 did we write our our collision check
- 00:37:23 method or detect collision method in
- 00:37:25 player that was this so it can just be
- 00:37:31 called with on the player class and
- 00:37:35 passing any other so we can just do if
- 00:37:38 detect collision and we're now going to
- 00:37:42 just do this as if enemy thought detect
- 00:37:49 collision with the player return true
- 00:37:52 else return false I think that's it this
- 00:37:57 is not player position this is player I
- 00:37:59 think that's it for this one cool and
- 00:38:02 we'll test all this in a sec because I'm
- 00:38:04 sure we're gonna have some bugs but for
- 00:38:06 now looks like we just took care of that
- 00:38:09 last class and our final thing we have
- 00:38:10 to do is make our rewrite our main loop
- 00:38:12 so we'll do that next let's create a new
- 00:38:14 file and we'll call this one main dot py
- 00:38:20 and we can copy in all this
- 00:38:27 over here and now we'll just have to
- 00:38:29 adapt it to user class okay so starting
- 00:38:33 from the top while not game over well we
- 00:38:35 need some sort of game over equals false
- 00:38:40 first okay that takes care of this right
- 00:38:48 here next we need to probably initialize
- 00:38:52 the player here so let's see for event
- 00:38:57 pi game to get it that's all good but
- 00:38:59 right here we should have a player
- 00:39:00 initialized so I'm going to do that
- 00:39:02 player equals human player and we need
- 00:39:08 to get this from our player file so oh I
- 00:39:11 didn't name this human player I need a
- 00:39:13 bit large enemy this was supposed to be
- 00:39:15 human player and we'll have to now
- 00:39:18 import from player import human player
- 00:39:26 okay now we have a human player we
- 00:39:29 should initialize its position somewhere
- 00:39:31 on the screen but we don't know what the
- 00:39:33 screen is yet so probably above this
- 00:39:35 will actually have to initialize a
- 00:39:36 screen so screen equals screen from
- 00:39:45 screen import screen and then we can use
- 00:39:50 this screen to initialize our human
- 00:39:52 players location so we can do screen dot
- 00:39:54 width divided by 2 for the exposition of
- 00:39:59 the human and then for the Y position we
- 00:40:01 should do screen dot height and then we
- 00:40:07 do minus 2 times player size over here
- 00:40:09 but we don't know what the player size
- 00:40:10 is without like you know mainly checking
- 00:40:14 the value of human player so I'm going
- 00:40:17 to just kind of hard code in a 100 here
- 00:40:19 so it's a little bit it's not at the
- 00:40:21 very bottom of the screen it's a little
- 00:40:22 bit above and you can play around with
- 00:40:25 this 100 value okay so that's the player
- 00:40:28 cool let's start factoring that in x and
- 00:40:33 y are no longer needed we can just use X
- 00:40:36 minus equals
- 00:40:38 player dot size player dot size and
- 00:40:46 we're now directly editing the players
- 00:40:49 exposition we're setting it here player
- 00:40:54 dot X and as I mentioned before we're
- 00:40:56 fine and Python to directly set just
- 00:41:00 directly accessing this attribute other
- 00:41:03 languages you probably made a setter
- 00:41:04 method player position that's now
- 00:41:07 already taken care of
- 00:41:09 cool one thing to note if you're on Mac
- 00:41:13 you might have to do import OS instead
- 00:41:17 I've imports this and I should probably
- 00:41:18 import that import sis so I think on Mac
- 00:41:22 you do OS exit but for Windows and Linux
- 00:41:25 I think it's fine to do assist on exit
- 00:41:28 okay now we need to start updating the
- 00:41:31 dropping the enemies and whatnot so we
- 00:41:33 need a game as well okay and so now we
- 00:41:41 can do we look down over here we can
- 00:41:50 drop the enemies so game dot drop
- 00:41:54 enemies and then we had to pass into our
- 00:41:56 drop enemies let's remind ourselves drop
- 00:41:59 enemies the screen width so we could do
- 00:42:01 screen dot width then we updated the
- 00:42:06 enemy positions I believe and that's now
- 00:42:10 called by game update enemy positions
- 00:42:13 just need to pass in this or an idle
- 00:42:15 actually path pass it anything here
- 00:42:19 other than the let's check one more time
- 00:42:22 the screen height
- 00:42:29 set level that's called by game not set
- 00:42:33 level and I think this one you don't
- 00:42:34 need to pass anything in cool so we've
- 00:42:38 accounted for all this logic kind of in
- 00:42:41 here now we need to start updating the
- 00:42:45 screen so we can just simply call the
- 00:42:50 screen dot update screen method that
- 00:42:52 takes in the enemy list so self dot game
- 00:42:56 dot or actually sorry not self psyche
- 00:42:59 game enemy list then it takes in the
- 00:43:05 player so that's just called player here
- 00:43:08 and then it takes in the score game dot
- 00:43:13 score right okay update screen that
- 00:43:17 looks good
- 00:43:18 if collision check collision check is
- 00:43:21 written differently now it's game dot
- 00:43:25 collision check and then you pass in the
- 00:43:30 player game where equals true yep that
- 00:43:35 looks good is everything good here I
- 00:43:37 think it might be one way to test it and
- 00:43:39 that's just to run the code my game is
- 00:43:47 not defined in screen ok so my game dot
- 00:43:51 display doesn't know how to deal with
- 00:43:52 that so we need to import my game here
- 00:43:54 so we're now we're trying to run into
- 00:43:57 some errors but we'll just work our way
- 00:43:58 through that ah we got a little farther
- 00:44:01 it looked like fought not initialized so
- 00:44:04 what did we not do in this code that we
- 00:44:07 did over here
- 00:44:07 one thing I immediately see is a PI game
- 00:44:10 down it so maybe we should add that to
- 00:44:15 the top of our code here just like we
- 00:44:18 had it in the top of our original code
- 00:44:21 PI game is not defined huh ok now we
- 00:44:24 need PI game here as well
- 00:44:29 okay we got all the way to this file
- 00:44:31 what do we need here game is not defined
- 00:44:36 we just defined it game is not define oh
- 00:44:40 it's because we didn't import it here
- 00:44:42 from game import game oh wow we got the
- 00:44:49 drop enemy's enemy list is not defined
- 00:44:52 and drop enemies that's in the game okay
- 00:44:56 so this is now self dot analysts did I
- 00:45:00 think that's good run our main again
- 00:45:04 screen dot uh page screen PI game is not
- 00:45:07 defined in screen ok we defined it name
- 00:45:12 play game to draw okay it's in the
- 00:45:15 player dot draw so it looks like it's
- 00:45:18 actually coming from the player class
- 00:45:21 that we need it import by game run main
- 00:45:30 come on we're so close
- 00:45:33 screen is not defined here screened lit
- 00:45:38 screened off UI so this is self dot
- 00:45:45 screen we're working our way through
- 00:45:48 them uh we saw a red thing that's good
- 00:45:53 enemy list is not defined in game dot
- 00:45:56 collision check ok self dot enemy list
- 00:46:06 Hey
- 00:46:09 is their score increasing yes yes yes
- 00:46:13 I think we've successfully refactor our
- 00:46:17 game this is also alright yeah that
- 00:46:19 looks good to me a couple small tweaks I
- 00:46:22 might make is let's pull out this stuff
- 00:46:25 right in here into its own function
- 00:46:28 showing on I'm gonna call this def play
- 00:46:32 game and so I need to just indent this
- 00:46:40 properly okay so let's play game
- 00:46:46 it now needs to take in a player a game
- 00:46:52 and a screen and two kind of I guess
- 00:47:00 organize it logically to how we
- 00:47:02 initialize these things I can say screen
- 00:47:07 player game okay so now we have the play
- 00:47:13 game method and now one thing I
- 00:47:15 recommend you do whenever you're running
- 00:47:17 code or have code that's executable is
- 00:47:19 actually surround it in the if name
- 00:47:24 equals equals main cuts and so basically
- 00:47:32 what this line does you'll see this all
- 00:47:34 over the place when you're looking at
- 00:47:35 Python code is it only allows this code
- 00:47:38 to be executed if you're actually
- 00:47:39 running main py and why that's useful is
- 00:47:43 that we can now write other files that
- 00:47:46 use play game and not have this code
- 00:47:49 execute and so one reason we might want
- 00:47:52 to use this in other files is let's say
- 00:47:54 we want to write a couple other levels
- 00:47:57 of this game so maybe a more difficult
- 00:47:58 level or maybe two or three more
- 00:48:00 difficult levels we can still use the
- 00:48:02 same play game and I'm going to show
- 00:48:04 that to end this video but does it still
- 00:48:07 wrong
- 00:48:16 looks good to me
- 00:48:26 all right let's create a new folder
- 00:48:28 called levels and in that we can define
- 00:48:34 a new file and I'll just call this level
- 00:48:39 2 py and we'll utilize our existing code
- 00:48:43 to make this happen okay so from main
- 00:48:46 dot py will want to copy in this main
- 00:48:50 code and then we'll want to basically
- 00:48:56 import all the same stuff and we'll also
- 00:49:03 need to now from main import play game
- 00:49:08 so we can access this function down here
- 00:49:11 so as is level 2 should run let's see if
- 00:49:14 it does know module named player and the
- 00:49:18 issue here is that it's looking at the
- 00:49:20 levels folder for player but now that's
- 00:49:22 one directory above so what we can do is
- 00:49:24 sip a thought insert this is basically
- 00:49:28 telling our machine to look one
- 00:49:30 directory higher to find these files so
- 00:49:34 I'm going to do that real quick and now
- 00:49:35 run it ok like that so our game works so
- 00:49:40 how do we want to define this level to
- 00:49:42 be more difficult so one way we could do
- 00:49:44 this is by making a like subclass of
- 00:49:47 game we could either just directly pass
- 00:49:48 in some parameters of the game that
- 00:49:49 makes it more difficult so or maybe like
- 00:49:52 to the screen that makes it more
- 00:49:53 difficult so we could like you know make
- 00:49:56 max enemies 20 that'd be a that would be
- 00:49:58 an easy way to do it
- 00:49:59 so let's try that real quick
- 00:50:10 it's already you'll see that there's
- 00:50:12 gonna be more enemies than there ever
- 00:50:13 was before so that's one way to make the
- 00:50:17 game more difficult and this will
- 00:50:18 definitely get harder as the speed ramps
- 00:50:22 up so that's one thing we could even
- 00:50:27 like change up the enemy that we're
- 00:50:29 dropping so if we go to game I'm going
- 00:50:32 to define a new class of game called
- 00:50:36 class hard game and that's going to be a
- 00:50:40 subclass of game and what we're going to
- 00:50:44 do here is just change up this enemy
- 00:50:47 that we're using here so I'm going to
- 00:50:48 bring out the enemy I want to say enemy
- 00:50:51 I'm gonna make this a class variable as
- 00:50:55 opposed to like an instance variable
- 00:50:57 that all these are defined us so we're
- 00:51:00 just say enemy equals enemy and
- 00:51:03 basically what this is doing is setting
- 00:51:06 self dot enemy so even though I'm not in
- 00:51:09 this in it if I define this class
- 00:51:12 variable we'll be able to access it by
- 00:51:15 doing self dot enemy and now what this
- 00:51:20 allows us to do is the code will still
- 00:51:23 rod maybe not oh oops I didn't pass
- 00:51:30 anything in here so what I'm going to do
- 00:51:34 is say enemy here is equal to large
- 00:51:37 enemy and we defined large enemy in our
- 00:51:39 player class over here so now I'll need
- 00:51:45 to import that into game enemy and large
- 00:51:49 enemy okay so all I change was enemy
- 00:51:54 equals large enemy here
- 00:51:55 an enemy equals enemy here and we're
- 00:51:58 taking enemy and large and me from this
- 00:52:00 and setting it here so in level two
- 00:52:04 right now it's the same game we've got
- 00:52:06 that enemy that is you know size 50
- 00:52:10 right now what happens is now if I use
- 00:52:13 that subclass hard game
- 00:52:18 it breaks hard game is not to find
- 00:52:22 harder game here
- 00:52:30 so right now we already have level two
- 00:52:32 which is these oh my gosh I just screwed
- 00:52:34 myself over maybe we don't make max
- 00:52:36 enemies 20 here but we just created a
- 00:52:40 new version of the game using our class
- 00:52:42 very very easily and we could easily
- 00:52:45 extend that hard game even further by
- 00:52:48 maybe rewriting the cell set level
- 00:52:50 function in the hard games I could say
- 00:52:52 def set level here it takes himself and
- 00:52:57 then maybe instead of having these kind
- 00:53:00 of different levels based on the score
- 00:53:03 like kind of hard-coded levels we just
- 00:53:05 make it a always increasing self dot
- 00:53:09 score or self dot speed equals that say
- 00:53:14 self dot score divided by five and
- 00:53:16 because the score is initialized to zero
- 00:53:18 let's make this self dot score divided
- 00:53:20 by five plus one so this also is
- 00:53:23 changing up how we set the level it's
- 00:53:26 going to always be increasing and that
- 00:53:30 will be factored into hard game without
- 00:53:31 having to make any other changes so
- 00:53:33 that's like one of the beauties of
- 00:53:34 classes we can make a change in one
- 00:53:36 place and it doesn't break the code
- 00:53:38 everywhere else so look it it's starting
- 00:53:43 really slow all these are lumped
- 00:53:45 together and you know maybe I change
- 00:53:48 this up a little bit but once I get by
- 00:53:51 this first set of blocks here you'll see
- 00:53:55 it rapidly start increasing come on get
- 00:54:01 off the screen get off the screen okay
- 00:54:03 and now we've already gotten oh my gosh
- 00:54:04 however I have a secret here I can get
- 00:54:07 off the screen and block this
- 00:54:09 temporarily I got really unlucky there
- 00:54:11 but everything kind of is increasing
- 00:54:13 there so that looks pretty cool and to
- 00:54:16 block this the little cheat I just did
- 00:54:19 this is something that everyone asked me
- 00:54:21 on the original video in your event I
- 00:54:25 keep I game dot left you could add the
- 00:54:27 statement it only go left if you are
- 00:54:30 greater than if your player dot X is
- 00:54:34 greater than zero so you can't go left
- 00:54:40 off the screen basically it won't work
- 00:54:42 and only go right if you're play
- 00:54:44 they're dot X is less than or equal to
- 00:54:50 the screen width minus the player size
- 00:54:57 no quick I'll just show that now oh I
- 00:55:00 guess I can still get off the screen I
- 00:55:02 screwed something up elsif player can
- 00:55:07 only go right
- 00:55:08 oh is sorry is greater than or equal I
- 00:55:17 maybe I screwed it up because this
- 00:55:19 should be in parentheses
- 00:55:28 can I go left off the screen I can't go
- 00:55:30 left off the screen now and I just might
- 00:55:33 need to fix this right along a little
- 00:55:35 bit okay yeah I can't go once I added
- 00:55:38 that parenthesis it works okay so now I
- 00:55:41 can't go off the screen so I can't cheat
- 00:55:42 like I did all right let's finish this
- 00:55:46 game off with one more level we'll say
- 00:55:47 that this is the boss level so I'm gonna
- 00:55:53 just call this boss level we basically
- 00:55:56 copy all the code from level 2 here into
- 00:56:00 boss level but now let's make it
- 00:56:02 obviously be called boss level of UI so
- 00:56:09 we can copy all the code from level 2
- 00:56:11 into boss level but now let's have a
- 00:56:13 little bit of fun with this and instead
- 00:56:15 of the hard game being defined let's
- 00:56:18 define kind of the boss game so in game
- 00:56:21 we're going to find class boss game and
- 00:56:30 the enemy here is where we're gonna get
- 00:56:32 fun I'm gonna say that this is called
- 00:56:33 the Keith's enemy so we're going to find
- 00:56:36 the Keith's enemy so in player we're
- 00:56:40 gonna find one more enemy and it's gonna
- 00:56:42 be called class Keith's enemy you can
- 00:56:47 initialize the same stuff the color and
- 00:56:51 stuff won't actually really matter here
- 00:56:53 but you'll see in a sec what I'm gonna
- 00:56:55 do okay so what we're gonna do here and
- 00:57:00 the Keith's enemy is I'm going to
- 00:57:02 rewrite the draw method and instead of
- 00:57:05 drawing a square I'm gonna have it pass
- 00:57:08 in an image of my face so it's
- 00:57:12 initialize the same way but this time
- 00:57:15 it's going to you know draw an image of
- 00:57:17 my face and I'm not going to go through
- 00:57:20 the details of how this code works but
- 00:57:23 I'll show you that it does work and you
- 00:57:25 can copy it into your own files but
- 00:57:27 basically we define a rectangle we have
- 00:57:30 an image so we need to find an image
- 00:57:31 I'll define an image on the outside as
- 00:57:34 in class variable maybe pygame dot image
- 00:57:39 dot load and I need to have an image
- 00:57:42 so I'm gonna create a little folder here
- 00:57:45 called
- 00:57:46 assets this is a good place if you want
- 00:57:48 to have multiple pictures to store them
- 00:57:50 and then I'm gonna take a selfie that I
- 00:57:53 just took I'm gonna move that into
- 00:57:57 assets I don't know if I can do it like
- 00:57:58 this
- 00:57:59 oh my god okay I'm gonna just do it okay
- 00:58:04 here's the selfie copy this and I'm
- 00:58:09 gonna find my assets folder and I'll
- 00:58:14 paste it in here
- 00:58:16 cool now I have selfie JPEG so that's
- 00:58:19 gonna be the path to that is dot slash
- 00:58:23 or actually might be up Wondrich already
- 00:58:26 know yeah its dot slash assets slash
- 00:58:32 selfie dot jpg cool cool and so now we
- 00:58:40 can define our hard game with the
- 00:58:43 Keith's enemy and we'll give you a we
- 00:58:49 have a size 100 that sounds good to me
- 00:58:51 now we can define our hard gate or boss
- 00:58:53 level with the boss game class and let's
- 00:59:00 see what happens
- 00:59:07 alright will it no oh
- 00:59:12 human Claire what's the air here
- 00:59:15 couldn't open assets that selfie so the
- 00:59:19 issue here is that it's getting all
- 00:59:21 confused because our levels directory is
- 00:59:23 not the same directory as assets so the
- 00:59:27 dot slash is saying current directory –
- 00:59:29 assets isn't there's no assets in the
- 00:59:31 levels folder so as a quick easy fix to
- 00:59:34 this what we can do in player is
- 00:59:36 actually paste in the full path so I can
- 00:59:40 get the full path on my windows by
- 00:59:42 clicking the folder icon when I'm here
- 00:59:45 so if I paste in this this is the
- 00:59:49 absolute path so it is and I might have
- 00:59:52 to make these other slash it direction
- 00:59:56 so no matter it doesn't look at relative
- 00:59:59 paths it just absolutely knows that this
- 01:00:01 is the file location on my computer and
- 01:00:03 its assets slash selfie JPEG okay so I
- 01:00:08 can rerun boss level now maybe not
- 01:00:13 Keith's enemy is not defined in boss
- 01:00:17 game so I need a import key that I'm
- 01:00:20 here okay look at that now it's just
- 01:00:30 selfie Leone selfies with me and so you
- 01:00:33 can have fun with this and make this
- 01:00:35 more difficult as you please maybe to
- 01:00:37 make it a little bit less daunting it's
- 01:00:42 already daunting enough just having my
- 01:00:44 image there so I'll have to change up
- 01:00:45 the difficulty too much but maybe I say
- 01:00:48 that the Keith's enemy has a size of
- 01:00:52 like 75 to make it a little more
- 01:00:58 manageable to pass all of them
- 01:01:03 and if you wanted to you could also like
- 01:01:05 play around with the screen size so
- 01:01:06 width equals 1,000 let's say maybe
- 01:01:09 height equals 1400 so this would make it
- 01:01:13 a bigger screen so I don't know just
- 01:01:18 have fun with these setting these
- 01:01:19 different parameters because we made it
- 01:01:21 all different classes it's a lot easier
- 01:01:23 to to change different things now and I
- 01:01:26 still can't go off the screen which is
- 01:01:27 nice cool I think we're gonna end this
- 01:01:30 video here so in this video we
- 01:01:31 refactored code to be more professional
- 01:01:33 more like it would be written at a
- 01:01:36 software company there's still more
- 01:01:38 changes we could make but I think this
- 01:01:39 is a pretty dang good base for the sake
- 01:01:41 of this video if you have additional
- 01:01:43 thoughts on ways we could make this code
- 01:01:45 even better
- 01:01:46 leave them down in the comments I would
- 01:01:47 love to hear your suggestions and kind
- 01:01:49 of get a discussion going on all this if
- 01:01:52 you enjoyed this video I mean a lot of
- 01:01:53 you throw it a thumbs up and also if you
- 01:01:55 haven't already subscribed I'll be
- 01:01:57 making some new videos very soon so look
- 01:01:59 out for a neural networks tutorial in
- 01:02:02 the next couple weeks and soon after
- 01:02:03 that I'll start working on a another
- 01:02:05 data analysis real-world data analysis
- 01:02:08 video and probably use a cattle
- 01:02:09 challenge for that also if you're
- 01:02:11 interested check me out on the other
- 01:02:12 socials Instagram and Twitter thank you
- 01:02:16 everyone for watching peace out
- 01:02:19 [Music]