Coding

Professional Code Refactor! (Cleaning Python Code & Rewriting it to use Classes)

  • 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]