SPACE INVADERS FROM SCRATCH (PART 2) – CS50 on Twitch, EP. 22

stuff DanCoffeeCCD is Dan Coffee who did a stream last year on Draw 50, which is an awesome tool which we actually used, I think, last Space Invaders stream Is a huge fan of pepperoni pineapple, so if Dan’s looking in the chat, shout-outs to Dan and his pepperoni pineapple pizza I’m not sure if that’s been mentioned– if pepperoni pineapple specifically was mentioned I think just pineapple and pizza generally were mentioned So anyways, back to LOVE.load, which was where we initialized all of our aliens We also initialized our ship And actually, shout-out [? Aslee ?] and Bhavik, who are in the chat right now We, last stream, ended up having a mini war on which ship we wanted to use at the start of the game– the player ship So I think if I run this over and over again, we see right here, this little ship here– this little red ship is going to potentially change to a another ship if I keep running it It’s random Yeah, so right here So I don’t remember offhand which one [? Aslee ?] chose and which one Bhavik chose, but they both had a different ship that they wanted to use, and we ended up using a little math.random two, which just gives you value between one and two And basically, used a ternary– Lua’s ternary statement, which is an and-or– well, a conditional and then an and and an or And then, what we ended up doing was, the game will randomly choose between [? Aslee’s ?] ship and Bhavik’s ship And their ships are just frame indices So if we look at our file here– let me go into Space Invaders, graphics, aliens I think was aliens six– no, it was aliens 12 I believe I’m not 100% I have to re-look and see Was it 12? It might have been Oh yeah, it is 12, because I recognize the ship here Essentially, all of these individual ships on this one texture– this one 2D image– you can split this image up into rectangles, and it’s called using a sprite sheet In LOVE 2D, they’re called quads They’re rectangles that define a sub-image on a 2D image And what we can do is, we can assign each of these an index between one and however many ships there are, counting top to bottom, left to right And by drawing our 2D image in LOVE 2D, and then referencing a quad, we can draw that sub-image And all the quads are– we split it up by 12 by 12 pixels and then put them into a table, so a one-dimensional table And so therefore, it’s from one to– I think this is 1, 2, 3, 4, 5, 6, 7, 8 It’s 16 by 16, 256 ships long So between one and 256 By sending a particular index and then drawing LOVE.graphics.draw, we can draw a particular sub-image And so that’s what we’re doing here We’re getting an index So we calculated the number We figured out what row it was on– 16 times three, and then the sixth one over is 16 times 12 And then, the ninth one over So third row and then the 12th row And that’s effectively how we did that That’s what that bit of code is there fore We instantiate a ship We put it in the middle of the screen, which is what this logic here does– virtual width divided by two, minus alien size divided by two Alien size is, I believe, 12 pixels All of the capitalized things are in constants.Lua Excuse me Constants.Lua is a good place to store constants Constants are just variables that should not change Lua does not enforce using constants, so you have to kind of use programmer, I guess, heuristics in order to use constants appropriately In this case, we do that by capitalizing– as is conventional amongst many programming languages– the variable name, and using underscore notation So anything that we see that follows this variable naming convention we can assume is a constant, and should not be assigned a value, only used read-only in our code In this case, alien size is a constant It is 12 pixels Virtual width and virtual height are the dimensions of our virtual resolutions– so how we make our screen look as if it’s retro, even though it’s not And there are some other ones here– projectile length We don’t have a projectile height, but just for good measure, projectile height is one And then, we can use that in the future when we reference that Yeah, Colton being very diplomatic about the ships It’s very important that we embrace everybody’s opinions Well, he multiplied it in a second Someone brushed on math during the holidays Oh yeah, because last year I was not able to, on the fly, figure out what 16 times 16 was And I was made fun of for it It’s 256– something that most programmers should probably know, and I was not included amongst that category of programmers, unfortunately

check to see if they’ve reached that end, and so on and so forth And then, when the do reach either end, they should all move down They should get closer to the player That’s how the game works– the actual Space Invaders game works So I can say if alien direction is equal to right– again, just comparing it directly to the string right, because that’s going to equal either left or right Excuse me And I’m going to preemptively say an else here It can only be right or left, so we don’t need any we don’t need another conditional statement We can just say else What I want to do is, I want to set every single alien’s position to the right just a little bit Well, I should say, I don’t want this to happen every frame I want to actually be on a timer So what I should do is– and do I want this to be using a timer library? Probably not Probably not yet That might be a little bit too much So I’m going to say, alien movement timer is zero And then, I’m going to say, in our constants– I don’t have constants open Constants.Lua, I’m going to set a alien movement interval [MUSIC PLAYING] That startled me a little bit Djoker07, thank you for following That name looks familiar I thought that Djoker was already falling, but if not, I apologize Alien movement interval, I’m going to set that to be– this is in milliseconds Is it in milliseconds? No, I think LOVE 2D measures DT in fractional seconds So let’s say I want the aliens to move every 0.4 seconds And again, this is a constant This isn’t going to change I could make this a variable that does change if I wanted the aliens to move faster the closer they get to the player, which is kind of, I think, how it works in– no, that’s not how it works in Centipede I don’t think so I think it just looks like they’re moving faster I don’t remember offhand But basically, it’s going to be a constant in this case And the timer itself is going to keep track of how much time has passed each frame And we’re going to add to it And once alien movement timer is greater than alien movement interval, which means 0.4 seconds have elapsed, then I should move all the aliens to the right or to the left, do the condition to check and see if they’ve reached the edge of the screen And then, I’m going to reset the timer back to zero, or at least back to timer minus alien movement interval, in case they went over 0.4 just a little bit, right? And shout out to David in the chat He says, thanks for tuning in today, everybody Thanks so much for tuning in, as well Djoker07 says, happy new year, Colton Thanks, Djoker, very much appreciate it Everybody’s talking about their amount of RAM– 16 gigs If it’s in idle, it won’t take any RAM, says OneDayMyLove I might be lost in the conversation there Oh, two instances of unity, open, plus one instance of blender And everybody’s saying hello to David Awesome Cool, cool So we have a timer now We can keep track of how much time has elapsed since the last frame We can cumulatively add this until we’ve gone past that amount of time So what I’m going to do is, before I actually– well, I’m going to keep the if statement there, but it’s actually going to be nested within my other if statement I can say, alien movement timer gets a movement timer, plus DT, right? Remember, DT is a variable that we get every frame passed into LOVE.update by the LOVE 2D framework And this is going to be measured in fractional seconds So it’s going to be 0.013, 0.0013 I forget offhand I think it’s 0.013 And if alien movement timer is greater than or equal to the constant that we’ve defined, which is alien movement interval, then– and this is where we nest that bit So I say, if alien direction is equal to right– so they’re going to the right What we need to do is, we need to increase every single alien’s x position, right? So that means we need a loop So I can say, four_alien in pairs, aliens do alien.x is equal to alien.x plus– and then we have to figure out how much we want to move the alien by So I guess we can say, alien size, alien step length We’ll call it that, alien step length And we’ll say that’s going to be five pixels I’m not entirely sure A lot of this you’re going to have to kind of do by feel, too, especially if you’re doing things that are based on time when you’re moving stuff, getting speeds right It’s a little tricky to kind of guess everything correctly right off the bat unless you know your specs in advance

I don’t know the specs advance, so I’m just going to take a guess And then, we can fine tune it as we need to go along And this has a role to play in game balancing, because this movement of the alien x– if it’s too small, the game will be too easy, because the aliens will take a long time to get to the bottom of the screen If it’s too big, the aliens will get to the bottom of the screen really fast, and as a result, it’ll be harder for the player to defeat all of them in time So we need to sort of keep this in mind as we’re balancing the game out– tweak it, play test it, and get a sense of it This is part of the QA testing side of making a game So we’re going to say, alien step length So we have alien.x is equal to alien.x plus alien step length In this pairs function, again, is how you iterate over tables in Lua So it takes in a table, in this case aliens, and will give you every single alien, every single key, and every single object within that– every key value within that table In this case, all the values are aliens– alien objects So we do that here And then, we do the same exact thing here, right? Except instead of setting the alien x equal to alien x plus the step length, we want to minus the step length so they move to the left instead of to the right And again, it’s mirrored to you to To the left, to the right, but I have to think of it the opposite way I can’t see that name It’s in black text WinLogon, happy to be here, taking 650 GD at edX Awesome Thank you so much Well, glad to have you with us WinLogon? WinLogon? I hope I’m pronouncing that correctly I’m probably not Colton’s saying, cool Colton’s sounding Jake Peralta I’m not entirely sure that is I should look that up Cool So this is how we move the aliens on a timer And then, once we have moved all the aliens, we want to set alien movement timer to alien movement timer minus– what’s it called? The alien movement interval That way, in case we do go over 0.4 to, like, 0.41, or something similar to that, it’ll take that into consideration– that overlap into consideration, and we won’t kind of get extra time added to our loop, which is what you do if you just set it to zero and don’t account for that overlap Alien movement timer gets alien movement timer minus alien movement interval That’s great So that’ll roughly be zero, if not 0.01, 0.001, or something like that And that will move the aliens to the right and to the left Now, if we run this, it should work They’ll move So this is roughly what we want things to look like It might be a little fast But notice that when they go to the right edge of the screen, they just keep going forever, because we haven’t actually implemented checking for the edge, right? So that’s something we want to do We want to say, if the far right alien is at the right edge of the screen, then downshift everything down by a few pixels– maybe even the step length, we could do that Or maybe step height, maybe we want to define step height as a separate constant So I can say step height And maybe we want that to be eight pixels, a little bit more than the step width They’re moving a little fast, so I think the interval should maybe be 0.5 seconds We’ll see if that’s any better That should be fine And this is a lot up to your tastes more than anything, so you kind of want to tweak it depending on what you like best So we’ve done that We’ve got the aliens moving Now, we need to actually figure out when the aliens are at the edges of the screen And for that, what we can do is, we’re just going to assume that all the aliens are sort of– even if they are destroyed, they’re there So we can always test the far right alien and we can always test the first alien to be our left and right edges, right? So our alien, or rather our far right alien, is 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11– our 11th alien So we can just kind of know our 11th alien will always be where we can indicate the right side of the screen So I’m going to say, if aliens at 111- so because we added to our table– actually, I’m going to use best practices here I’m not going to use 11, I’m going to use far right alien and far left alien And aliens wide is also the same index as far right alien in this case, but we’re going to separate them just so that our code is more readable

This is important You want to make variables that are readable so we can, at a glance, know that we’re checking the far right alien here We’re not checking some random 11, which doesn’t make any sense I’m just reading it offhand, if you’re not familiar with the code base So if aliens far right alien.x is greater than or equal to– and this is where we want to check to see if it’s at the right edge of the screen, right? So we’re moving right So I want to say, if aliens far right alien.x is greater than or equal to virtual width– that’s the far right edge of the screen– minus alien size, and minus alien size because we want it to be when the right edge of the alien touches virtual width, not the left side of it Remember, everything in LOVE 2D is based on its top left coordinate So if we check for just virtual width, the alien will get all the way to the right side– like, past the right side of the screen before it actually checks the condition We want it to check when the right edge of it touches virtual width, right? So I’m going to say, if aliens far alien.x is greater than or equal to virtual width minus alien size– if the alien is right at the right at the right edge of the screen, this is where we want to set the direction– which the variable is up here It’s alien direction We’re going to say, alien direction is equal to left It’s no longer right We’re no longer moving to the right Now, on the next frame, this is going to be false and this is going to be true And it’s going to tick all the aliens to the left And this process will continue– assuming that we fleshed out this if statement here, this else statement– this will continue infinitely So what we can do is then say, alien direction is equal to left, and this will have the result of– it could be possible that the aliens move slightly past the right edge of the screen and we need a bit of logic to sort of reverse that But we can solve that I guess it’d be fairly easy just to figure out what that difference is, and then subtract that from every alien’s x But we won’t worry about that yet It’s not super important What we’re going to do first is just get the loop working infinitely So in this case, now, we want this to be right So in the else statement, so when they’re moving to the left, we’re going to– we still have it decrementing their position, but now we don’t want far right alien to be tested for We want far left alien to be tested And we want it to be less than or equal to zero, which is the left edge of the screen, not virtual width minus alien size Now, we’re checking to see if the left side of the left alien– the leftmost alien, the first alien– is right at the left edge So if aliens far aliens.x is less than or equal to zero, than alien direction is equal to right So then we’re going to go back to the right And we’re missing one last step, and that is, we want every alien to move down when this happens So what we can say is, again, another loop 4_alien in pairs of aliens, do alien.y equals alien.y plus– and then we just defined it– alien step height here And then, I want to bring this same exact code over here, just like that So if everything is according to plan and my logic is correct, when these aliens reach the far right side of the screen, they should bump down Let’s test and see Yeah, it looks like it jerked a little bit to the right there a little funkily So yeah, that’s the– am I changing all of their things to the right size? I might want to do greater than, not greater than or equal to, so that it doesn’t do that weird sort of diagonal jump Let’s see if that fixes it No, I don’t like how that looks It looks a little bit weird This might be acceptable for now, just in the sake of time 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, boom

from the aliens And it does it with an if-else, so it won’t do them both in the same turn So we do get block movement on the frames– or not the frames, but on the part of the interval where we actually do move the aliens down We don’t move them down and then move at the same time That was the core issue It wasn’t in and if-else Now it’s in an if-else, so that problem is fixed Yeah, essentially what Bhavik said When it reaches either left or right extreme, pause for a time step, go down that time step That’s what we did Yeah, it felt. Awesome Cool So aliens look good now The movement looks good The next step is probably collision, right? So I can move around I can move the ship around and I can shoot, but it doesn’t do anything It actually just goes straight through the aliens through the other side And that’s not ideal behavior So a couple couple of things we want to do As we mentioned earlier, we want the projectiles to be only around as long as they’re visible So when they’ve gone past the top edge of the screen, if they haven’t hit an alien, we want to get rid of them We want to get rid of them if they hit an alien And if we hit an alien, we want not only to get rid of the projectile, but also to get rid of the alien itself So a few steps, a few pieces There’s a long block of code, too– 58 to 86 to do the alien movement We could separate that out, I guess So you can call this, like, tick aliens And then go down to the bottom here Just modularize our functions a little bit, see if it still works, which it should So it’s a good habit to make your update and draw functions kind of as small as you can In this case, we have this big block of code that does something very specific So take aliens We just took it out, made it its own function Now, our code looks a lot more readable We can say, OK, in our update function, we update the ship, we update projectiles We probably can put this in there, as well And then, we tick the aliens So we move the aliens So boom, that’s done Cool Essentially, just a copy-paste out of the update function It’s not better engineered, necessarily, but it’s easier to read It looks a little bit better It’s more easy to keep track of what’s going on You’re not navigating through a monolithic code base to figure out what the functions do When you have functions that you can reference by name, you can also reuse them in multiple places if you wanted to, and mix and match them– puzzle pieces It’s useful OK so now, collision detection with our projectiles So the projectile class, here What we can do is probably define a collides function We want a collides function that works with every entity in the scene, because we want to check to see– I mean, essentially, we only want projectiles and ships to collide with stuff So we could just define a collides function on a projectile that takes in something that has an xy width and height The aliens– do the entity have a width and a height? No, they don’t So in this case, we can probably set self.width is equal to alien size Is alien size the one in– alien size, yeah It’s always going to be 12 But this way, each object has a width and a height now, and we can use that in our collides function So we can go to projectile I’m going to create a new function called collides I’ll do it before update and render And it takes in an entity And this entity is assumed by this function to have an xy width and a height, which is why we just added width and height to entity The ship and the alien will all inherit from entity And therefore, they will all have an xy width and a height So this is aa, bb collision detection I think we covered this in a prior stream I forget offhand which stream it was Maybe somebody in the chat knows which stream we covered it in I remember drawing it– or at least I thought we did Pong, yep, there it is OK Did we cover that in 3D Pong? Did we really do that? I thought for 3D Pong we did Unity’s collision to systems, so we didn’t need to do aa, bb We cover aa, bb in the games course for the G50, but for stream I don’t remember if we covered it

Essentially, check to see whether two rectangles– whether one rectangle’s opposite edge is past the other edge of another rectangle That means that they impossibly cannot collide, and therefore it’s a simple check And it assumes the rectangles are on the same axis They’re not rotated rectangles They’re axis aligned, so completely orthogonal– is that the right word? Perpendicular to the axes, or orthogonal to the axes And therefore, it’s a very inexpensive operation and a very simple operation So I can say if self.x is– and so we’re checking the left side of the rectangle So if the left side of this rectangle– this projectile– is greater than entity.x plus entity width, then that means that this rectangle’s left side is beyond the right edge of another rectangle Therefore, it’s impossible for them to collide, essentially, right? And we do that same logic for all four sides of the rectangle And then, if any of these are true, then there’s no collision Otherwise, there’s a collision So if self.x is greater than entity.x plus entity.width, or self.x plus self.width is less than– that’s the right edge of the projectile If it’s less than the– oh this doesn’t have a width and a height So we need that as well So this needs to have a width So projectile– do I not have projectile width and height defined? Projectile height Oh, that’s not projectile height, that’s width My bad I screwed up the constant in dependencies I called it projectile height It should be projectile width– width and length, which is fine So self.width is projectile width Self.height is projectile length So it’s one and five, respectively– small rectangle If self.x is greater than entity.x plus entity.width, or self.x plus self.width is less than entity.x, or– fairly long if statement– self.y is greater than entity.y plus entity.height– so if this is below the other rectangle– or self.y plus self.height is less than entity.y– above the rectangle– then we want to return false, so it does not collide Else, we return true Both of these For a long if statement, it gets kind of obnoxiously formatted But that’s essentially it Check to see if opposite edges are beyond each other If they are, it’s not a collision If not, it is a collision Cool Simple And now, we can, in our main.Lua, say, for every alien– or I guess for every projectile, rather– projectile update Now, the thing is, if we want to update each projectile so each projectile takes in– it updates, right? So it ticks It says, if the direction is up, move it up Self.y minus projectile speed times all the time And the same thing goes for moving it down, right? So we can update all projectiles And maybe ideally this exists in the update function for a projectile, but it would probably be ideal to do that– from within projectile test a collision against each entity, say, for each entity in the scene do this, blah blah blah What we’re going to do instead is, we’re going to do that in here So we’re going to move every projectile And then, since we have access to all the aliens and the player ship within this function here, since we’re in main.Lua, we’re just going to check collision here in another four loop So we’re going to say, for _alien in aliens, pairs aliens two So we’ve moved the projectile, and now we’re going to say, if– I’m trying to think Because if we do that, we also need to get rid of the projectile

So remember, functions that you declare don’t have access to DT unless they’re called a reference within main So we take DT and we pass it to tick aliens so that tick aliens can do whatever work it needs to do with delta time So boom So now, if I do that, oh, it works Awesome No sound, so will it work with aliens that are beyond– yep That’s so cool It works No sound effects I feel like sound is always a super important aspect of the game, so I want to make some sound effects [? Aslee ?] says, AWESOME, in all caps Yeah It’s pretty cool I’m happy that it worked sort of on the first try I mean, I had a couple of syntax errors, but it works My logic wasn’t wrong That’s the more difficult thing to solve OK, what sounds good? Let’s see Let’s turn this up, turn my sound up little bit So if you’re not familiar, this is VFXR I’m not sure how you pronounce it It’s a sound generation program on Mac and Windows, and I think maybe Linux I’m not 100% sure It just generates sounds using simple sound synthesis, different sound waves that you can use, triangles, sine waves, saw waves, et cetera They even have whistle waves, which is interesting They have some pre-set settings here that are all kind of randomized and tweaked, so it’s super nice I’m going to make a couple sounds So the first one I want to create is, like, shooting, like a laser So they have a laser shoot category here [LASER SHOOTING] I couldn’t hear that [LASER SHOOTING CONTINUES] OK, that was a bit better That might be a little obnoxious I might turn down a little bit What do you think? Does that sound obnoxious? It sounds kind of nice, right? We’ll use that one Where are we at? In here, Space Invaders Oh yeah, VFX doesn’t let you create folders within the interface So it’s sounds, and then export wave, sounds, laser Do the aliens shoot back? Yes Not yet We will implement that Sounds, laser, and then we want something for when we defeat an alien, so explosion [EXPLOSION BOOMS] No, probably not that one [EXPLOSIONS CONTINUE] No That’s a little loud, but if we turn down– a little harsh That sounds OK, right, maybe? That sound is so much like the original Space Invaders, though, the first explosion This one? I, for one, welcome our new alien overlords, says JPGuy Not without a fight You need a short sound for the explosion Yeah, I kind of agree [EXPLOSIONS CONTINUE] Can I speed up the sound? Yeah, it should be sustain time to K time How’s that? They only eat pineapple pizza Yeah, nice OK, we’ll go with that one That’s fine So we’ll just call that one explosion.wav, and we’ll leave that open in case you want to add some new sounds I’m going to go to my dependencies So this is where we have all of our assets, g sounds, this is going to be a new table I’m going to create– a global table That’s why we’re using lowercase g at the beginning of it, because it’s a global We’re not doing that in main.Lua with some of the globals we have, because there is no real fantastic reason, I guess, because they’re all used within– well, they’re not globals, technically speaking, actually They’re all locals that are highest level in main.Lua, but they’re not technically global You can’t access them from other modules You can access them from main.Lua So I guess that’s maybe the reason g sounds equals– this is a new table, so each sound needs a string key So in this case, a laser equals LOVE.audio.new source This is how I declare an audio file, an audio object LOVE.audio.new source, sounds/laser.wav

And then, I think it takes in a word after that to declare whether it’s static or streaming, and then explosion So static or streaming just means whether or not it will sort of load the audio dynamically into memory when it needs to get used, and then sort of free it up Static means it’s always stored in memory So smaller sound files you can keep in memory and it’s not a problem For us for a game with a lot of music– for example, Super Smash Brothers, the new Super Smash Brothers Ultimate, has 900 songs– all, I assume, CD quality That’s a lot if you keep all those in memory at one time So those you would want to stream from disk In this case, we’re not streaming them We’re just going to keep them static They’re small sounds They’re very few kilobytes LOVE.audio.new source sounds, explosion.wav, static And then, in ship.Lua, this is where we actually instantiate the projectiles So going to say, g sounds laser play And actually, right before I do that, I’m going to call stop on it And what this does is, if the sound’s already playing it stops it and then replays it instantly And this is to solve the problem that happens because if you try to fire a sound or play a sound in LOVE 2D and that sound’s already playing, it won’t re-trigger the sound, it’ll just keep playing the sound that was already playing So you can’t, like, rapidly hit laser and have a do, do, do, do It’ll just play it only as fast as the sound itself is going until it ends, and then it’ll trigger a new one But we wanted to basically, if user presses space bar fast, we want it to trigger every single time So we’re going to call stop and then play, and that will solve that problem And then, in main.Lua when we actually do the collision, we’re going to say g sounds explosion stop, and g sounds explosion play Just like that So this should work [EXPLOSIONS AND LASERS] So a pretty easy game, I would say, at this point We might need to throttle how fast we can shoot the laser, but it works It’s pretty cool The other thing that we need to do which we haven’t done, which I mentioned we would do, is get rid of the projectile when they’re off screen JPGuy says, got to go for a while, hopefully be back before the stream ends Good luck with the Space Invaders stuff Thanks so much, JP Appreciate having you on I’ll see you next time Tune in on Friday for David’s stream He’s going to do some Docker stuff It’s going to be super cool MKloppenburg, thanks for the tip Downloading VFXR now Awesome Yes, it’s a great sound synthesis program I love it for simple, like, retro-style stuff Sustain, yep, did all that Death to them all, says JPGuy Death to all the aliens Normally, when you hear the word love, you think of romantic stuff Now, immediately thinks of LOVE.update Yeah, I’ve ruined that idea for a lot of people, I’m sure All right, awesome Everyone’s thinking that this is super cool I think it’s super cool, too I mean, the sounds really sealed the deal, right? [LASER FIRING] Now it actually feels that we’re playing a game It’s not just a little weird demo-y thing We’re actually getting somewhere with it So that’s that Let’s also take care of the projectiles being at the top of the screen So we can say, if projectile.y is less than or equal to zero minus projectile– or I guess we can just say, negative projectile length, then projectile P key is equal to nil And then, this four loop then needs to be in an L statement, because if we do this, this projectile collide function will break, because that’s now a nil object, right? Is that true? I think the object will still exist We still have reference to the object itself So I don’t think that’s necessarily true, but we should still put it into an else just for good

measure, because logically we don’t want to check to see If it’s beyond the edge of the screen, we don’t need to check to see if it’s colliding with an alien It’s impossible It’s beyond the view So we’ll do that So now, we can demonstrate that this works In my LOVE.draw, if I say, LOVE.graphics.print, projectiles, two string, length of projectiles So this should print– yeah, projectiles zero, right, up at the very top [LASERS FIRING] Yep See, they’re all set to zero So we have no projectiles left They’re all getting set to nil Pretty cool And it looks like it renders it I think it takes it a second to unload Like, the reference is nil, but for some reason it takes it, like, half a second to actually update that number So it stays– it’ll, like, instantly go to zero– everything But it works It’s good We are freeing our memory as we use it [LASERS FIRING] So we don’t need to worry anymore about sort of having a ridiculously long update loop or running out of memory Those aren’t concerns anymore We can check if the projectile is nil or now in the loop before shooting Well, we’re not going to– oh yeah, I see what you mean Yeah, we could do that It’s probably unnecessary and more code than just doing an L statement, though, to be honest, so that’s OK Probably slightly more efficient, too Oh wait, yeah Yeah, slightly more efficient, because it’s going to update iterate through every alien if we did that So we’re just saving some cycles It’s not a huge optimization, but it saves us, minimally, 55 if statements, if not more logic than that Maybe it’s more complicated than that So it turns that into just an else So it’s pretty cool We have a special guest today with us, here Who do we have on stream? You might be cut off You might need to crouch a little bit, there Hey SPEAKER 2: Hey! Nice to see everyone COLTON OGDEN: Is this the first time I’ve seen you since– SPEAKER 2: In like, since 2018 Yeah COLTON OGDEN: Yeah, I didn’t realize that actually, yeah SPEAKER 2: These streams are like a tour of my childhood, it seems COLTON OGDEN: Oh yeah Did you want to play a little bit of crappy– SPEAKER 2: Yeah, how far along are we now? COLTON OGDEN: We’ve got projectiles, and you can use the arrow keys and space bar to shoot some aliens if you want SPEAKER 2: All right Hey, that’s a lot of diverse enemies up there COLTON OGDEN: Yeah, we have it all– they’re set to a random index on a spreadsheet We just implemented getting rid of projectiles when they’re off screen, and so now the memory gets freed That was the most recent step SPEAKER 2: I still remember that sound There’s a very prototypical laser sound COLTON OGDEN: Yeah, we used a– if you remember from the games course, the VFXR tool which we used to generate sound SPEAKER 2: Yeah for sure COLTON OGDEN: You started a new course today, right? SPEAKER 2: We did We’re teaching a new course on computer science and the law at Harvard’s Law School, in fact COLTON OGDEN: How’d that go? SPEAKER 2: Good, good Doug Lloyd will be co-teaching too, so he takes over later this week So a few more lectures up this week COLTON OGDEN: Nice And then you’re coming in on Friday? SPEAKER 2: Oh, yeah, no surprise this time, though What game are we playing on Friday? COLTON OGDEN: Oh, yes It’s called Docker SPEAKER 2: Oh, yeah, so we actually use Docker, which is a containerization technology, which is a similar in spirit to virtual machines, if you’re familiar So we’re looking forward to talking about how those works and how they drive all the CS50’s infrastructure, and increasingly a lot of cloud-based services, as well COLTON OGDEN: Nice I’m excited to learn a few things about Docker, as well SPEAKER 2: Cool All right COLTON OGDEN: Have a good time SPEAKER 2: Well, I don’t want to take away from the game Good to see everyone and see you back in the chat, and thanks for tuning in COLTON OGDEN: Cool Thanks for popping by Appreciate it All right, so we did the freeing of the memory when the projectiles go off screen So the next thing that we should probably take a look at maybe is have the ships fire back at us Because currently, we can fire at the projectiles, but it’s a one-sided battle The aliens cannot actually give us any challenge Eventually, they will come down towards the player and theoretically collide with us– well, they will collide with us, certainly But yeah, actually having an adversary fire at us is probably worth implementing So why don’t we take a look at that? So in the alien class, this is probably where we want that to happen [MUSIC PLAYING] Aminebenamor, thank you very much for following And actually, now that I think about it, probably not the alien class,

because only a specific subset of aliens are going to want to be able to fire at the player Do not give them weapons This is how it starts, says [? Aslee. ?] Yeah, no Unfortunately, for the sake of having an interesting enough game to at least give us a challenge– is what Bhavik is just mentioning now– we probably want to make this a bi-directional game So my initial thought was do it in the alien class, but that’s not going to work necessarily well, because we need to have access to all the aliens We need that access to that information because we need to figure out which aliens are at the bottom row And the reason we need to do that is because if we look at the game and we see the aliens moving, if we allow every alien to fire and the projectiles will sort of indiscriminately collide with other aliens or the player’s ship, as you can imagine, all the aliens that are above the other ones will kill the aliens below them And this will therefore leave only this top layer of aliens, depending on how fast the shooting interval is, once that has passed So what we want to do– exactly, Bhavik Knight is saying The bottom row aliens only, otherwise the aliens will kill themselves That’s correct So we only want the bottom row to shoot However, we want the bottom row to shoot, and that includes aliens that we defeat from the bottom rows up So if for example, if we defeat an alien there, the alien above it should therefore be able to shoot at us now And you know, the same thing if we do it again Then, the alien in the third row now should be able to shoot at us, and so forth So we need to figure out– I guess we could sort of tweak the aliens that can fire based on the aliens above them I guess whenever we defeat an alien, we can then trigger some code that gives the alien above it the ability to fire That’s probably the easiest way to do it, honestly, is to give each alien a flag So the alien– I guess we just do it in entity, because ship and alien can fire So self can fire is false We don’t want every alien to be able to fire necessarily Now Colton is trying to build Skynet He is one of them I can neither confirm nor deny such claims– such accusations I’m going to, in main.Lua where the ship gets instantiated, I’m first going to let the ship fire Ship can fire is true This should be true And the aliens are all going to be, by default, not able to fire They’re going to be sent to can fire is equal to false So let’s go ahead and give the bottom row of aliens the ability to fire So we generated all the rows and columns, and then I’m going to say, if y is equal to aliens tall, then– So this is– OK So I’m going to do this I’m going to say, local aliens equal to this bit of code here So what I’ve done is, as I’ve taken that constructor out of the table insert function so that we can store a reference to it here So local alien equals alien at xy, math.RAM 256 for the random frame And then, I’m going to say, if y is equal to aliens tall, which means if we’re bottom row, then I’m going to say, alien can fire is equal to true Right? So this will only give aliens at y level five the ability to fire And then, in our update– did I do this in update? I guess I can in alien here Yeah I want it to be on a timer, and I want to give each alien a random interval of time that it will fire

Because I wanted to be kind of random I don’t want to be on a consistent timer, because if they are, they’ll all fire at the exact same time And it’ll be kind of like a blanket of fire, and it’ll be weird And it won’t be unpredictable It won’t be fun So also, each alien needs to have a reference to its own firing interval, right? So it needs to randomly choose a length of time It will wait to fire, and then fire And then, when it fires, it needs to reset that interval to some other random value And we can set it between maybe one and three seconds Or no, because that would be pretty fast Maybe one and seven seconds Yeah, we’ll do it between one and seven seconds One and 10 seconds? Yeah, one and 10 seconds This is all game design, game balancing, that sort of thing– again, up to taste more than anything else You want to tweak values, mess with them, figure out what works So we’re going to say– what makes the most sense, here? Do we put it in here? Because if we do that, we need to create a new constructor Just brainstorming for a second, figuring out what makes the most sense We can check if the alien has another alien in front Yeah, we could do that, but that’s going to be a little bit less– I think not as clean of a solution as I want to look for I mean, it works That’s solution would work fine, I think We can set it so that if there are fewer aliens, they shoot rapidly With more aliens, they shoot at a slower pace, says [? Bhavik Knight. ?] That’s not a bad idea That’s pretty cool, interesting sort of game design idea Certainly would work Certainly would be good I’m just trying to figure out how to structure this in my head before we actually code So the aliens that can fire need a timer– a fire timer The fire timer is going to get a random value between one and 10, and that’s the number of seconds Each one will therefore need a timer, itself So an interval and a timer– the interval will be the amount of time to wait for it to fire The timer itself will be the amount of time in delta time in seconds that have elapsed to wait for that interval to have passed Will then fire, will reset the timer, create a random new interval So yeah, we have the pieces So the best place to– I mean, dynamically, we could just do it in main.Lua We could just say, alien.timer Everything alien is going to need a timer so that we can update it Well, it will have a timer Oh yeah, so alien.timer is equal to zero Fire timer, we should call it fire timer Try to be a little bit more verbose when you can And then, fire interval And that’s going to be math.random 10 So this is the random length of time that will pass Aliens in the back have less pause, and aliens of the front have more pause to shoot Yeah, that’s a good idea, [? Bhavik. ?] Not bad I would recommend implementing something like that, for sure Try it out That’s a good example of an actual mechanic to influence the gameplay– the difficulty of the game So fire timer is zero Fire interval is equal to math.random 10 So what we can then do is say, in our update– tick aliens It could go in tick aliens, too We’ll write it in here, and then maybe we’ll make it a separate function

So for _alien in pairs aliens, do And then we’re going to say, if not alien.invisible, because the alien can’t shoot if it’s invisible If alien.can fire– if it can fire, then that means that it will have a fire timer and a fire interval So we’ll say, fire timer equals alien.fire timer plus delta time, if alien.fire timer is greater than or equal to alien.fire interval So this means that the amount of time has passed that’s the same or greater than the actual interval that we’re waiting for this particular alien It’s going to be random for each alien So this alien is set to fire after five seconds, and five seconds have elapsed, then I’m going to set alien.fire timer equal to alien.fire timer minus alien.fire interval So set to zero, or roughly zero And then, we’re going to spawn a projectile, and it’s going to go down So this is kind of what we did before Table.insert into projectiles a new projectile, which is going to get alien.x and alien.y plus alien.height And then, it’s going to be set to down So this projectile is going to move downwards It’s not going to move upwards, right? So let’s try this Oh, hey, whoa, nice OK So some of them are firing in tandem, because it’s not a floating point value It’s an integer So the random number– oh, we forgot to change this to another random value So alien.fire interval is equal to math.random 10 All right Aliens can’t shoot when they’re invisible This is in line with Star Trek As far as I recall, the Romulan spaceships couldn’t fire while they had their cloaking devices on That’s interesting I’ve not watched much Star Trek, but that sounds very apt for this particular example But the aliens are firing Now, the only thing is, they’re not shooting at us I guess I do want the alien to also do the sound effect for firing So g sounds, laser, stop, g sounds, laser, play Now, I kind of almost want to have a different sound effect [LASER FIRING] It’s kind of cool, because it’s creating, like, these obstacle courses that I have to fly through Whoa, like that Oh, it went right through me There’s no collision for the ship yet, actually, so it’s not doing anything So it can just go straight through me I forgot I, like, instinctively wanted to dodge it Yeah, the sound’s not bad, because it stops every one when it fires A different sound effect would be better, says Andrej We can do that Different sound effects, so let’s do some lasers Not that one [LASER FIRING] That sounds obnoxious [LASERS CONTINUE] Even more obnoxious That’s not bad I kind of like that I’ll do that one Alien laser Different alien projectile color, as well That makes it a little bit more complicated, because then we have to add that as a field onto the class Maybe we can make that an optional feature at the end if we have time For simplicity, we’re going to keep them the same color, just for now Dependencies– it’s a good idea, though Don’t think that it’s not a good idea I just don’t think we have the time But no, it’s an awesome idea I totally agree Alien laser equals LOVE.audio.new source, sounds, alien laser.wav, static Alien laser.wav does not exist What did I call it? I called the alien laser.wav

Oh, sonds That needs to be sounds OK Oh, so now we have to actually call the right sound effect So in here it’s alien laser [LASERS FIRING] Yeah, I kind of like it It’s a little bit deeper than the regular spaceship, so it kind of has a more even, like, a weird, very subtle, sinister difference So I kind of like it It’s pretty cool Yeah, that’s great We’ll do it Ship it Now, the projectiles should collide with the ship, as well So what we should probably do is– updating it if it’s less than projectile length, or projectile.y is greater than virtual height Remember, because these are the projectiles that go below the edge of the screen, we have to keep track of this, as well Then, set it to nil We were only checking above the top edge of the screen We also need to check the bottom edge And we need to also check to see if it collides with the ship So we can say, if– we can shortcut this, too Do I want to do that? No We’ll just say, if projectile collides with ship, ship.invisible is equal to true So because ship inherits from entity, this should result in the ship dying Yep, perfect So I’m still moving the ship around I can still move it around, but it is not visible And I want an explosion sound to play I want a different explosion sound to play than when the ships die, though I want a more dramatic sound, I think So let’s try here [EXPLOSIONS FIZZING] Oh, that one was all right It’s not quite long enough, maybe [EXPLOSIONS CONTINUE] That one’s very dramatic, but it’s kind of appropriate Cool We’ll do that one, just for the drama Death.wav Let’s go over here, we’ve got got to go into dependencies Got to add death.wav Audio.new source, sounds, death.wav, static Cool And then, here, set explosion We want death Lots of positive words All right, let’s try and die [EXPLOSIONS BOOM] There we go A very dramatic death sound, and the player does die We do not go to a different screen, unfortunately That is not yet implemented, but that’s probably the next step, honestly We’ve implemented movement We’ve implemented the ships firing We’ve implemented death on the player’s side There’s no score, yet Score is important We probably want score The title screen, probably important Yeah, that’s probably it for now The next part is going to be the largest part– the more complicated one, I suppose So let’s do that So the title screen Well, the state machine class first I’m going to create a new folder called states within source, and then I’m going to create a new file in source called state machine.Lua And a state machine is a– it’s been a blast thus far, have fun with the rest, [? says MKloppenburg. ?] Will have to watch the part later on Thanks so much for joining, [? MKloppenburg. ?] Glad to have you with us Hope you enjoy

Be sure to tune in on Friday for David’s streaming It’ll be super awesome The state machine class is a– so a state machine is essentially a finite representation of what the state of something is, whether something is– it can only be in one state at a given time, and going back and forth between states occurs during certain transition criteria, right? So you have a title screen When your game is in the title screen, it’s in a state of being in the title screen You’re not playing the game You’re not at a game over It can only be in one state at a time You can’t be a title screen and the game over screen at the same time That doesn’t really make sense You could maybe make a game that tells you you lost, but is also sort of the game over But it’s technically still going to be a different state, more than likely A state machine is what allows you to transition between the different states of your game The state machine is kind of like a thing that points at whatever state is currently active and updates it, checks for the transitions, and then transitions when it needs to do so and keeps track of that The actual states themselves are how we modularize our game, and we can then implement the title screen separate from the play state separate from the game over state, et cetera So the state machine class– first of all, it is a class So like we did before, we’re going to create it as a class The state machine has an update and a render function Just like a lot of the other stuff that we did, we’re going to call this from main It also has a change function, which will allow us to put it into a particular state And we want to actually be able to create it, so it takes in a state table which we are going to store all of our states in So when we call change state, we want to do is essentially say, self.current state We’re always going to have a current state And this state machine can apply to creatures in your game It can apply to the game state itself You can basically make a state machine for anything that changes state and that you want to modulize the state of, or encapsulate into a discrete file or module You can use a state machine for it It’s pretty flexible, and typically you use it for creatures in the game or game states, most often, but you could find multiple uses for it The state machine will always have a reference to whatever the current state is as its current state field, and that changes depending on what we call a change, and so forth So I’m going to say self.current state, exit So every state is going to have an exit function and an enter function The exit and enter functions function as the transition– sort of an abstraction of the transition of a state from one state to another state When you transition from one state to another, you call exit on the state that you’re in So it’ll clean up whatever it needs to do, do other stuff, and then it will call enter on the state that it’s transitioning to And then, it will set the current state to that state And so the enter basically lets you clean up stuff in the state they you’re currently in if you need to do so, free memory, do whatever you got to do, and then call some initialization code in your new state with the enter function And enter usually takes params, as well So that’ll be this, if taking the param is a second field of that function And then I can say, self.current state is equal to self.states state, and then, oddly, I do call it as a function, which we’ll see here in a second as to why we do that You don’t have to necessarily do it that way, but it’s a nice, clean way to do it when you have a game that uses, like, fresh states every time you do a state transition And then, I’m going to say, current state enter params Self.states is equal to states

Self.current state update, and self.current state render So we have a state machine class that will take a dictionary, it will take a map, take a table of states, and they’re actually going to be in the form of anonymous functions And we’ll see that That is why we call this here– this parentheses here, like where you’re doing a function call, because each of the self.states is actually a function [MUSIC PLAYING] It’s actually a function object Mirkyst, thank you very much for following So if I go to main.Lua here, first of all, go to dependencies.Lua and require source state machine, like so And in the LOVE.load, this is where I like to initialize the state machine I’ll usually do it after all the setup stuff And back for another half hour or so says, JPGuy Thanks for joining again Just doing some state machine stuff now, so a little bit more meaty, so to speak It’s a simple class, but a very flexible, very useful class What we’re going to do is, I’m going to create a g state machine Now, this g state machine is global because we might want to change our state from within other states Well, from outside of main.Lua, we are going to change it from within other states Each state of our game is going to be able to transition to other states So the state machine itself needs to be global So I’m going to do this here And I’m going to say title is equal to an anonymous function that returns a title state object, which we have not seen yet Play is going to be equal to a function that returns a play state, which we also have not seen yet And game over is equal to a function that returns a game over state, which we also have not seen yet And I’m going to change our state to the title state It takes no parameters And we want to make sure that if self.current state, then we want to basically put this in an if statement, because if we’re starting the very beginning of the game and we don’t have a current state enabled, then this will not work, because self.current state will be equal to nil And we can’t call exit on nil It has to be something that has an exit method attached to it, which is every state Every state needs to have enter and exit associated with it That’s part of the interface That’s how we can get this to work It assumes that any state that we implement will have that interface This is kind of like an interface, as per what Bhavik mentioned earlier But again, this is all dynamic Nothing is going to enforce that these functions exist It’s up to you to enforce that So I’m going to go into states, here, and create a new file I’m going to call this base state Not the most useful comment blocks of all time, but better than nothing, I suppose, arguably Base state is going to be the state from which every other state inherits And the reason that we want this to exist– we wouldn’t normally need this, but this is to prevent us from having to write empty enter and exit methods for our future states, because not every state needs an enter and an exit method, but our state machine assumes they exist And because it assumes they exist, we want to basically make sure every state has this interface– it adopts this interface And so we get this through inheritance So base state is then equal to a class And all base state is a bunch of empty methods Base state, update, render, enter, which takes parameters, and exit So this is all that base state is– just an empty class– well, not a completely empty class, but a class with five empty methods, an init, update, render, enter, and exit– all functions that the state machine assumes exists on each state that it works with So now what we can do is, I can say, new file in states

I can call this title state And title state is going to be equal to a class which includes equals base state, right? And so now this is essentially the same thing as copying over these five methods into title state for free So if we just saved it like this, titles class is essentially the same thing as titles state– sorry, this should be title state, not title class Title state will be the same thing as base state, essentially They have the same methods We don’t want that to be the case, though We want title state to actually have some behavior So what I’m going to say is, any function now that I define that has the same name as these, it’ll just override that It will just replace it with our own version while keeping the other ones that we inherit from base state, which is super useful So we can say it’s title state, and then this will be update and render We only need these two for now, just to demonstrate how it works So I’m going to say I LOVE.graphics.print, Space Invaders This is the title screen Actually, this is going to be printf Title screen, right, so this is going to be Space Invaders It’s going to start at zero It’s going to be roughly in the middle of the screen, virtual height divided by two minus– I don’t remember how tall the font is I’m going to assume 16, so I’m going to have minus 8 It’s going to use the width of the screen as its wrap amount, and I’m going to center it Oh, sorry, this should be in the draw function And up here in the update function, I’m going to say, if LOVE.keyboard.was pressed, enter, or LOVE.keyboard.was pressed return, then I’m going to– a bit of a brain fart g state machine change to play No parameters So maybe you see what’s happening here It’ll be clear shortly if not This is just a title screen that’s going to say Space Invaders in the middle of the screen And it’s going to check for input when we press enter or return– return taking into consideration Macbooks, which by default, the enter key is return It’s going to use that g state machine we declared in main.Lua and transition to our play state, a state that we defined as play And again, the states are all here– title, play, and game over Those are the string keys And they map to anonymous functions These anonymous functions are being stored in our state machine in self.states So self.states is just a reference to this table, here That’s what this curly bracket syntax is Remember, you can instantiate a class with its name and curly brackets if it just takes in a dictionary or table or map– however you want to look at it And these are anonymous functions that are stored there, assigned to these keys So key value– the values are function objects Those function objects will be called here, right? And remember, all they do is they just return a state– a title state, of play state, and a game over state– a fresh state, completely blank, which we so set to self.current state on line 13 here by saying, self.states at state– remember– change to state And then, we call these curly brackets That’ll actually call the function object It’ll execute that function’s code And the function’s return value is that state– depending on whether it’s a play state, a title state, or a game over state– and therefore assign it to current state, so then we have a reference to that state object– a brand new, clean state object MetalEagle says, hello CCSA TV Hello, MetalEagle Glad to have you with us Happy new year So that’s how the state machine is working That’s how it’s getting the state object and it’s keeping track of whatever state is currently active We still have a few pieces left to implement, though Why don’t we go ahead into– well, we’re already implementing the different states, the title screen Let’s add a play state The play state is essentially going to be all the stuff that we implemented in main.Lua already Play state equals class, includes equals base state And so what this is going to do is, all of this stuff here, right,

this is all going to be sent to the init function of the state Play state Right, so that’s what this does So we’re using self now So we’re no longer having these pseudo-global variables that are at the parent level of our main.Lua Now they’re actual member variables– member fields– of the object itself, these new state objects We’ve essentially taken all of our logic– we’ve found a way to take the game logic itself and put that into a class And so now we can modularize how our game flow works and not put every bit of important logic into main.Lua, so it’s super nice And that includes also these variables up here We don’t need these in main.Lua Those can be in the play state, just like that And they’re no longer a local, right? So boom, boom, boom, boom They’re self And now these– the [? Aslee ?] and Bhavik variables were just kind of stored temporarily they aren’t really ever referenced later on So we can keep those as locals We can keep the ship index as local We’re reusing it here and we’re putting that into self.ship, which is actual ship variable that we’re going to use consistently throughout the rest of the course Oh, it’s JPGuy’s birthday Happy belated birthday, JP I did not know, as well I apologize if he mentioned it before I did not know December 17th, nice Happy birthday So now, notice that self.projectile, self.aliens, self.ship is not necessary here, because we assigned it here Yeah We declared it in advance as a local because we wanted to reference it later on And if you want a local variable that you reference from within a nested scope, you need to define it above that function, which is why we did it before We don’t need to do that anymore, because we can just call it self.ship here and assign it, so super straightforward, saving a lot of code, actually All of these we can keep in main.Lua We can keep [? kush, ?] we can keep all the initialization stuff We can keep the state machine, itself, being initialized All of this stuff, though– this is all actually update code for our play state So copy that, bring it over here to our update function So this is cool Now remember, every time we have a reference to ship, it’s no longer just a reference to ship or projectiles We actually have to reference it as self.ship and self.projectiles, so that’s important that we keep track of that Let me make sure that I’m not missing any of those OK And tick aliens– remember, that was a function that was in main.Lua We no longer have access to that from within here So what we want to do is, we want to take tick aliens probably out, and take that out of main So again, saving space in main, allocating it to a different module Can I just copy it here? Right, yeah OK, and self.aliens, cool And alien movement timer, that’s a self as well, right? Yep So we want to set alien movement timer as self.alien movement timer And alien direction, as well? Yep Alien direction, that also gets adjusted So alien direction becomes self.alien direction Whoops Boom, boom, self.alien direction, perfect So that should be good That looks good to me So our main.Lua is now 68 lines of code, so we’ve actually reduced it quite a bit The draw, as well, we can get rid of that, right? So we can do this, get rid of this, go over here to make a draw function Or render, I should say And this should also be set to play state tick aliens

And this will be self tick aliens So here, we do this So pair is self.projectiles, self.aliens, and self.ship So everything is kind of coming into plan, here Code looks very good and modularized now Yep, thank you Watched the video about state machines 600– so of course someone has mentioned it before Yeah, super useful construct in game programming– ubiquitous, very useful, very helpful OK We’re going to keep if keys equal to escape in our actual main.Lua so it’s accessible from within every single game state Now, the missing ingredient is, we actually have to call g state machine render and g state machine update, right? Because if we don’t do that, then all that code that we put into play state is just kind of lost in space It still needs to be triggered And we do that from within main.Lua using the state machine object that we declared earlier and that we initialized So assuming that I did everything right, and actually I know right now that I did not actually require the states, themselves Very important that you do this Title, state And because I have a reference to it, I am going to require a game over state, and just add it really fast Game over state.Lua Game over state class Not functioning game over state Game over state is equal to class, includes equals base state Cool, now assuming that everything is in place, this should at least give us a title screen And as soon as we hit the title screen, and we press enter or return, we should get transitioned to sort of the game as we saw before So let’s take a look Cool, pretty nice We see we have the Space Invaders text in the middle Because remember we’re defaulting to the title screen– the title state So starting right off in the middle of the screen, we press Enter OK, so it’s not completely perfect Play state line 33, bad argument to insert OK, play state line 33 Let’s see what that looks like Ah, aliens needs to be self.aliens Let’s try that again Bad argument, two pairs, play state 66 Probably the same bug Yep, self.aliens And play state 112 Yep, self.aliens OK, boom, boom, boom, boom Remember, aliens by itself is no longer meaningful It needs to be self.aliens because it’s within the play state So now– OK, 78 Still have a few that we missed, which is OK Self.projectiles Yep I can’t believe we haven’t missed any other one Let’s see Yep, right here, self.projectiles OK, so hopefully that works Once again, 16 Oh man Wait, what did I miss there? What was that? Oh, projectile line 16 OK So projectile line 16 OK, takes on an entity, which gets an xy within a height So where are we referencing that for– let’s see if we have a stack trace here OK, that’s from line– oh, play state 56 OK, play state 56 This needs to be self.ship, not ship OK And this needs to be self.ship, as well A lot of these little things you’ve got to tweak If you start this off from the beginning in a state– what was the key code to press when changing two of the same names at once? Oh, if you highlight something, you can press Command-D or Control-D, and that will highlight the next thing of the same name in VS Code, and a lot of other text editors like Atom, too All right Is this working? Come on

[LASERS BLASTING] OK, that looks pretty good Let’s make sure that I can shoot other ships too OK, cool One thing that we didn’t implement, actually, which is important is that the ships above the ships that die on the bottom row haven’t been given the ability to fire, so we need to also do that But yeah, we’ve modularized everything Everything is cool We have two different states, now We have a title state and a play state And the last one will be a game over state when we die So as soon as we die, we should just do a change to the game over state, which we can very simply just kind of copy over the title state stuff, here, making sure to rename them to game over state And then, we want to set this to title And then, game over like that, which won’t do anything, because we’re not actually transitioning to it yet So from within play state, what we want to do is, when we die, we want to g state machine, change to game over Is that how I named it? Let me make sure Yep, perfect So now when we die, we should go to a game over Let’s try it [EXPLOSIONS] Awesome So we have a game over If I press Enter, we go back to the title screen If I press Enter again, back to a brand new game Now, do the ships regenerate? OK, let’s move firstly the green one and then– yep So the ships themselves also regenerate Sorry, that was a lot of sound at once MetalEagle says, why do you have call stop before play? So we mentioned this before What it does is, if you’re triggering in LOVE 2D a sound effect, and you trigger it fast before it’s finished playing, LOVE 2D will not refire it It will let it the sound effect keep playing until it’s finished And so if you want to have a rapid fire laser, for example, you will kind of just be stuck waiting for the first sound effect to finish, and it will kind of be like a weird sort of– sometimes it’ll fire, sometimes it won’t, kind of sound So if you stop the sound effect and then play it immediately afterwards, you will be able to re-trigger it instantly So you will get the effect of rapidly triggering that sound effect over and over again Good question You weren’t thinking about separating the entity class, and with modularity, look how far we’ve come with state machine Yes Yes, this is Bhavik And that’s a it’s a good point Always try to modularize stuff as best as you can I mean, I’m sure we could do a better job of modularizing what we have now It’s fairly well-structured, but you can almost always get better at organizing stuff If you see really large functions, a good heuristic is to kind of break those up and make smaller functions Separating the states is very good for game development, that sort of thing Yeah, it’s good practice Always try to make the most elegant code that you can It’s difficult if you’re in a rush and you have deadlines to meet and stuff Sometimes you can’t do it But as best as you can, as much as is realistic for your hobby projects or whatnot, it’s good practice, if anything The other thing that we were going to do is, we were going to make sure that aliens could still fire at us from the upper rows when the lower rows are cleared out And we also want a score And we want to display the score when we get a game over So what we can do is– and also we would also want to trigger a new level each time we clear out the map I’m not sure if we’ll have time to do that, but we could certainly talk about it But for now, let’s do the aliens being able to fire when the lower aliens are cleared out So what we can do is– where is the code located at? [MUSIC PLAYING] Balthazar_Bratt, thank you so much for following Appreciate it In play state– so in play state where we actually check each projectile against each alien, what we’re going to want to do there is, when we do collide with an alien– which is what we do here, when we trigger the code for clearing it out– we want to give the alien above it the ability to fire,

give it an interval, that sort of thing So what we can do is, A key will be the number– the index of the alien every time That’s what we have set to, here That’s why we needed to declare it So we’re going to say, if A key is greater than 11– and the reason that we’re setting a greater than 11– and what we should actually do is use a constant, so in this case, aliens wide, right? What this will give us is true if it’s anything greater 11, which is the length of an individual alien row So any alien beyond the top row, right? So if it’s the case that that alien is below the top row, then we want to say, aliens at A key minus aliens wide.can fire is equal to true And we have to do the same thing that we do when we basically figure out if the y level is aliens tall when we initialize the aliens So we’re going to say, can fire is equal to true, fire timer to zero, and fire interval to math.random 10, right? So fire timer equal to zero And fire interval, math.random 10 And that should work Let’s try it out [LASERS FIRING] I’m going to clear out this alien Whoops Play state 55 I forgot to do self.aliens for all of these So make sure to do that OK Clear that alien out So pay attention to that OK, so he killed the other alien, so that was an unfortunate bug Whoops Let’s try that again [EXPLOSIONS] So the reason that’s doing that is because the movement is fast It’s too fast So we can maybe tweak that So if we set constants to the alien movement interval to 0.75– [LASERS FIRING] OK, so it’s still killing the aliens below it So how did I fix this before? I’m trying to remember I solved this problem once before The simple thing to do– they’re not spawning in the middle of the ship, are they? No, they’re not That is a bug Yeah, the projectile is spawning right at the alien x We don’t want that to happen We want it spawn at alien size divided by two– alien x plus alien size divided by two That should fix it That should fix it Now it’s right in the middle [LASERS FIRING] There we go Perfect So it was spawning right at the x, right at the edge of the alien, and so it was instantly colliding with the alien right below it if there was an alien right below it So you don’t want that You want the lasers to spawn right in the middle of the alien So we fixed that problem Let’s try and figure out a [INAUDIBLE],, see what it looks like [LASERS FIRING] Whoa They can still kind of– they can still sort of kill each other Yeah, because they move in such a way that the movement itself

might be slightly off of when the projectiles themselves move So I think what we should do is set the movement interval to 0.7 and not 0.75, so it’s not in between a second, because all the lasers will always fire at a second, I think Oh, I guess not, because when we kill the alien, it changes the– oh whoa, that was weird I got an alien to die above another alien, which is probably because I shot a projectile and it moved right into it That’s pretty cool [EXPLOSIONS] So yeah, lots of fun stuff To do features where we ask a player named, score, high score, with the player name, levels, et cetera If the alien should check whether any alien is in front of it or not before shooting Yeah, that would be one way to solve the problem a little bit more appropriately The problem isn’t that there’s an alien front of it The problem is that it moves into it on the frame after it’s shot the projectile So anticipating that is a little bit trickier I could just make all the projectiles always spawn at the lowest y-level, but that’s not as convincing-looking We won’t spend too much time fine-tuning that, I don’t think We’ll kind of consider it a feature for now, just for the sake of time I think if we had more time, we’d actually implement perfect laser firing from the aliens It’s pretty good, though It works pretty well Andrej says, you could do what the other, original game did With game creation, I found some glitches that you did not initially intend to be a cool and unexpected feature Yeah, games are so crazy a lot of the time that stuff that you try out and mess up ends up actually being interesting, and demos you create end up being fun It’s pretty cool And then, Andrej said, you could do what the original game did But I’m not sure what that is Andrej, if you wouldn’t mind elaborating that’d be awesome Aliens’ lasers would be ignored by aliens Oh yeah, we could do that too I could just– yeah, I could say if projectiles down and it collides with an alien, do that It’s not super important at this point, I think We’ll just let it exist as it is It works well enough for the demo It’s probably somewhat fairly easy to fix And I encourage, actually, if you’re following along, to try to fix it, because that’d be cool Let’s implement a score mechanic in the play state, and then let’s feed that into our game over state So let’s go ahead and set a score to– here, I’m going to set the score to zero And in the render function, I’m going to draw the score after the ship So LOVE.graphics.print score, two string, self.score Just like that So that’ll print a score in our play state, which it does, very top left Pretty cool It’s not going to change, though, because we don’t get a score any time we kill an alien But that’s easy All we have to do is go to our update function, and whenever we collide with an alien– which is here Say, self.score equals self.score plus 100 Pretty easy, right? But we’re not feeding the score to our game over screen, so we can’t see what our score actually was So we should probably do that So I’m going to, in our what we call game over, which is– where is that? That is right here So game over, remember the change function can take parameters So what we’re going to do is, we can say, we’re going to pass in an anonymous table, and I’m going to say, score is equal to self.score And what this is going to do is, this is going to pass this table to the game over state with a key of score that equals the score as it is right now, self.score So in game over, I’m going to game over a state, Enter, params, self.score is equal to params.score So remember, that table is going to get passed in our state machine