Make Animated Retro Games with JavaScript | Frank Dvorak | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Make Animated Retro Games with JavaScript

teacher avatar Frank Dvorak, Creative Coding

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Project 1 Introduction

      1:02

    • 2.

      Project 1 features

      1:27

    • 3.

      Project setup

      4:24

    • 4.

      Game and player objects

      5:36

    • 5.

      Keyboard controls

      7:26

    • 6.

      Object pool

      13:01

    • 7.

      Enemy Waves

      13:33

    • 8.

      Collision detection

      8:05

    • 9.

      Score and status text

      12:48

    • 10.

      Restart method

      5:46

    • 11.

      Beetlemorph enemy class

      4:50

    • 12.

      Sprite animation explained

      10:35

    • 13.

      Animation timing

      10:15

    • 14.

      Player animation

      13:08

    • 15.

      Extra features: Armored enemies

      0:57

    • 16.

      Rhinomorph enemy class

      9:24

    • 17.

      Extra features: Boss battles

      0:30

    • 18.

      Boss class

      9:27

    • 19.

      Boss movement

      10:22

    • 20.

      Boss vs player collision

      7:07

    • 21.

      Extra features: Super weapons

      0:43

    • 22.

      2 laser classes

      8:01

    • 23.

      Laser damage

      8:01

    • 24.

      Resource management

      7:05

    • 25.

      Eaglemorph enemy class

      6:55

    • 26.

      Enemy projectiles

      6:21

    • 27.

      Projectile interactions

      4:48

    • 28.

      Squidmorph Enemy Class

      9:18

    • 29.

      Lobstermorph Enemy Class

      2:30

    • 30.

      Project 2: JavaScript Planet Defense

      3:18

    • 31.

      Project 2: Planet and Game Class

      8:10

    • 32.

      Project 2: Mouse Position

      6:18

    • 33.

      Project 2: Player Spaceship

      4:42

    • 34.

      Project 2: A Little Bit of Math

      7:47

    • 35.

      Project 2: Understand Canvas Rotation

      6:15

    • 36.

      Project 2: Debug Mode

      2:25

    • 37.

      Project 2: Object Pool

      12:22

    • 38.

      Project 2: Player Projectiles

      6:10

    • 39.

      Project 2: Enemy Pool

      7:25

    • 40.

      Project 2: Collision Detection

      2:20

    • 41.

      Project 2: Periodic Events

      8:06

    • 42.

      Project 2: Asteroid Enemy

      4:21

    • 43.

      Project 2: Sprite Animation

      9:15

    • 44.

      Project 2: Lobstermorph Enemy

      9:15

    • 45.

      Project 2: Game Text

      5:26

    • 46.

      Project 2: Player lives

      5:09

    • 47.

      Project 2: Beetlemorph Enemy

      1:36

    • 48.

      Project 2: Rhinomorph Enemy

      2:43

    • 49.

      Project 3: JavaScript Mobile Game

      1:08

    • 50.

      Project 3 Setup

      2:02

    • 51.

      Make Everything Responsive

      6:15

    • 52.

      Enemy Class

      7:58

    • 53.

      Object Pool Design Pattern

      3:35

    • 54.

      Periodic Triggers

      6:50

    • 55.

      Mouse Controls

      1:31

    • 56.

      Collision Detection

      7:50

    • 57.

      Touch Events

      1:37

    • 58.

      Game Text

      7:04

    • 59.

      Start Restart

      3:34

    • 60.

      Fullscreen Games

      4:11

    • 61.

      Simple Crew Members

      1:30

    • 62.

      Simple Enemy Type

      4:23

    • 63.

      Sprite Animation

      4:20

    • 64.

      Animation Timing

      4:08

    • 65.

      Debug Mode

      2:09

    • 66.

      Enemy Variety

      4:29

    • 67.

      Randomized Space Crew

      3:47

    • 68.

      State Management in Games

      4:27

    • 69.

      State Design Pattern

      15:23

    • 70.

      Sounds

      9:49

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

98

Students

--

Projects

About This Class

Old is gold. Let's get inspired by the classic games from the 80's and add our own graphics and game features. In the first project we will explore the interstellar void and use 3 different weapon types to burn through swarms of space bugs of different types, some larger than the others.

We will start with a game loosely inspired by the classic Space Invaders arcade and we will experiment with different additional features such as boss battles, super weapons and different enemy types.

Let's explore object oriented programming with JavaScript and implement a useful set of basic 2D game development techniques such as object pool design pattern, sprite animation, timing and staggering techniques using timestamps and much more.

Don't forget to download all the bonus gifts. Students of this course will get a pack of premium quality 2D game art, this time in a sci-fi space theme. You can also download the source code from multiple stages of the project, as we gradually add more features.

We will implement multiple enemy types:

Beetlemorph - basic enemy, 1 hit is enough

Rhinomorph - armored enemy, multiple lives, multiple damage states

Mantismorph - massive boss size enemy, increasing pool of lives

Eaglemorph - when hit, it will sacrifice a body segment and it will spit it back

Squidmorph - inflatable alien bug, it can absorb our weapons

Lobstermorph - unstable DNA, splits into multiple smaller clones when hit

Have fun!

Meet Your Teacher

Teacher Profile Image

Frank Dvorak

Creative Coding

Teacher

Hello, I'm Frank. I'm a front-end web developer, owner of Frank's Laboratory YouTube channel. Come explore creative coding, game development and generative art with me.

See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Project 1 Introduction: Let's travel back in time into the golden age of arcade video games. In this class, we will use HTML, CSS, and Javascript to build a game inspired by the classics, But we will give it our own art style and custom features. We will control a spaceship that has to fight its way through increasingly larger waves of enemies with an occasional bust in between. As we progress deeper into the Unknown, we unlock more weapons and we encounter even more dangerous alien species. Class is not for complete beginners, but if you already understand the basics like variables, arrays, and for loops, come explore game development and chat script animation with me. Students of this class will get a ton of premium quality two game art completely for free. You can use it for your own personal projects later as well and build your own games with it. You can also download the full source code from multiple stages of the project as we expand it and add more and more features. 2. Project 1 features: First we will implement three weapon types, a basic attack, a long range laser, and a super laser. We will need it because we will have to fight our way through five different enemy types. At first we encounter just a regular space back. One hit from our basic weapon is enough. As we explore further, we run into armored enemies. We have to hit them five times. We will be able to see the gradual damage to their thick exoskeleton after each hit. If we are not careful, we might find a massive sized enemy with a dangerous set of claws. Every time a new one appears, it will have more lives than the one before slowly increasing the chal***ge for the player. As the game goes on, some alien species are up for revenge. Look at this one. Every time we hit it, it sacrifices one body segment and it will throw it back at us as a mutated projectile made out of ice, slime, and tentacles. We will also have to fight an enemy that absorbs our projectiles and inflates until it pops. With that one, I will give you a regular sized and both sized version of the spread sheets to make your game even more diverse and fun to explore. We will code everything from scratch with no frameworks and no libraries as usual. Hope you have fun on this Java Script space adventure. Let's go. 3. Project setup: In index HTML, we create a simple blank webpage. I give it some title. I link CSS style sheet, I create HTML five canvas element with an ID of canvas one. And I link script the GS file in style CSS. I target my canvas element and I give it a border. I want to center it in the middle of the web page vertically and horizontally. One way to do that is to use these four lines of CSS. We can use transform translate, or we can also just use the translate property like this. Be careful about the syntax, there is no comma between the values. Everything else in this class will be written in plain vanilla Javascript. No frameworks and no libraries. In modern programming, we can structure our code in many different ways. There are a few common and established programming paradigms from something very simple, such as procedural programming, all the way to functional and object oriented programming. Object oriented programming is probably the most popular paradigm. The core concept is that we organize our data in objects. It usually relies heavily on classes that give us a way of creating many similar objects based on a shared blueprint. In today's class, we will keep our code clean and organized by making everything into an object. And we will make those objects talk to each other. For example, when projectile object hits an enemy object, enemy object will be deleted. One of the main principles of object oriented programming is encapsulation, Which means we data and methods that operate on that data into separate bundles into objects. We can also restrict access to that data from outside the bundle us closures, private fields and so on. We will encapsulate our data into four separate classes that communicate and work together to create the final game. Player class will handle movement and animation of the main player character, the robotic spaceship. This class will only have one instance. Classes are used as blueprints to create many similar objects. In this case, player doesn't have to be a class, we can just declare it as a one simple object. I will make it into a class to keep the code structure same across the code base. I want this to be easy to read for beginners. Projectile class will handle lasers that the player will be shooting. We will learn how to make this into a re, usable object pool to massively improve performance. Because creating and deleting thousands of projectile objects would waste a lot of memory. Enemy class will draw and animate Space Invaders. We will learn how to organize them into grids and how to make them come in larger and larger waves. As the game goes on, Game class will contain the main logic of the code base. This is the main brain that sends commands everywhere and it holds all of this together. We will be using polished professional game art that I'm giving you completely for free. And we need to make sure Javascript runs only after all our art assets are loaded and available. I will only start and set my project up after load event on window object fires when the whole page has loaded, including all dependent resources such as style sheets, scripts, images and so on. Inside the callback function on load event listener, we can set up our canvas element. As usual, I use four simple lines of code. First, I point Java script towards my canvas element using its ID. I save that reference in a variable, CTX context canvas variable dot get context and I pass it to the. This will create an instance of built in to the canvas API, giving us access to all drawing methods and canvas properties such as fill style or line width. Because we want to make sure that canvas drawings are not distorted. We are not setting the size of canvas with CSS because that would only set the element size if I set canvas width and height like this. With Javascript, we are setting both element size and drawing surface size to the same values. Html canvas has two sizes, they need to be set to the same value to prevent distortions. 4. Game and player objects: Game object will need to be aware of canvas size. So constructor will expect a reference pointing towards canvas element as an argument. Inside we convert it to a class property. Take canvas passed as an argument and convert it to this dot canvas property on this instance of game class. From there, we can extract canvas width of 600 pixels and canvas height of 800 pixels. This is very important. And these values will be needed all over our code base. Because for example, player and projectile need to be aware if they are inside or outside the visible canvas area. Game object will have a custom method. I call for example, render. This method will run 60 times per second, drawing and updating everything. First, let's just put a consolo in there. I create an instance of game class using the new keyword on line 14. I can see it expects canvas as an argument. I pass it canvas from line 25. If I consolo this new game variable, I can see an instance of my game class. If I open it, I can see these properties perfect. I can also call that custom render method we wrote on line 19. And now I can see it's correctly consolo in width of 600 pixels and height of 800 pixels. Our game is set up ready and working. I want to draw and animated The player player class constructor will expect a reference to the main game object from line 13 as an argument. Because we need access to width and height and many other things that will be sitting on the main game class, I need access to all these properties from inside the player class. Keep in mind that by doing this, I'm not creating a copy of the main game object. I'm just pointing to the space in memory where the game object sits from inside the player class. I'm saving that reference as this dot game property width of the player will be 100 pixels. Height will also be 100 pixels. For now, horizontal x coordinate will be 200 and vertical Y coordinate will also be 200 pixels. Let's give it a custom draw method. It will expect a reference to context to specify which canvas we want to draw on. I do it like this to keep each class as self contained as possible inside we will take that context from it. We call built in fill rectangle and we give it x, y, width, and height. The current player position and size. I will structure my code in a way where everything sits on the main game object so I can draw and update everything from there. Inside the game class constructor, I create a custom dist player property and I set it equal to an instance of player class. Using the new keyword, player expects a reference to the main game object. I passed this keyword because here we are inside that game class. Now that we created the player, we can draw it by calling draw method from line nine. This player from line 27 draw. I can see that draw method expects context and I will be calling this Phil rectangle method from context. I also know that Phil rectangle method is sitting on my CT X variable down here. I pass CTX to render, render will expect that value as an argument and it will save it as a variable called context. I will pass it along to Player Draw like this method already expects context. And that's how this fill rectangle can be called. Here on line ten, nice, we are drawing a black square representing the player. I can change x and y coordinates to move the player around. What if I want the player to be in the middle horizontally? This game dot width times 0.5 Then we need to offset that value by a half of the width of the player. Now it's perfectly centered vertically. I want the player to sit at the bottom of the game area. The height of the game minus the height of the player. Perfect. We have a working game object and a player object. I want to make the player move left and right. As we press arrow keys on the keyboard, I give the player this dot speed property. I want it to move, for example, by five pixels per animation frame. I give it an update method that will update horizontal position of the player by its speed. To run this code, I have to call it from down here. Nothing really happens because this code runs only once. To create some movement, I need to draw the player update its position, draw it again, update it again, and so on. Let's create animation loop. Custom function. I call animate. I put game dot render inside. Then we call request animation frame sits on the main window object and I pass it animate the name of its parent function to create a loop. If I delete window dot here, it will still work. Javascript knows where to find this method. We call animate. We draw and update the game, and we trigger animate again. This will repeat over and over. I just need to actually call animate to trigger the first loop like this. We see old paint. I only want to see the current animation frame. Between every loop, I will clear the entire canvas from coordinate 002. Canvas with canvas height. Nice, the player is moving to the right, five pixels per animation frame. 5. Keyboard controls: If I set speed to minus one, the player moves to the left one pixel per animation frame. If speed is zero, there is no movement. Let's add keyboard controls. All the code inside a class constructor gets automatically executed at the point when we create an instance of the class using the new keyword. Normally, we only use the space to give our object properties, but we can actually put any code in there that we want to run at this point when this particular object is created. For example, if I do this event listeners will be automatically applied. When a new instance of game object is created, I create an event listener for key down event. Callback function has access to autogenerated event object that contains all different properties and information about the key down event that just fired. To use it, we just have to give it a variable name here and Javascript will know what to do. I will call it for event inside. I will consolo. I save my changes, I select Canvas element, and I press something on my keyboard. Keydown event fires and autogenerated event object is displayed in the browser console. If I inspect it, I can see all kinds of information. Today, we care only about this key property. Right here you can see I pressed letter on my keyboard, in this case if I consolo key. Now when I press random keys, the name of the key that was pressed will be displayed. Make note of these values. Notice how it spells arrow keys, because we will need these values. Now we need to make sure we use the exactly same spelling, including lower and upper casing. On my main game object, I will have an array called this dot keys. When a key is pressed down on key down event, I will add the name of the key that was just pressed into this array. When the key is released, we remove it. I take this dot keys here and I call push method. I will push dot key the name of the key that was pressed into the array. I save it and I test it. When I start typing on my keyboard, I will get a console error. It is because we are placing event listener that sits on a window object inside our custom game object. In here, I'm trying to access this dot keys property that sits on the game object. But this callback function doesn't actually remember where in the code it was originally declared, it doesn't remember its lexical scope. We need to bind the keyword so that it points towards the game object from inside this callback function. Or alternatively, we can use ES six arrow function syntax. Arrow functions automatically inherit this keyword from the parent scope. Now this dot used here correctly points to the game object, and my code will work. Scope enclosures are advanced programming topics. If you are a beginner, you don't have to fully understand it at this point. It will make more sense eventually. Just keep writing code. I'm cons logging this dokey and we can see that it grows larger and larger as I press more and more keys. Also I reload and notice that if I keep pressing arrow up, it will add it over and over again. I only want to add one entry per each key. If arrow up is already in the array, don't add it again. In Java Script, index off method can be called on an array. It returns the first index at which a given element can be found in the array. Important thing to remember is that it returns minus one if the element is not present. Knowing that, we can say if this key index of dokey is equal to minus one, if the key that was pressed is not present in this dot keys array. Only then push the key into the array. Now I can press arrow down over and over, and it will only be added to the array once perfect. I also want to remove the key from the array when the key is released. When key up event fires, I copy this code block. To make it cleaner, I create a block scoped constant variable, here called index. And it will be index of the key that was released inside this dot keys array if index is more than minus one. Meaning that if the key that was released is inside this dot keys array, which it always should be. By the way, we will use splice method to remove that entry, that key, from this dot keys array. Built in Java script splice method can be used to replace or remove existing elements from an array. If key is found in the array I call splice, I find the index of that element in the array and I remove it. Splice can be used to remove multiple elements. We have to pass it one here because we want to remove only that one element we found in there. Okay, so I press Enter Key on my keyboard. Entry is not present in this dot keys array. We push it in there, I release Enter. We find the index of that entry in this dot keys array and we remove it using the splice method. I press arrow up, It's added, I release it. It's removed. I type a bit more. It works well. Great. It's a good practice to always remove consolo when we don't need them anymore. Now on the main game object, we have this dot keys array that keeps track of keys that are currently being pressed down. Have access to everything on the game object from inside the player object because of this dot game property here inside update method on player class. I can say if this game dokey index of arrow left is more than minus one, meaning that arrow left was pressed, keep producing horizontal position of the player by distort speed from line eight, making it move to the left. Another if statement arrow right and we say plus did speed making it move to the right. Now I need to set the distort speed to something other than zero. Here, for example, five pixels per frame. Now I can press left and right arrows, and player is moving left and right. The advantage of this code structure is that we can easily boost player speed. Or we can slow the player down by changing this speed property on line eight. The problem is that the player can move all the way outside the game area. I will set speed to ten pixels per frame. For now, this is where we handle horizontal movement. I will introduce some horizontal boundaries here. If this x the horizontal position of the player, the top left corner of the player rectangle is less than zero, x is zero, this will create a hard left boundary L. If because the player can't be touching left and right the game area in the same animation frame, we can use L if here, if x is more than the width of the game minus the width of the player, x is equal to the width of the game minus the width of the player. This will create a hard boundary on the right side. I test it, the player can't move outside the game area anymore on both sides. Nice. 6. Object pool: Now that we have keyboard controls, I want the player to shoot lasers when we press something. Projectile class will handle that. In a game like this, we will shoot a large number of projectiles. We could create a new projectile object each time and discard it when it collides with something or when it flies off screen. But as I explained in the previous lesson, creating and discarding large amounts of objects creates memory related performance issues. In this game, we will have only ten projectile objects in total. And we will re, use those same ten objects over and over, massively improving performance. The performance benefit will become especially apparent in more heavily animated parts of the game. Believe me, this game can get very busy and animated when waves of enemies start coming. We need to make sure we optimize performance of our games. We will achieve that by using object pool design pattern. Each projectile will have width, height, x, y, and speed properties. Because we want to turn this into a re, usable object pool member, we also have to give it this dot free property. When this dot free is true, projectile is sitting in the pool ready to be used. It's currently not playing an active role in the game. It's not visible. When this dot free is false. It means we pulled it from the pool and we are using it. It's no longer free, it's no longer available. The object pool design pattern is a creational design pattern. It allows us to avoid performance issues related to automatic memory allocation and garbage collection processes that trigger when we create and destroy large amounts of Javascript objects. We will instead create a small pool of ten projectile objects. And we will pull them from the pool when we need them. When the projectiles collide with enemies or when they fly off screen, we just return them back to the pool. We reset their properties and we make them available to be pulled out again, they are needed. This will completely remove the slowdown caused by memory allocation when we create objects one by one. Also garbage collection process that automatically and periodically clears objects that are no longer referenced in our game from memory will not trigger at all because we will not be discarding those projectiles. There is more to object pool design pattern than this, but this class is for beginners. Today I will show you how to do a very simple but powerful implementation in a real working project. If you want to read more about it, I'll link some good articles in the description below. We give it a draw method, but we only want to draw active projectiles only if the projectile is currently not free. Same goes for update. Any code inside update method will run only for the active object pool members. Only if free is false, exclamation mark means false if projectiles are not active, if they are just sitting in the pool waiting to be used, we will not draw them and we will not update them. If projectile object was pulled from the object pool and it is not free. Right now, we will draw a rectangle representing the projectile, the update method for all active projectiles. We will make them move upwards in the negative direction on the vertical y axis. I want them to move relatively fast. Let's try 20 pixels per animation frame and see what that looks like. Each object pool member needs to have two helper methods. A method that will run when the object is taken from the object pool. I will call it start. Another method that will run when the object is no longer needed and it's returned back to the pool of available objects. When we start using the object we set free to face, the object is being used, it's not available in the pool anymore. Reset method will return it back to the pool by setting its free property to true. Which means because of these two checks, the object will stop being drawn and updated after reset method runs. I hope it makes sense leave a comment if you understand it or if you need more in depth explanation. You can just leave a comment with a simple thumbs up emoji. If you understood it well, I will know what you mean and everyone else will be confused by that comment. This is the projectile class. It's an object pool member and it has everything it needs to create object pool design pattern in our code base. Now we just need a way to create that object pool using this projectile class. We will do it inside the main brain of our code base. Here in the game class, I give it a property called this Projectiles pool, and I set it to an empty array. Number of projectiles will be ten. I want to use only a very small number here. It will work well for gameplay in this case as well. I will show you why I want only ten projectiles when we have some animation going. Object pool design pattern needs a method that will fill the pool with ten inactive projectile objects at first. This way we pre allocate the memory for old objects in one go, which is good for performance. It's faster to do it this way and to create all of the objects in the pool at once rather than if we make Java script look for free space in memory for each projectile separately, one by one as and when we need them. This is a very basic way of explaining how and why object pool design pattern solves memory allocation issues by reusing them instead of deleting them, we also completely avoid triggering garbage collection process. Another performance benefit custom method I call create Projectiles. It will run ten times. Each time it runs, it takes this projectiles pull and it will push one new projectile object inside created us. In the class we wrote on line 23, we need one last helper method. A method that will allow us to take one free projectile object from the pool when we need it. I call the method, for example, get projectile inside. We will cycle through the projectile pool one by one. As soon as we find one element with three property set to true, we return that element and we stop searching. The return keyword will stop execution of this four loop. I want to create projectiles automatically. Here, when an instance of the game class is created, Projectiles pool is created and automatically filled with ten inactive and ready to be used projectile objects. Let's check if it worked by consolo. In this projectiles pool, I can see it's an array with ten elements. I just open one and I check to make sure I don't see any undefined or non values which would indicate a problem inside my projectile class. All is good here. Projectile has a start method that will run when we get the projectile from the pool. And we want to start using it in the game because projectile will be flying out of the player. Start method will expect X and Y coordinates of the player as an argument, it will set this dot and this y of the projectile to the current x and y coordinates of the player. Finally, to complete this big logic loop, we give the player a custom method called shoot Inside I create a block scoped constant variable called projectile. And it will be equal to get projectile method we just wrote on the main game class here on line 92. It will search through the projectile pool if any of the ten projectiles is free and available, it will give it to us if all ten projectiles are currently being used in game, it will not find any free one. So we would get an error here. Only if we found the projectile and it's not undefined, we will call start method on that inactive projectile in the pool to activate it. We know that start method expects x and y position of the player. I pass it dot x dot y. We are passing the current x and y position of the player wherever the player is when start method runs, start method expects it. It sets player x and player Y coordinates to x and y coordinate of the projectile. And it activates it by setting its free property to falls, meaning that the code inside draw and update methods will pass this check. It will start running drawing and updating the projectile. How do we trigger this custom shoot method we just wrote? I could for example come down here and inside key down event listener. I say if the key that was pressed is enter, be careful about the spelling. Lower and upper case letters here are very important. You can consolo key from here to see how any particular key value is spelled. Maybe I want multiple different attacks. Basic shot will be triggered when we press number one on the keyboard. In this case, numbers are in number in this context is a string data type. When number one is pressed on the keyboard, player shoot method runs. To actually see it, I need to cycle through all ten projectile objects inside projectile spool array and draw and update them. I do it from down here. This projectile spool for each projectile object in the array, we call its update and we call its draw method. We know that the draw expects context. We just pass it along the context value from line 84. That context value is expected here. If projectile is activated, its free property is set to false. Context will be used to call phil rectangle method that will draw the projectile for us. I save my changes and I press one on the keyboard. Shoot method runs. We get a free projectile object from the object pool and we trigger its start method. Projectiles will always start from players current x and y position, even when the player moves around. Because we are passing those current player coordinates to the start method. Here I can only shoot ten times. And then we used up all the objects in the object pool and I can't shoot anymore. I want projectiles to reset and become available in the pool again when they fly off screen. If the vertical y coordinate of the projectile is less than zero minus the height of the projectile, if the entire projectile has moved behind the top edge of the screen, we call reset method from line 52. Reset method will set free property on that projectile to true returning it back to the pool, making it available again. Now I can shoot nonstop. If I shoot very fast, it will give me ten projectiles in a short burst. As they leave the screen, they reset and they will be able to come out again. Perfect rectangles on canvas are drawn from the top left corner. Player X and Y is this top left corner. Actually, I want them to come out from the middle of the player horizontally. We pass it x of the player plus half of player width. It's still not perfectly centered, which becomes even more obvious if I make the projectiles wider. Maybe my secondary attack will look something like this. I need this to be centered over the player, no matter what shape the projectile is. I will do it from here, inside the projectile class. Because here we have access to the width of the projectile itself. We can offset the horizontal position coming from the player by a half of projectile width like this. Now, no matter how narrow or wide the current projectiles are, they are always coming exactly from the middle of the player horizontally. Let's do eight pixels for now. Amazing work. We have the player that can move around and shoot projectiles. The techniques we just learned are extremely useful and powerful and you can use them to make hundreds of different games if the player we have is very wide, for some reason, if I stop player when it touches the edges like this, we will struggle to shoot enemies that are closer to the edges of the game area. We will not be able to reach them with our basic attack. This can create all kinds of chal***ges in how we design our game. I will fix it here in horizontal boundaries area. I will actually allow the player to hide behind the edge of the screen until half is hidden. Only then we will introduce stop boundary. Now I can reach enemies all the way to the left. I will also do this for the right edge of the game area. Now no matter how narrow or wide the player is, our basic simple laser attack can reach everywhere and enemies have nowhere to hide. Perfect. 7. Enemy Waves: Speaking of enemies, this will be interesting. Let's create enemies that come at us in a grid formation. And every time we defeat one wave, a larger wave of enemies will come. Before I do that, let's give our game some a background. I'm giving you a complete polished and professional set of high quality to the art assets for this project. You can download everything in the resources section below. Take the background PNG image you can find there and put it inside your project folder, Then use it as a background property. We can actually do this part with CSS. Css is GPU accelerated. Doing it this way is faster performance wise then redrawing the same image over and over on Navas as our game animates. Now my canvas drawings are too dark against that new background down here. When everything is loaded and navas is set up, I set fill style for everything drawn on navas too wide. For now this is fine. I will create individual enemies using our custom enemy class. They will need access to some methods and properties that I put on the main game class. We will have a reference to the game class from here as well. Like this. There are a few challenges we have to solve here. Because we want enemies to move in a grid and we want them to move in the same direction. I want the entire wave of enemies to follow the same movement pattern. We will have to stop and think about how to organize our code. To achieve that each enemy, actually all objects in our game need to have width, height, x, and y properties, mainly for collision detection purposes. Custom draw method will take context as an argument and we stroke rectangle representing each enemy. For now, I was going to make enemies into a reusable object pool as well. But I want to keep this class beginner friendly and combine an object pool with the grid logic we are about to write could become hard to follow. For now, enemies will be very simple basic objects, no object pool functionality here. For now, update method will move the enemy. But if I want all enemies to move in a grid formation, in the same movement pattern, we can't have individual speed here and update each enemy separately. Position value of the entire wave of enemies will have to be stored somewhere in one place in our code. And each enemy will know where it sits in relation to that value. As the wave moves, all enemies will move with it. Let me show you exactly what I mean. Create a wrapper class called Wave Constructor. Again, will need access to properties and methods on the main game object. We know that all objects in our game need to have width, height, x, and y position. Let's set position to 00 top left corner of the game area for now. Here inside the game class constructor, I remove this consolo. Each wave will have a set of enemies organized in a grid. The first wave will be a grid of nine enemies organized in three columns and three rows. I also need the enemy size, the size of each individual enemy to be globally available, all over my code base. Because we need to be aware of it in multiple places in the code. For now, each enemy will be a square of 60 times 60 pixels. I want the entire grid of enemies to bounce between the left and right edges of the game area. Each time the wave of enemies touches the edge, it will jump one step down, closer to the player. The width of the entire wave of nine enemies organized in three rows and three columns will be this dot game. Dot columns from line 95 times this game enemy size from line 97 height will be this dot game do rose times enemy size. Like this render method will draw and update that entire wave of enemies. It will need context as usual, then we will use that context. And for now we will stroke rectangle representing the entire wave area. Just bear with me, it will make more sense in a minute. Each wave will contain a certain number of enemies depending on didot rose and did columns value. We are starting with three times three. The first wave will have nine enemies. Each time we destroy all enemies in one wave. Next wave will be automatically triggered. We will keep all active waves inside didot waves array on the main game class. Immediately as we create game class, the first wave of three times 39 enemies will be automatically created and pushed inside this dot waves array. I passed this keyword to represent the main game object we are inside of right now. It is expected here and converted to this dot game class property. From here we have access to columns, rows and enemy size. Now I can take didot waves array, we pushed one wave inside. Already I call for each Wave object inside this waves array. Currently there's only one inside. We will call it surrender method. We pass it context. We can see the wave being drawn here, D stroke style to wide, so it's easier to see it line with, for example, 35 pixels. Size of the wave will adjust to fit all enemies it contains. If we have five columns and eight rows of enemies, 40 enemies in total, they will be arranged inside this area. The entire wave of enemies will move as one unit. The speed will be on the wave object. For every animation frame, we increase horizontal position by speed if x is less than zero or if x is more than the width of the game minus the width of the wave. Meaning that whenever the wave rectangle touches the left or right edge of the game area, flip its horizontal speed to its opposite value. This will make the wave bounce endlessly left and right. That worked. Let's make it three times three. Vertical speed will be zero whenever it touches one of the edges. I want it to jump by enemy size down vertically towards the player. I cut this line and I paste it down here. And I also increase vertical y position by speed y. When we touch the H like this, speed y stays high and the wave keeps moving down. I only want it to jump by enemy size in one animation frame and then return back to speed y zero. Yes, this is the movement pattern I was looking for. We have a wave that moves left and right and down over the game area. It will contain a grid of enemies. Each enemy will move with the wave using x and y position of that wave, plus relative horizontal and vertical position of the individual enemy within that grid. Within the wave, I will call those values this position x and this dot position Y. Position X and position Y is the position of the enemy within the wave. Each enemy has to know exactly where it sits inside the grid. Width of the enemy will be coming from this value from line hundred and 11, I set it to 60 pixels. This game dot enemy size. For width and height as well. Enemies will be square shaped. X and y will be 00. Initially, when we create an enemy, we pass it as an argument relative position between the enemy and the entire wave. Position x and position y values will determine where in the wave relative to the top left corner of the wave rectangle. This particular enemy sits position x and position Y past as arguments will be converted into class properties. Here update method will take x and y position of the wave as arguments. And it will set x and y position of the enemy relative to that current value. Exposition of the enemy is position of the wave plus relative horizontal position of the enemy in that wave. Y position of the enemy will be vertical, Y position of the wave plus relative vertical position of this particular enemy in the wave. There might be a better way to structure this code. I just came up with this. Let's see how it works for us. Each wave will have its own enemies array. We give it a custom create method inside, we will have a four loop. We want to organize something in a grid, which means we will need two nested four loops loop inside of another loop. Let's write it first and then we explain how it works. The outer four loop will handle rows as we go down row by row. Vertical y coordinate will be increasing. The inner for loop will handle columns as we go from left to right. Inside each row, horizontal x coordinate is increasing. Let's say we are here. This is the current enemy square 60 times 60 pixels row is zero. In the outer loop, we enter the inner loop and we cycle through all horizontal positions Within that row, we reach the last column. We exit the inner loop, we enter the outer loop, we increase vertical Y position and we jump to the next row. Again, we enter the in loop, We cycle through horizontal positions through the columns from left to right. We exit the inner loop, enter the outer loop, we increase y and jump to the next row. We enter the inter loop cycle through all horizontal positions. There we repeat this over and over until we created the entire grid of the entire wave. I need to account for enemy size when creating enemy X and enemy Y properties. I could have also alternatively jumped by enemy size value here and here. The result will be same. Each time we jump to a new cell in the grid. We take this enemies wave and we push one new enemy object inside. We can see that enemy class constructor expects game and relative X and Y position of that enemy in the grid. I pass it this game from line 78. I pass it enemy X and enemy Y. Okay, When we create a new wave, we have a look inside game class constructor to see the current value of rows and columns. Based on that we create a grid of enemies. I want create method to automatically trigger when we create a new wave. I call it here, that means that as soon as we create an instance of wave class, this enemy's array will be automatically filled with enemy objects. And their X and Y coordinates will be organized in a grid inside render. I can now take that array and for each enemy object inside, I call its update method and it's a draw method. I pass draw method context as usual. Here we can see that the update method expects X and Y position of the wave so that I can use it to position enemies in a grid like formation. Whenever I call enemy update, I have to pass it X and Y position of its wrapper wave object to make sure all enemies move around the screen. With it we are drawing three times three enemies. Remove this rectangle that strokes the entire wave. That was just to help us visualize what was happening. We are still drawing the enemies. We have a wave of three times three enemies and they move around the screen in a synchronized way. Perfect. I want the enemies to come wave by wave. And I need each wave to start up off screen and float into the game area. I said the initial y coordinate of the wave to be zero minus the height of the wave, meaning that initially it will be hidden behind the top edge of the game area. The wave will be created off screen, and I want it to quickly float down until it's fully visible. Then it will start its left right motion pattern. If this Y is less than zero, increase Y by five pixels per animation frame. It will float in like this and starts bouncing left and right when all rows and columns of enemies, the entire wave is fully visible within the game area. I can test it by changing the number of rows and columns. You can see it still works. It still floats down until all enemies in that wave are visible and can be targeted by player lasers. I try five columns and seven rows, which will give me a wave of 35 enemies. 8. Collision detection: This is going really well. We have the player, projectiles and enemies. I want the projectiles and enemies to interact. When an enemy gets hit by a projectile, enemy is destroyed, projectile object is returned back to the object pool. Every object in our game has x, y, width, and height properties. Let's create a re, usable collision detection method, which will compare any two rectangular objects we pass to it as arguments. And it will return true or false depending on whether or not these two rectangles collide. For the purposes of two de, collision detection, rectangles need to be axis aligned. If they are rotated in any way, we would have to treat them as polygons. Collision detection would need to be a more complex technique such as separating axis theorem formula. Today, all the rectangles will be axis aligned, non rotated. So we can use the simple and the most straightforward collision detection formula between two axis aligned, meaning non rotated rectangles reusable custom check collision method. We'll take two arguments, rectangle A and rectangle B. There are many articles online about this technique. I can reference them. I will leave some links in the resources section below. The formula always checks if rectangle A is within the boundaries of rectangle B horizontally and also vertically. For that, we need to perform four checks comparing all four edges of the rectangle on. If all four of these checks are true, have a collision else, even if one of them is false, there is no collision. Let me show you how that works. By the way, this formula is very cheap when it comes to performance because the calculations are so simple. If our game design allows it, we should try to use it. Some games, of course, demand more complex collision detection techniques. It's not always suitable for our project. Today it's perfect. We need to check four things. First, we check if the horizontal position of rectangle we pass as argument a here is less than horizontal position of rectangle B plus the width of rectangle. We are checking if this is to the left of this. At the same time, double percent operator. We also need to check if the horizontal position of rectangle a plus the width of rectangle a is more than horizontal position of rectangle. We are checking if this is to the right of this. If both of these checks are true, we know that rectangles collide horizontally, but they can still be far away from each other vertically. We need to do the same two checks, but this time for the vertical y axis. I check if the vertical position of rectangle A is less than vertical position of rectangle B plus its height. If this is above this one last check, We check if the vertical position of rectangle A plus its height is more than vertical position of rectangle B. If this is below this. Only if all four of these checks are true, we have a collision. If all are false or at least one of them is false, we know there is no collision. We know that the two rectangles are far away from each other, at least in one direction. I can actually simplify this and I can make this method automatically evaluate this expression and return true or false directly. This way I can just call check collision passed two rectangular objects, for example projectile and enemy and it will directly return true or false. For me this is our re usable collision detection method. Keep in mind that any objects we pass as rectangle A or rectangle need to have x, y, w and hyde properties. For this code to work, I want to use a custom check collision method. Now we hold all ten re, usable projectile objects Here inside projectile pool array, enemies are stored inside enemy's array separately. For each wave here, those enemies are created using the class, the blueprint we wrote here on line 57. So it makes sense to put that collision check in here. Every time update method on each enemy object runs, we will compare x, y within height of that particular enemy with all ten projectile objects. We will only check against the active projectiles projectile pool. For each, for each projectile we call our custom check collision method. We know it expects rectangular object a and rectangular object as arguments. We know both of these objects need to have x, y, width, and height properties for check collision method to be able to work with them. I pass it this enemy object as rectangle A and I pass it all ten projectiles one by one as we cycle through projectile pool. For each method we wrote check collision method to directly return true or false. So I can just say if and wrap it in brackets like this. If this enemy and projectile collide, this code block will run side. We delete the enemy. I said it's marked for deletion property to true. Also I need to declare that property in enemy class constructor Up here inside render method on wave object, we will filter enemies that were destroyed out of enemy's array. Built in array filter method filter method will create a copy of a given array and that filtered copy will contain just the elements that passed a certain condition here I'm basically saying create a copy of this dot enemies array and only allow inside elements that have marked for deletion property set to false. Then override this original dis dot enemies array with that new filtered array. This way I'm removing all enemies that collided with projectiles because those enemies have marked for deletion property set to true. I'm getting a console error. It is because I misspelled projectile pull here. Yes, it's supposed to be spelled projectiles pull with an S. When a new wave of enemies comes, you can see that the bottom left enemy is already destroyed. It's because all my inactive projectiles are initially sitting in that corner at coordinate 00. We are not drawing them and updating them, but we are still calculating collision between those inactive projectiles and enemies. I fix it by only checking collision if projectile free is false. If the projectile is currently active, we want to ignore inactive projectiles when it comes to collision detection, I also want to reset that projectile and return it back to the pool. It collides with an enemy so that each one projectile can destroy only one enemy. We have a reset method here for that which will set free property to true returning projectile back to the pool of unused available objects. When collision between enemy and projectile happens, I call reset method on that projectile to deactivate it. Yes, this is the gameplay I was looking for. When collision between enemy and projectile happens, enemy gets deleted and projectile object gets returned back to the object pool. 9. Score and status text: I want to draw status texts such as score wave counter player lives or how much energy we currently have for lasers and special attacks. I will do all of that inside draw status text method, I call built in fill text method which takes at least three arguments, the text we want to draw and x and y coordinates of the anchor point in relation to which the text will be positioned. I call it here inside Render, and I want to draw it behind enemies. So I draw it first. It's just my choice. You can draw it on top if you want. I passed context along, and here we go. I set font to, for example, 30 pixels impact for nice, big and easy to read letters. We will keep the current score as a variable on the main game object. It will start at zero. Inside field text, I will add that dynamic variable value next to the text like this. Now I want the score value to increase by one when we destroy an enemy here. When projectile and enemy collide, we take this game score and we increase it by one. Like this. Nice, I'm shooting enemies and I'm increasing my score. Perfect. The game will be lost if any enemy touches the bottom of the screen. For each enemy, I will check if its vertical Y position plus its height. The bottom boundary of enemy rectangle is more than this dot game dot height, the bottom boundary of visible game area. If that happens, I set this game game over to true and I destroy that enemy by setting its marked for deletion property to true. For now, I need to make sure I declare that game over property here. Initially it will be false. If game over is true, I want to draw some text. As you can see by default canvas text is left aligned. I want this game over message to be center aligned. Font will be 100 pixels. Impact text will say game over in capital letters. And it will be exactly in the middle of the screen. Width of the game times 0.5 and height of the game times 0.5 Nice, we have big game over text in the middle of the screen. As soon as enemy touches the bottom of the game area. The problem is that this text line and font properties change the entire canvas state. And now the same text style applies to score fill text on line 194. I will wrap this entire code block between safe and restore built in canvas methods. The safe method saves canvas state, including fill style text line font and all other canvas properties. It creates a safe point, like in a video game. It remembers what values all canvas properties have. At this point, then we can alter canvas settings in any way we want. Then when I call restore, it will return all canvas properties to what they were when safe method was called. What is happening? Now we save canvas state, we draw score at 30 pixel size and left aligned, we set text 200 pixels center aligned, we draw game over and we reset those settings. Back in the next animation loop, when score is redrawn, it is back to 30 pixels left align. It's an endless animation loop we have here. I hope it makes sense, we can take it even further and since we wrapped all the status text between safe and restore, we separated it from the rest of the shapes drawn on canvas. I can also give it some shadows here. Shadows will only be applied to the text, but not to enemies, projectiles, and player shapes. To display canvas shadows, we need to define at least three out of four available properties. Horizontal distance between the shape and the shadow. Vertical distance, color of the shadow. And we can also apply blur using shadow blur property. But it's optional. Blur is performance expensive. It involves calculating opacity and sub pixel values. I will avoid it today. We are counting score and we are drawing game over message nice. When I destroy an entire wave of enemies, I want a new larger wave to come automatically. We will count them and players can chal***ge themselves to see how many waves of enemies they can defeat. Wave count will start with a wave number one. Like this, we will draw the wave number here, like this. Inside our draw status text method vertically, I set the text to 60 pixels. No, 80 pixels from the top. Yes, the first wave will be a small grid of two times two enemies. When I destroy these four enemies, I want a new larger wave to appear. We will handle that logic inside a customer method. I call for example, new wave. You can think about this technique as a very simple level mechanics. When you defeat a wave, larger, more difficult wave of enemies will come a new level. We can add any conditions and properties of that new wave here. First, I can increase the size of the wave by one column and by one row. Let's try that. I will increase columns and row values by one and I will push new wave object into this waves array. I pass it a reference to the main game object as an argument because it expects it as we can see here on line 91. Because we increase columns and rows value, these lines of code will ensure that the next wave is larger. I also need to make sure that each wave triggers the next wave only once. So I give it a flag that indicates whether or not it already triggered the next wave. Initially, I said it to false. Each wave contains enemy's array that holds all currently active enemy objects in that wave. As we run for each method on all wave objects in this waves array, I check if the ***gth of enemy's array on that wave is less than one. At that same time if the flag I called, next wave trigger hasn't been activated yet. And only if game over is false. Because when game over happens, I want new waves to stop coming. If this entire expression evaluates as true, we entered the if statement block inside. I call new wave method we just wrote. We will also increase wave count by one. Finally I sat next wave trigger to true, preventing this particular wave from triggering any more new waves. I test it, we have a wave of two times two enemies. If I defeat all of them, we immediately get next wave of three times three enemies. Perfect it is because here in new wave method, we always add one more column and one more row each time new wave of enemies is created. If I want the waves to grow a bit slower, I want to randomly in 50% of the cases to add a new column, or in the other 50% of cases, I want to add a new row. We can do that for example. This way math at random called on its own, like this, will give us a random value 0-10 included, one excluded. I can say if math at random called on its own is less than 0.5 roughly in 50% of the cases increase the enemy grid by one column, else add one row instead. This way the waves will still grow but a bit slower. It will take more time before they fill big part of the screen and the game becomes more difficult later. I will also add boss battles, features randomly. Instead of a new wave, we could just get a big boss with a lot of health. When we defeat the boss, waves will start coming as usual. I will also have to make sure we are only adding new columns to a certain point. Let's say until the width of the entire wave is less than 80% of the screen width. If we allow it to go more than that, the game can quickly become too fast and completely unplayable. You can try to play the game at this stage where we have no limitation on columns and rows. See what I mean. I will also only add rows if the height of the entire enemy wave is less than 60% of game height. I tested by setting starting grid to five times five enemies new wave. And I can see it added a new column. Let me quickly deal with them. I need to add some more powerful weapons later. Now it added a new row. We have a grid of six times six. Now it added one more row. We have a grid of six times seven. When we get to this stage, I want enemies to somehow react when they touch the player. The first step in that interaction will be to detect a collision between enemies and the player. If you check collision between this enemy and player is true set marked for deletion on that enemy to true to destroy it. Inside that if statement, we do another check if game over is false. If score is more than zero, we reduce score by one. We will punish the player for not being able to shoot the enemy at distance. I will also reduce player lives by one. Then I check if player lives variable is less than one. If it is, we set the game over to true. Nice player will start with let's say three lives. To check if it works, we will visualize the lives inside draw status text method. But let me show you a different way how to display them. Rather than just to draw a number that says three, I will create a four loop that will run once for each player life. Each time it runs, it will fill rectangle at coordinates 1010 within height of the rectangle will also be ten times ten pixels. Now I'm drawing three squares on top of each other. I want this to be a loading bar. I just multiply horizontal position Tams index of the four loop. Now the three squares representing player lives are drawn next to each other. This value is effectively spacing in between. If the width of the rectangle is less than the spacing, we will see them drawn as separate shapes like this height, maybe 20 pixels. I can also add left margin like this vertically. I position them 80 pixels from the top, 100 pixels from the top. If I let enemies hit the player, we can see we lose lives and then we get game over message. Each time we successfully defeat a wave of enemies, a new wave is created. We will give the player one more bonus life. I test it, I have three lives. I defeat the wave, yes, now I have four lives. I set the grid to five columns and 11 rows. I need to test something. When game over happens, I want to prevent the player from being able to get any more score points. We are giving these score points here. I will only do it if game over is false. Now if I get game over and I destroy more enemies, game score stays the same. Down here, I want to add one more line of text. I copy these two lines of code. Font will be 20 pixels. Text will say press R to restart. I move a bit down under the game over message. Now when game over message appears, we get another message that says press R to restart. Let's actually implement that feature. 10. Restart method: Restarting a game can be handled in many different ways. I usually do it when I finalize my basic code structure like we did here. At this point we understand our code base pretty well, and we understand what variables, properties all across our code base needs to be reset to a default value when the game restarts. Yes, I can also restart the game by simply reloading the browser window, but let's do it the proper way this time. First, I need to restart the player. And I can do it here from the player class. I will give the player a custom restart method here. I know that when we restart, I want the player to move back to the middle of the screen. I want to reset player lives back to three. There might be more things here to restart later after we actually animate the player spaceship. But for now, this is all we need to do in this area. On the main game class, we create the main custom restart method. From here, I will call the restart method we just defined on the player. I also need to reset game properties. I go up here inside game class constructor and I have to think which properties from here change values as we play the game. Therefore, there will need to be reset to default when we restart the game. I copy all of this code and I paste it down here. Enemy size will stay the same. I delete that. When the game restarts, I want to go back to a small grid of enemies, maybe two columns and two rows. I will delete all wave objects from this waves array in case there are still any. We will automatically push one new wave of two times two enemies inside. We reset wave counter back to one, reset score back to zero, and we set game over to falls. I should make sure that columns and row values are the same here as well. Because as I play the game, the number of columns and rows increases as I defeat enemies. Wave after wave. We need to make sure that the restart method resets the enemy grid back to this small size. Down here we have key down event listener inside I say if the key that was pressed is lower case R, we call the custom restart method. We just wrote the game. I destroy some enemies. We press R and the first wave comes out again. I play, the enemy grid is getting larger. I press R and we reset the game and enemies are back to the basic grid of two times two. Yes, this clearly works. You can use or operator here and you can have multiple keys triggering the restart method. For example, lower and upper case R. If you want to, I don't want the player to be able to restart the game unless we see the game over screen. We will only run the restart method if lower R was pressed. At the same time if game over is true, like this, now I'm pressing R and it's not restarting. I increase roles to ten just to get a quick game over, when enemies touch the bottom of the game area or when player lives get depleted. I see game over screen now When I press R on my keyboard, we actually reset the game Perfect. When I hold down number one to shoot, player will shoot all ten projectiles over and over very quickly in a single sequence. And it actually makes the game too easy and trivial. Maybe I want to prevent the player from doing that. And I want to make sure that each time we want to shoot the basic laser attack, basic projectile, we have to press the button again. If we hold it down, only one laser projectile comes out. We will add more powerful attacks later, which will shoot a massive laser ray as long as we hold a key down. But that strong attack will have energy cost attached to it. We can't have a Spam Mable super attack like this, otherwise the game is too easy and point less. I will create a simple flag here called fired. It means that attack button was pressed and one laser projectile was fired inside Key down event. I take this, I put it here. After that, I set this dot fired to true. And we will only call player shoot. If fired is false, it means it will only shoot one pair. Key down event. Then in key up I said this dot fired to false again. Okay, now one key press means one projectile. We have to release the key and press it again to shoot another projectile. Perfect. Well done forgetting so far. If you are watching the extended version, there is a code from this stage available to download. In the resources section, we have a very solid game skeleton. Our game has enemies coming in larger and larger waves. We use object pool to reuse projectiles and improve performance and memory management of our game. Have keyboard controlled player that gets a bonus extra life for each enemy wave we defeat. And we already implemented many other smaller features. It's time we talk about graphics and animation. In this project, we are focusing on optimizing performance. Let me show you how to make the game look great, but at the same time, how to use very lightweight animation system that will make sure our game runs smooth even on the oldest machines. 11. Beetlemorph enemy class: The first enemy type I want to implement is a basic space bug. A simple enemy with one life that explodes when we hit it. With a projectile, you can download the spreadsheet in the resources section below, Place the image into your project folder and include it inside index HTML file. Like this. Source is beetle morph, Png ID is Beetle moorphscriptGs. We declare our enemy class, I want to have multiple enemy types. I will put properties and methods that are shared between all enemy types on the parent enemy class. Here I will create a smaller subclass for each enemy type separately. There we will declare properties and methods that are specific only to that enemy type. We will do it using the extends keyword class. Beetle morph, extends enemy. The extense keyword used here makes beetle morph a child class of enemy parent class. We can also call this a subclass and enemy is a superclass. I will give this subclass a constructor as well when I create an instance of this class. First, I want to run the superclass constructor. First, I want to trigger all the code inside the parent enemy class constructor here. To call this constructor, I can see I need to pass it game position x and position y. Subclass constructor will expect the same arguments. And we will call superclass constructor triggering the code inside the constructor on the enemy class. We know we need to pass it these values along for that code to actually work. Now I triggered superclass constructor and once all the code inside here is executed, the code that contains properties shared between all enemy types, I can finally use this keyword inside here and give this subclass some properties that are specific only to this particular enemy type. Each enemy type will have a different sprite sheet image. This dot image here will be document dot get element by ID. We gave it an ID of beetle morph back in index HTML file. If your browser window is larger than mine, you can also see the sprite sheet here. I want to hide that IMG element. I give it display none with CSS, we only want to draw it with Java Script on canvas. We will draw that image here inside the draw method on enemy class. Whatever drawing code we put inside this method will determine what each individual enemy looks like. I will use built in draw image method which expects at least three arguments. The image we want to draw dot image and x and y coordinates where to draw it. Now when I save the changes, I will get an error. This error message means that Java script can't find the image I'm trying to draw. It's because I'm creating an instance of the parent enemy class. This class doesn't have didot image property. I need to instantiate the subclass and enemy class constructor will also be triggered from there. When we extend classes like this, Javascript will also create the usual prototype based inheritance behind the scenes. If I for example, call draw and update method from an instance of Beetle Morph class from the subclass, Javascript will not find that method on this child class and it will automatically follow the prototype chain up to the parent enemy class. It will trigger that draw and update methods from there. For Javascript to actually find this image property sitting on the child class here, I need to create an instance of Beetle Morph. Instead, as we just explained, Beetle morph child class has access to all properties and methods on the parent enemy class as well. We pass it game and the relative x and y position of that particular enemy within the wave within the grid. These properties are expected here they are passed along to enemy class constructor. All the code inside enemy class constructor will be executed. On top of that, we will add whatever code we have here that is specific only to the Beetle Morph class. Beetle morph is a subclass child class, enemy is a superclass parent class. 12. Sprite animation explained: We get this strange situation. It is because we are passing a draw image only three arguments. So it is drawing the entire image, the entire spread sheet we passed to it here at its original size. At these x and y coordinates, we can pass draw image optional fourth and fifth argument for width and height. And when we do that it will squeeze or stretch that image to fit that specified area. Now I'm squeezing all 12 frames of the sprite sheet into an area of one enemy, of one frame. We want to crop out individual frames from the sprite sheet. For that, we will need the longest version of draw image method which gives us the most control over the image we are drawing. We will pass draw image method nine arguments. The image we want to draw source source Y, source width, and source height of an area. I want to crop out from the source image, destination X, destination Y, destination width, and destination height to define where on destination canvas we want to place that crop out piece of image on to, let's say I want to crop out the area from coordinates 002, coordinates 2050. I want to stretch this cropped out piece of source image over a space of 60 times 60 pixels on the destination canvas. This is what we get. What if we crop out an area 00-5050 pixels? Ideally, we want to use the same size, so I will use, with height currently that's 60 times 60 pixels. I created the spreadsheet frames at a size of 80 times 80 pixels. Let's draw the images at the same size on canvas. Enemy size will be 80 pixels. We are setting width and height of the enemy to enemy size here. And then we are using that width and height in side draw image method here. Now we are cropping out exactly one frame from the source image. And we are drawing it at the same size of 80 times 80 pixels on canvas instead of hard coding coordinate 00. Here we will convert these into variables. I will put them on the subclass, because each enemy type might have a different number of frames. In the spreadsheet frame X will handle horizontal navigation around the sprite sheet. In this case, because of how I structured this particular spry sheet, we can see that this will give us distortion and explosion animation that will play when we hit the enemy frame. Y will handle vertical navigation around the sprite sheet. In this case, that will give us different variations of the beetle morph. You can see I created some variety. I created four versions with different wings, different armor, and different claws. It's just to make the game a bit more visually interesting. You can see that each enemy will distort slightly differently. And we will show different explosion frame when we hit them with the projectile. I could have made the explosion animation smooth out of many animation frames as I always do in my other classes. But today I want to show you how to improve performance with this sprite animation technique, where we use only a limited number of frames in each sprite sheet. It will give us a bit of a retro effect. And it will look good because animations will react to key presses and to game events. Let me show you what I mean. These are source X and source Y arguments passed to draw image method. They determine X and Y coordinates of the cropping area. Currently, we are cropping a rectangle of 80 times 80 pixels. Starting from coordinates 00, I can jump around the sprite sheet by w. And height like this, zero times width, zero times height is still this frame from coordinate 00. If I say one times height, here we are dropping from coordinate 080. Here we can see the second row in the sprite sheet with a different enemy variation, two times height will crop from here. Seeing another beetle morph, three times height will give us the last one. I can replace this value with frame Y. Source X will move around the sprite sheet horizontally. One times width will give us this cropping area. Two times width will give us this frame. If I increase it to three, we are outside the spread sheet and we are looking at a blank frame. It will still work and nothing will break, but we just don't see anything. I will use frame x variable here. Now we know that source y argument, this code determines a role. Well, if I want each enemy object to be randomly assigned, one of the four available visuals, one of the four available petal morph variations. I can do that simply by setting frame y to random value 0-4 There is no Road 3.5 for example, so I will need integers here. I wrap it in mask floor to round the number down. Now this line of code gives us either zero or one, or two, or three. We can see we are getting randomized beetle morphs in the wave. Perfect, That's vertical navigation. Now I want to also use horizontal navigation around the spreadsheet. And I want to play the frames like this. When enemy gets hit by a projectile, we go up to the parent enemy class. Because this behavior will be shared among all enemy types. We will give it a custom method. I call for example hit that will take damage value as an argument. I do it like this because maybe we will have weapons that hit for more damage. Later, we will have enemy types with more than just one life that need to be hit multiple times. Inside I decrease lives of the enemy by the damage. Each enemy type will have a different number of lives. Beetle Morph is a simple, basic, squishy enemy with only one life. I put that property here on the subclass. We also need to define Max Frame. In this case we have frames 01.2 Max Frame here is two. I will also create a property I call Max Lives and I set it to the initial distant lives value. We do that because even if the current enemy lives might be zero and the enemy was destroyed, I want the enemy object to remember its original maximum number of live, so we can reward the same amount of score points once we defeated that enemy. We will write that code in a minute. Up here, when active projectile collides with an enemy, we set marked for deletion on that enemy to true. I want to change this logic. Instead of immediately deleting the enemy, we will call this dot hit method we just defined. I pass it a damage of one like this. For now. Inside hit method, we are reducing lives of this enemy by this damage value. If you remember, after that I create a separate if statement and I say if this lives is less than one, once we hit enemy enough times to deplete all its lives, which in this case was very easy because each beetle morph has only one life. I want to trigger horizontal navigation around the sprite sheet to play this animation. This dot frame X plus plus. Every time we increase frame X by one, we check if the current frame X is more than max frame. We check if we played all the horizontal frames in the sprite sheet, only after we hit the enemy, we depleted all its lives. And after we played all horizontal frames of the sprite sheet, only then we are ready to set marked for deletion to true. Which will filter the enemy out of enemy's array. Because of the logic we wrote earlier, automatic garbage collection process will eventually delete it as it does with all variables that are no longer referenced anywhere in the code. I will also cut this line of code only once we destroyed the enemy. If game over is false and the game is still running, we increase score by the original amount of enemy lives. By this max lives, enemies that had one life will give one score point. We will have another enemy type with three lives later, that one will give us three score points when destroyed. Down here we can see we give Beetle Morph one life, so it will reward only one score point. The code, I can see that horizontal frames are playing, but they are playing very fast. We can barely notice what's happening. We are animating probably at 60 frames per second for every animation frame. We are increasing frame X by one, and we only have three frames. This whole animation plays out in a fraction of a second. We need a way to control the speed of sprite animation. I can comment out the rectangles around enemies, This looks better. I want the waves to move slower, maybe one pixel per animation frame. I also want the waves to start from the middle horizontally. The initial x coordinate of the wave will be the width of the game times 0.5 minus a half of the width of the wave. I want each wave to randomly move to the left or to the right from that middle position. I will do a little trick here. Horizontal speed is equal to an expression, so called ternary operator, the only Java Script operator with three operands. We will use it here as a simple one line L statement. If method random is less than 0.5 roughly in 50% of the cases set speed x to minus one L set speed x two plus one ternary operator used as an L statement goes like this expression to evaluate if true question mark, do this L colon, do that. We could have also used a regular FL syntax here, but this is faster. Now if I reload the project a few times, I can see that waves start from the middle, and randomly they will move to the left or to the right at a speed of one pixel per animation frame. When we hit an enemy, horizontal frames play, but they play very fast. How can we control that animation speed? Let me show you. 13. Animation timing: Built in request. Animation frame method we are using here has two special features. The first one is that it automatically adjusts the speed at which it serves the next animation frame. It adjusts it to the screen refresh rate because there is no point calculating and drawing more frames than the refresh rate of your computer monitor allows you to display. Drawing those extra frames would be a waste of performance because we wouldn't be able to see them anyway. The second special feature is that it automatically generates a time stamp which simply is a value of milliseconds that passed since the first request animation frame in the sequence was called. We will use those auto generated time stamps to trigger periodic events in our game. For example, I can update horizontal sprite frame in enemy sprite sheet only once every 500 milliseconds, which would be two frames per second. We will be able to set any frame rate we want. Let me show you how to do that. We will need a help er let variable I call last time. This variable will hold a value of a time stamp from the previous animation loop. So that we can compare it with the time stamp from this animation loop. And we can calculate how many milliseconds passed between the two animation frames. We usually call this value Delta Time request. Animation frame auto generates a time stamp and it passes that value to animate function here. All I need to do to use that value is to assign it a variable name. I will call it timestamp here. Now if you consolog this time stamp from inside Animate, you will see how it counts milliseconds from when the first loop started. 1 second is 1,000 milliseconds. Delta time is the number of milliseconds it takes our computer to serve one animation frame. It is the difference between the time stamp from this animation loop minus the time stamp from the previous animation loop. Once we calculated delta time, we will set last time to the time stamp from this animation loop so that it can be used as the old time stamp in the next animation loop. As the animation loop runs and request animation frame is generating new time stamps, we are always comparing the current time stamp and the old time stamp from the previous loop and that difference between them giving us delta time. We will need that delta time value inside render method. I pass it as an argument here on the main game class inside render, I make sure that the value is expected. I will consulate delta time from here to make sure it worked. If I scroll all the way up, I can see that the first two values of delta time are non, not a number. This might be a problem depending on how we plan to use the delta time value. This non here could break our code. Potentially, we are getting none because the first animation loop is triggered here, but that one doesn't have autogenerated timestamp value. Time stamp only gets generated when the second loop is triggered here by request animation frame. For the first loop, the time stamp is undefined and I'm calculating delta time undefined minus one, which is giving me none, not a number value. I can fix that simply by passing zero as the first time stamp. From the next loop, we will start getting proper autogenerated time stamps. Now when I scroll all the way up here, we get numbers all get here. As you can see, my delta time is around 16.6 milliseconds. It takes my computer around 16.6 milliseconds to update and draw one animation frame. 1,000 milliseconds divided by 16.6 is around 60. I can see that I'm getting animation speed of 60 frames per second. If you have some high refresh rate gaming screen, you might be getting much lower delta time, which also means that your entire game is running faster than mine. Because as we said before, request animation frame method automatically adjusts to the refresh rate capabilities of your screen. We can control the FPS of the entire game now here by simply saying only call render to update and draw the next game frame. If, for example 50 milliseconds have passed, which would give us 1000/50 is 20, it would give us animation speed of 20 FPS. Basically what I'm saying here is that we can now use this delta time value to trigger any periodic events in our code. Delta time is milliseconds. So we can say do something every ten milliseconds, do something every 100 milliseconds. We can do whatever we want. It could be updating the entire game every 50 milliseconds or something else. We can add a boss, a power up, or a special enemy every 15 seconds. That would also work. I will now show you how to use Delta Time to periodically update spread sheet frames in our code base. Because we want to slow down the animation that plays after we hit enemy with a projectile. We will also use this later to animate other things in our game in this low frame rate retro style that allows us to have spreadsheets with just a few frames to get a nice performance boost. It also allows us to time things separately. In our code base, I have player movement, projectiles, and enemies animating at full 60 FPS. But the speed at which the spreadsheet itself swaps frames will operate on its own separate speed. Let me show you how to implement that. I go up to the main game class here, inside the render method, I delete this consolo. Even a consolo like this in our game would affect performance negatively. It's good to use it for the bugging, but don't forget to always delete your consolo, especially the ones that run for every animation frame like this one does. I want to have a flag variable here on my main game class. This sprite update flag will always be false. It will only switch to true once every, let's say 500 milliseconds. It will switch to true for one animation frame. It will allow all sprite sheets in our game to update, then it will switch back to fall again until the next 500 milliseconds pass. I want to update all sprite frames in our game periodically. Let's say every 500 milliseconds, we can easily change that millisecond value to something else. Later we will need two helper variables. Sprite timer will count between zero and sprite interval. Every time it reaches sprite interval, it will set sprite update to true, and the timer will reset back to zero so that it can count again towards the next periodic trigger. I will handle sprite timing logic. Here I say if sprite timer is more than sprite interval, do something else. Do something else. If sprite timer accumulated enough delta time that it is now more than 500 milliseconds, we set sprite update the true. We reset sprite timer back to zero so that it can count again. Sprite update will remain true only for a single animation frame, because in the next loop, when the L statement runs, it will immediately set it back to false. This L statement means that sprite timer is less than sprite interval. In that case, we want timer to keep accumulating delta time until we accumulated more than interval Again, because delta time is the actual amount of milliseconds, these periodic events will trigger in the same interval. On slow and on fast refreshed screens it will be almost the same. It will not be exactly the same because when I reset sprite timer back to zero here, in most cases there will be a little bit of extra delta time that I'm not accounting for here, which will create some difference. I'm okay with that. If you want complete precision, take delta time that goes over the interval value of 500 here and assign that leftover value to the starting time here. Instead of setting timer back to zero, that should make it even more accurate. I don't think I need that level of accuracy for my game right now. I want to avoid unnecessary calculations for now. For maximum performance, now we have this sprite update property that once every 500 milliseconds, just for one animation frame, is set to true. The rest of the time it's set to false. We can use it to trigger sprite animation when we hit enemy with a projectile and when enemy lives are less than zero. Instead of increasing frame X in the spreadsheet immediately. We will only do it if sprite update is true. Let's test it. I shoot an enemy and every 500 milliseconds it plays the next animation frame perfect. Now we have a problem that the enemy is stopping projectiles until the animation finished playing. Once we hit the enemy and its explosion animation starts slowly playing, I want the next projectile to ignore that enemy, fly through it and to hit the enemy behind it. I do it by only checking collision between projectiles and enemies. If that enemy has more than zero lives. Like this, we have a complete control over the spread animation speed. Now I can change it down here, Let's say I want to make them animate a bit faster. Now they animate fast, but it's still slow enough for us to see the individual frames, which is what I was looking for. Normally, when I create my sprite sheets, I create complex animation loops with 20 or 30 animation frames. But sometimes if you have many enemies animating on screen at the same time, it can slow your game down using sprite sheets with less frames and controlling how fast we swap from frame to frame when animating these sprite sheets is a simple and performance friendly way how to deal with that chal***ge. 14. Player animation: I wanted to change the color of projectile lasers to, for example, gold. If I set Phil style like that, it changes the entire canvas state. Now all shapes on canvas that use Phil will use that gold color. I changed the width to four pixels, maybe just three. Yeah, that looks better. I want to restrict this Phil style only to this Phil rectangle. Cole, I will wrap this code block between safe and restore methods. That way any code that sits outside this area will not be affected by this fill style lasers are gold, everything else stays white. If I go back here to the beetle morph class and I set lives to three, I have to hit each enemy three times to destroy it. Each one rewards us with three score points. Everything is working as intended. I will set it back to one. I have a special plan for enemies that have more than one life. Because I want to draw and animate that damage step by step, each time we hit them to reduce their lives. We will get to that part later. It's time to draw and animate the player. What I want to do is for the player to react when it shoots a laser projectile. Later I might do also advanced attacks. I'm thinking something like this. And this. Notice how the player spaceship animates differently for each different attack type. At the same time, I also want to animate player jets, the propulsion rockets, when we move left, right? And when we stand, the propulsion rockets will animate to reflect that motion. I want the shooting animation to react when we press a hot button. And I want the jets to react completely independently of that. When we press the movement keys, how do we make the player animation react to two different independent sets of inputs? Let me show you, you can download all art assets in the resources section. Below we will bring player PNG and player underscore jets, PN G to the project and give them IDs of player and player jets. Like this, I hide them with CSS using their ID's. I save changes I just made in all my files. Here we will bring in the main player sprite sheet as this image property. And we point Java script towards that image element using its ID. Inside our custom draw method, I can use built in draw image method. Again, to draw the spaceship on canvas. We already know that we need to pass it at least three arguments. The image we want to draw and x and y coordinates. Where to draw it? This will draw the entire sprite sheet, all four frames. I adjust player width 240 pixels and height 220 to match the frame size. I adjust player speed to five pixels per animation frame. We will need frame X property to navigate around the sprite sheet horizontally. We don't need frame Y for vertical navigation this time because this sprite sheet has only one row. We also already learned that we can pass draw image method, optional width and height. And it will squeeze the entire sprite sheet, in this case all four frames to the area of one frame. We want to crop out just that one frame at the time. So we will need to use the longest version of draw image method. I add source x, source Y, source width, and source height, and the values we pass to draw image method as these arguments will determine which area we want to crop out from the source image. This frame would be from coordinate 00 on the image to width and height of the player, which corresponds to the width and height of a single frame in my sprite sheet. I like to create my art assets at the same size at which they will be displayed in game. Doing this, make sure your images are sharp and detailed enough, but they are not larger than they need to be. I want to navigate around the spread sheet. I will again use source x argument to define the horizontal crop in coordinate zero times the width of a single frame. Is this frame one times width is this area, two is this, and three is this. We will use some of these later, probably for super weapons I want to implement. I will comment out the white rectangle. We don't need it anymore unless we want to display the exact boundaries of player collision, hit box. I replace this with frame X property. And now I can change which frame in players sprite sheet gets displayed here. In this area, I will handle sprite frames logic inside. I check if attack button was pressed. In our case, we check if this dot game dot keys array, which we are accessing through didot game reference here. And it sits on the main game object here. When a key is pressed, we add it to the array. When it's released, we remove it from the array. If keys array contains number one, which means we are holding down number one key on the keyboard, frame X will be one. Frame X is zero, we are jumping between these two frames as we press the basic attack button. Let's test it. Actually, I will draw the projectiles behind the player by swapping these lines of code here. Now if I shoot, we get a subtle movement and animation of the laser cannon on top of our intergalactic spaceship. I will use frame two for another special attack a bit later, but we can test the animation here. I made the last frame for super laser attack. It doesn't really work well with the basic projectile. We will probably make use of all of these frames in a bonus section of the class if you want me to do it. For now, we have just a simple basic laser projectile. And player spreadsheet reacts and animates. When we as a user press the attack button, I will animate player jets, the propulsion rockets. I want them to react to a different set of inputs. Will animate depending on the direction of movement, depending on which movement key is pressed. The easiest way to do it is to draw those jets as a separate image and we can layer it together with the player. Let me show you what I mean. We already included player jets image in index HTML and we hit it with CSS. I'll reference it here with Javascript. As this jets underscore image, I copy this draw image code and I'll also draw jets image like this. It looks like Javascript can't find the image. Let's check in index HTML. Oh yes, I gave it an idea of player underscore jets. Now I'm drawing this frame. I will create a property. I will call for example, Jets frame. It will serve the same purpose as frame X does for the players spread sheet. We will use Jets frame for horizontal navigation around the spread sheet. I will use it here inside source x argument. Now jets frame is zero and we see this frame. When jets frame is one, we see this frame. And when it's two, we see this frame. We will start from jets frame one because that's the middle basic state inside the update method. We are already keeping track of arrow left and arrow right key presses. We expand this code block here. When we move left, jets frame will be zero. I test it. Yes, L. If we move right, jets frame will be two left, right, left, right. Yes, I will also add L statement if arrow left or arrow right are not pressed. We set jets frame to one. Nice, this is one way how you can animate a character to react to multiple independent sets of inputs. Just split it into multiple layers that react separately. What we did here is also great for performance. We only have a few animation frames, but it feels very reactive and animated because it responds instantly. If you are coding along, you can test the gameplay yourself and see how it feels. Do you prefer when I do complex animation sequences like I usually do for my other games with 30 animation frames per loop? Or did I convince you to sometimes try this more performance friendly animation technique that uses only a minimal number of frames? I will create a larger wave two times eight enemies. And I will let it trigger a game over by depleting player lives. Notice that when enemies hit the player and they are destroyed. They don't play the explosion animation as they should. We handle collisions between enemies and the player here, I don't want to immediately mark that colliding enemy for deletion. I delete that line of code and I will also scrap this. I don't want to reduce score when player collides with an enemy. I will instead just set enemy lives to zero when they hit the player. This will trigger the code block in the following loop. Now I have another problem. Because hitting one enemy takes all three player lives, because we are colliding with that enemy that already has zero. And it reduces one player life per animation frame. That enemy has zero lives, but it is still in there. It's animating the explosion sequence and we are colliding with that. I only want to check collision between player and enemies if that enemy object has more than zero lives. Now enemies are animated and each enemy collision just takes away one player life. I can press R to restart the game. I will increase the number of projectiles in the object pool to 15, so we don't run out So often I will slow down the sprite animation, maybe serve the next animation frame. Once every 150 milliseconds here where we handle loose condition I use or operator and I say if this game dot player dot lives is less than one trigger game over from here. And in that case we don't need this code. I also don't want the enemies to be deleted when they touch the bottom edge of the game area. I also delete this. I said the initial enemy wave to one times one. Up here on the player class, I will create max lives property. It will be, for example, ten. Inside the draw status text method. I copy this for loop that draws lives and I will draw max lives first. Maximum potential lives will be only empty stroke rectangles like this. I make them larger, maybe ten times 15 pixels here as well. 20 pixels spacing here. And here. I want the line width to be only one pixel, which is also the default value on canvas. I don't need to declare it at all, and this is the visual I wanted. When we defeat a wave, we get a bonus life and stroke rectangle turns into a field rectangle. We can easily see we currently have five out of potential maximum ten lives. I also need to go here to line 247. When a new wave is triggered, we will only give the player one more life if players current lives are less than players max lives. We implemented many features and learned a lot of new techniques. We have a fully playable game with increasing difficulty as large and large waves come. As we progress through the game, what should I implement next? Boss battles, super weapons, enemy types. How about enemies that have multiple lives and multiple damaged states? Let me know in the comments if you code it all the way here, and what bonus features you would like me to implement next from the ones I suggested, or you can give me your original ideas. Are there any features in the original Space Invaders game that I forgot about and you would like to see in our version? Click you like if you found some value. And check out the video description if you want to make more games with me. A. 15. Extra features: Armored enemies: What makes enemies interesting in a two day game like this, It can be things like their behavior properties and also their visuals. Different combinations of enemy types in our games should create different situations and chal***ges for the player to deal with. Today, we will design and implement a unique enemy type and we will make it a part of our game. Okay, it looks like we are somewhere deep in space, exploring the interstellar void similar to the Kiper Belt in our solar system. This Unknown part of space has a massive asteroid belt. These asteroids are mostly just solid chunks of ice and dust. It seems these alien life forms are well equipped to survive in the vacuum space and they have a thick excess skeleton to protect them in case of collision with an asteroid. Interesting, how are we going to get past them? I will calibrate our lasers to a higher frequency. It should be able to crack their shells, but it might need multiple well aimed hits. Perfect. Let's do it. 16. Rhinomorph enemy class: I created four visual variations for the new rhinomorph enemy class. If you take a close look at the sprite sheet, you notice they all get damaged in different ways. My goal is to basically connect their sprite frame to their health. Let's say this column in the sprite sheet is the enemy on full health. It will have four lives. When we hit it once, it will display this frame. This is the enemy on two lives, one life, and the final hit will play this animation. As usual, you can download all art assets in the description down below. If you are just joining me for this project right now, part one is linked in the description as well. I put rhinomorphPNG file into my project folder. I include it here in my index HTML file. And I give it an ID of rhinomorph. I use its ID to hide it with CSS because we only want to draw it with Javascript on canvas. Later we already learned about subclassing in Java Script. We know that enemy is the parent class, also called a super class. This class contains all properties and methods shared among all different enemy types. Then we use the special extense keyword create Beetle Morph child class, also called a sub class. This class contains only properties and methods specific only to a particular enemy type. For example, if we hit Beetle morph enemy with a projectile, we are triggering a hit method, but the Javascript will not find that method on this subclass. The extends keyword sets up the standard Javascript prototype chain behind the scenes. Javascript knows that if it can't find a method on the subclass, it will go automatically look for it on the superclass, on the parent class, it will follow the prototype chain until it finds the method. That particular hit method will be found here We have all the logic in place and we understand how parent and child classes in Java script work. Let's use that knowledge to implement another enemy type with unique properties and visuals. I copy this code block and I will rename it to Rhinomorph. We point it's this dot image property to that new rhinomorphspriadsheet we just included in index HTML file. This spreadsheet has 012345 horizontal frames, max frame will be five, frame Y will stay the same because this spreadsheet also has four rows, same as beetle morph. Rhino morph will have four lives. We will need to hit it multiple times to destroy it. Important thing here is this max lives property. It is created when we create this enemy object and it always holds. And it remembers the initial value of this dot lives even as the game is running and the enemy Rhinomorph has currently, for example, only two lives because we already hit it before. This dot max lives property will always hold. And remember that initial value of four, that maximum value, we will need all of this in a minute. So try to remember this please. Okay, so we have a new subclass. How do we add this new enemy type into the game? I go down here to our custom wave class. This class creates a group of enemies and it organizes them in a grid like formation down here inside create method on wave class. First I will just check if everything works by replacing beetle morph with rhinomorph. Nice, we can see Rhinomorphow what happens if I hit it? We gave it four lives, so I need to hit it multiple times. And when we deplete all its lives, its remaining animation frames will play. Currently, this enemy type is using the same logic as the first simple enemy. We hit it over and over until we deplete its lives. And then the rest of the spread sheet will play. I would like the spreadsheet to swap frames every time we hit it, to show the gradual damage we are doing to it by our high frequency lasers. To do that, we need to learn one more thing about extending Javascript classes. These are my subclasses and they both extend this enemy superclass when we hit an enemy, this method from line hundred and 27 runs. I want the things to stay the same as they are for the beetle morph class, but I want to add some more logic here for the rhinomorph class. One thing I can do is to copy this method and to add it here on rhinomorph. That way when it method is triggered on rhinomorph, Javascript will find it method directly on this class and it will not go looking for it up on the enemy class anymore. Basically, I'm overriding that method for beetle morph. It will still stay the same as it was before. There is no hit method on this subclass. Javascript will still be referring to that original hit method on the parent enemy class. For Rhinomorph, we are overriding. Original hit method here on line 154. Now I can just put any additional logic inside hit method on rhinomorph class. This logic will only apply to this particular enemy type. I want to somehow attach and connect the frame number on Rhinomorphspridesheet to the current value of enemy lives. When we hit Rhinomorph, we will set frame to max lives minus its current lives. Max lives is four. As we know, we hit it once. Four minus three is one. Frame X is one. We hit it again. Its current lives are 24, minus two is two. Frame X is two. We hit it again. Current lives are 14, minus one is three. Frame X is three. I hope it makes sense. I test it. I hit it once. We see this frame. I hit it again. We see this frame, I hit it again. We see this frame. I hit it one more time. And the rest of the spreadsheet will run perfect. I played the game for a while and you can see we get randomized four variations of rhino morph enemy class. And they all get damaged step by step. As we swap spread sheet frames by hitting them, I might implement other weapon types later. And this damage value might not always be an integer, it might not always be one damage per hit. This damage value has decimal points. It would actually break this logic that swaps sprite frames. To prevent that, I will wrap this dot lives in math dot floor to round it down to the nearest lower integer. And now we are safe even if we have some kind of a laser weapon that deals damage in smaller or larger values per one hit. Even in that case, the frame swapping logic here will still work. Now I had fun creating the sprite sheets, and I was trying to come up with four different ways enemy shells can crack as we damage them. Step by step, we implemented this new enemy type, and probably it was easier than you thought it would be. I would like to hear your design ideas now. Can you come up with another enemy type with a unique feature if you want? You can also give that enemy type a name. If you come up with something really good, I might actually design it, implement it, and I will release it as a bonus episode in this class. Now I want the waves of enemies to be made out of some beetle morphs and some rhino morphs. And I want to be able to control what percentage of the wave is made out of which enemy type. To do that, I go here inside our custom wave class. Here on line 193, we are pushing only rhino morphs. Right now I will do this method random trick again. We already used it to randomly decide if the wave will first start moving to the left or to the right when it's created. Again, method random called on its own, like this, will return a random value 0-1 The full definition is that method random returns a floating point pseudorandom number that is greater or equal to zero and less than one. If I create an expression that says method random is less than 0.5 it will be true in roughly 50% of the cases. 50% of the wave will be made out of rhino morphs, else meaning the other 50% it will create beetle morphs. Now if I play the game, we are getting both enemy types and they should be distributed somehow, equally 50, 50. Of course it's random, we'll always get more of one or the other, but overall it will average out to give us almost equal distribution. Let's say I want only a 20% of the enemies to be rhino morphs and the remaining 80% to be beetle morphs. I would use 0.2 here. This gives us a very simple way of controlling enemy type distribution in our game. Adding an enemy type that works slightly differently makes our game a little bit more interesting to explore for our players. What else should we do to improve this game even further? What other features should we implement? Give me your creative ideas down below and help me design it. See you in the next part. 17. Extra features: Boss battles: I have no data on this creature. Its shell is pure tellurium polymer, impossible to scan. There are no records on this species. No one who meets this creature survives to tell the tale. I'm trying to get more data. In the meantime, the only strategy we have is raw firepower. Hit it with everything we have before it hits us. And let's try to avoid these massive tellurium claws. Something tells me they would cut through our shields like butter. Yes, any close contact will result in immediate shields, failure, keeping our distances imperative. 18. Boss class: When writing custom code for a project like this, the most important thing is to always be aware which code runs just once. Which code block runs when a specific event happens. And which code runs over and over for every animation loop in our game, the enemies come in larger and larger waves. What if I want every third wave to be a randomized boss encounter? And as the game goes on, I want the bosses to have more and more health. Gradually increasing the chal***ge for the player. You are watching the full extended version. The full source code from each stage is included in the download section down below. If you are watching a free Youtube version, don't forget to click the like and let me know you want more projects like this. As usual, I start by importing the art assets. You can download boss PNG file in the resources section below. Place that image inside the project folder and link it in index HTML file like this. I give it an idea of boss, we hide it with CSS. If you inspect the spread sheet, I created four different boss creatures. The spread sheet is organized like this. The first two frames will play when we hit the boss with a projectile boss will move a little bit to react to being hit. When we deplete all its hit points, all its lives, the rest of the spreadsheet will play. I hope you like the pop animations I made. I was having a bit of fun with this. Down here on 960, I create a custom boss class. Constructor will run only once to create a boss object. Every time we call this class using the new keyword, we will be pointing to the main game object as we did before. To get access to all properties and methods that sit on there, I want the boss to be much larger than regular enemies. Width and height will be 200 times 200 pixels. I want the boss to start exactly in the middle of the screen horizontally. This game dot width times 0.5 minus half of the width of the boss. At first, it will be hidden behind the top edge of the visible game area. The vertical y coordinate will be minus dot height. Horizontal speed, speed x will be randomly minus one or plus one. To do that, we use ternary operator that evaluates mathrandom expression like we did before. If mathrandom is less than 0.5 in approximately 50% of the cases speed x is minus one, the boss will start moving to the left, else the boss will move to the right. Speed Y will be zero. Initially, boss will always have let's say ten lives at first. The next boss will have more health. We will increase lives each time we create a new boss wave. I will also give it max lives. That property will remember the initial dis dot lives value so that I can award the player the appropriate amount of score points when the boss is defeated. Marked for de lesion will be false. At first, this dot image will point to the sprite sheet I have that contains four different boss creatures. Frame X will handle horizontal sprite navigation. We will start at frame zero. So the left column frame Y will determine which one of these four bosses we will see it will handle vertical sprite navigation. Each time we create a new boss, I want to randomly pick one of these four. Frame Y will be a random value 0-4 We use Matt floor here to round it down to the nearest lower integer. We do that because there is no row 1.5 in the sprite sheet. For example, we want only integers. Now this expression gives us either zero or one, or two, or three. We need to know the maximum horizontal frame to check if the entire explosion animation finished playing, and we can remove the boss object from the game. I will set max frame to 11. This reminds me that I forgot to do one thing in the previous lesson. Down here in the new wave method on the main game class, we push new wave object into this dot waves array whenever the previous wave of enemies is defeated. If I consolo this waves and I play, I defeat wave one, wave two, wave three. We can see in the console that didot waves array is endlessly growing and the old waves just stay there even though they don't contain any active enemies anymore. To fix this, I go up here to our custom wave class. I give it a property called marked for deletion. Initially it will be set to falls inside render method on wave class. We know that this method runs for every animation frame. Moving the wave around the game area and filtering out destroyed enemies out of its distort enemies array. When the player destroyed all enemies and didot enemies, ***gth is zero. Are no enemies left in this wave. We will set marked for deletion on this wave object to true. When this wave object has enemies array that contains zero enemies, it means we defeated all of them and the new wave was created. We want to delete this old wave down here where we create a new wave. We will filter out old waves every time we add a new wave to the game, check this dot waves array and we filter it. Only those elements that have marked for deletion properties set to face are allowed to stay in this dot waves array. If they have marked for deletion set to true, they will be removed. Now I play the game and I only ever see two waves, the old one and the new one that was just created. Actually, if I move the consolo here and I play the game, we can see that this dot waves array only holds one currently active waves object. I hope this makes sense. Any questions about this, you can leave a comment. Let's go back to the boss class. It will need a custom draw method to draw the boss in game, and update method to move it around to define its behavior. We have a sprite sheet with multiple frames we want to swap between. Which means we will need the longest version of draw image method, a version that takes nine arguments. The image we want to draw source x, source y, source width, and source height of an area. We want to crop out from the source image as usual, destination X, destination Y, destination width, and destination height. To define where on destination canvas we want to place that crop out frame onto. I want to crop out top left frame from coordinate 002 with height. I want to place it on canvas at position x dot y dot dot height. Like this, the boss will start entirely hidden behind the top edge of canvas. I want it to flow into view until it's fully visible. If this y is less than zero, this dot Y plus equals ten pixels per animation frame. This is a good basic setup for the boss. Now let's actually draw it. So we know what we are working with down here on the main game class. We know that all the code we put inside a constructor is automatically executed at the point when we create an instance of that class using the new keyword, I am automatically pushing wave number one, the first group of enemies, into the game. As soon as we created the game, I delete this For now. I will create a boss array that will hold all currently active bosses. We will probably only have one active boss at the time, but we could easily have multiple ones if you want to make the game even more chal***ging for our players. Down here we have a custom restart method that runs when we get a game over. And when we press letter R here you can see I'm just setting everything back to the default values. The problem is that if I want to make any changes to any of this as I develop the game, I need to make the same changes up inside the game class constructor to those properties. And also down here in the restart method to make sure it's consistent with the time when the game first starts and when it restarts. I could avoid having to do that by actually calling restart method from the constructor, meaning that it will reset all the values as soon as the game starts. Maybe we could also call that method something like initialize. Either way, now that I've done this, these initial values of 11 here don't really matter. Because here, even before the game starts, restart method will set columns and rows two to two because those are the values we use the down here when we restart the game. We also need to set boss array to an empty array like this to clean up. Now because we know that the restart method runs immediately, we can put any code in there that we want to run when the game starts and when the game restarts. I'm already automatically pushing the first enemy wave here. Let's also use our new custom boss class to push one new boss object into the boss array. 19. Boss movement: I need to go up here inside the render method and we need to call its draw and update boss array. For each, for each boss object inside boss array call its draw method. We know it expects context and also call its update. Nice, we have both enemy wave at the same time. Now we know that we can go down here inside the restart method. And maybe we want to start the game with a wave of enemies. Or maybe we want to start with a boss wave. Which is what I will do now. Because we are building and testing our boss logic, I can change this value to make the boss float into view. Faster or slower. You can decide your own speed value. Here I will go with four pixels per animation frame. I want to give the boss the same left and right movement pattern we gave to the wave of enemies. If horizontal x coordinate of the boss is less than zero, meaning if the boss is touching the left edge of game area, or the horizontal position of the boss is more than game width minus the width of the boss. Meaning that the boss is touching the right edge of the game area. In both of these cases, we swap speed x value from line 167 to its opposite, which will make the boss bounce left and right. Now I just need to increase this dot x by speed x for every animation frame, I will also increase dot Y by speed Y. Nice. We have a boss that floats into the view and it bounces left and right. I also want to give it speed y of 200 when it touches either edge. But that means the boss will just rush forward like this. I want that speed y property to increase only for one animation frame for a quick jump. Then immediately we set it back to zero. All of this movement stuff is exactly the same logic we used for wave motion before. Now it works. I will make the vertical jump equal to half of the boss's height. Like this. We can always see only this frame because I'm dropping from 00 to width and height. If I want randomized row instead, I use source y argument for that. Zero times to height is this frame one times, height is this frame two times height will give us this version of mantis morph. Three times height will give us this deep space, lower crafty and monster. We already prepared frame Y property for this purpose, on line 174, let's use it here. Source will handle horizontal sprite navigation. It will be frame x from 973 times width from 963. For example, if frame x is five, it will give us this frame. If you got this far in this course, I think you understand this part already. So let's just move on whenever we reload the game or create a new boss using our custom boss class, we will randomly get one of these four boss creatures perfect. The first boss will be easy, it will only have ten lives. Let's actually draw boss lives. We can choose to do it as a health bar or as a number. I will wrap this code between safe and restore to make sure any changes to canvas state I make here are limited only to this area will call built in fill text method which takes at least three arguments. The text we want to draw this dot lives from line 169 and x and y of an anchor point in relation to which the text will be displayed. Let's start with x and y of the boss, which as we know is the top left corner of the boss. Hit box rectangle. I actually want to move the text a bit down, maybe plus 50 pixels vertically and horizontally. Let's try the width of the both times 0.5 Doing this put the text anchor point exactly in the middle, but by default the text is left aligned. From there, I will use Text Align property and I will set it to center because we wrapped this code block between safe and restore. That means it will only affect the boss lives and not any other text we are drawing on canvas to make the white text more visible against the background. I can also give it a shadow of set X three pixels, shadow of set Y three pixels as well. And shadow color can be black. Now that we see both lives, let's set up collision detection between both and projectiles inside update method. On both class, I will take projectiles pull array that sits on the main game class. I call for each method on it. For each projectile in projectiles pull array, I will check the following. If check collision method between this boss object and the projectile we are currently cycling over with for each method, if the collision check on the rectangular hit boxes returns true at the same time double percent operator. I only want to check if the projectile is active because projectiles come from a re, usable object pool only if free property on projectile is false, meaning the projectile is being used. It's active in the game. One more check if lives of the boss are more than zero. Because when we depleted both lives and the explosion animation frames are playing, I want the new projectiles to ignore that and fly through it, not collide with it. Only after all these three checks are true, both and projectile are colliding with an active projectile and Bos has more than zero lives. We reduce lives of the boss by one. We will also call reset method on the projectile, which means the projectile object will become inactive and it will be returned back to the object pool. I test it. Yes, when I hit the boss, we deplete its lives. This is going really well. Instead of reducing lives directly like this, I will create a hit method that will take damage value as an argument. And it will reduce lives by that damage. I want the boss to move and animate a bit and react to being hit. We will swap between frames 0.1 only if lives are more than one. When hit, we will set frame X to one displaying this frame. Now I use it method here and I pass it damage of one. Okay, that still works. We hit the boss and we swapped frame to frame one. This one now I want it to return back to the original frame zero, but we want to wait for sprite update flag to be true to slow the animation down. Same as we did with enemies. Also, we only return to that frame if boss lives are more than zero, because when they get to zero we want to play the entire animation role. Nice. Now if we hit the boss, as long as boss lives are more than one, we swap between frame 0.1 to make the boss wiggle and react to be in hit. If I reload and I get a different boss creature, we can see it moves in a different way. I gave each boss a saddle way to react to being hit like this. It helps to give the player more visual feedback to make the game feel more alive. I think we are using basic static images, but they react to inputs and actions. Sprite sheets have only a small number of frames, but everything is reactive. This is one of performance friendly ways to animate your games. I will say more than zero here. Actually, when both lives reach zero, we want to animate the rest of the sprite sheet where the boss is getting inflated and destroyed. If the lives of the boss are less than one. If sprite update flag is true, we will start slowly increasing frame eggs by one traveling through the sprite sheet horizontally. Let's test it. I hit the boss ten times. Nice. It plays the animation. You can see that the boss is still there. It's just showing a blank sprite frame. Actually, I don't need to draw zero lives. We will only draw lives if this lives is more than zero. Now we destroy boss. We are no longer drawing its lives, and projectiles no longer collide with it, but the invisible boss is still there. Moving around the screen, we need to remove it using Marked for deletion property we defined here on line 171. As we update horizontal frames, frame X is more than max frame. We set max frame to 11 here on 975. At this point, we know that the boss was destroyed and that all animation frames of explosion were displayed. We know at this point it's safe to remove the boss object from the game entirely. I will set it's marked for deletion property to true. I will also increase game score by this max lives which holds the initial number of lives, the boss head in this case ten boss with ten lives will award ten score points. When defeated, we set marked for deletion to true here. And I go down to the main render method and I will filter out boss array. This line of code runs for every animation frame, which is a bit of a waste. To be honest, we could easily just put it somewhere else, for example, into new wave method and only clean all the boss objects periodically, we don't have to check it for every animation frame. We already covered how filter method works and how it filters out all the objects from the array that have marked for deletion property set to true. Let's see if it works by consolo. In this boss array, we have one boss. Inside the array, we deplete all its lives. Explosion animation plays. Now I can see in console that boss array is empty. Great, I delete the consolo. 20. Boss vs player collision: Now we need to decide what happens if boss gets all the way down and collides with the player. I check if custom check collision method between this boss object and player object returns true at the same time. Only run this code when boss has more than zero lives. Because there could be a scenario where player collides with explosion animation frames. Which would be fine because the boss was destroyed already. We don't want to register collision in that case. Inside I set game over to true. We need to destroy the boss before it touches the player. Otherwise, its claws goes straight through our shields. The boss is very dangerous. At the same time, I can set lives of the boss to zero to trigger the explosion animation sequence if I want to. Let's say our shields will also destroy the boss. I don't know. Come up with your own story. Let's test it. I will speed this up. When the boss touches the player, we get game over and the boss explodes. That worked perfect. Another loose condition would be if boss gets all the way down here and touches the bottom of the screen. If vertical position of the boss plus its height is more than the height of the game. Meaning that the bottom edge of the boss touches the bottom of the visible game area. We set game over to true. When I destroy the boss like this, I want the game to continue and I want regular waves of enemies to keep coming. Boss was destroyed here. If game over is false, we call our custom new wave method. Let's test it. I destroy the boss, we get a wave of enemies. I destroy all enemies in the wave, I get another larger wave. This is a pretty good game loop already. Isn't it done if you follow it all the way here? Every time a new wave comes, we are increasing wave count value and we are displaying it. Here we are calling a new wave method we defined on line 393 here. Every time wave count is divisible by two without any remainder, for example, four waves, 02468, so on. We will push a new boss, else we will create a regular, increasingly large wave of enemies. I have to be careful about the brackets here. I say this boss array, push new boss. I passed this to point to the main game object we are inside of right now. I don't want to increase wave count here, I deleted. Instead we increase wave count here inside new wave method. That way both boss and enemy waves will increase wave count value. Now let's test it. We start the first wave with a boss as we defined inside restart method. On the first load we defeat the boss. Wave counter increases to two, which is divisible by two with a remainder of zero. This block runs and we get a boss again. We defeated wave is three. This is false else statement on line 396 runs and we get a wave of enemies. Four is divisible by two with a remainder of zero. Now we get a boss. You can change how often you want to get a boss by adjusting this value here. If you want the first wave wave zero to be boss or enemies, we define that inside restart method here. When the explosion animation starts playing, I don't want it to bounce from the edges anymore because that looks strange. If explosion starts playing, just let it flow off screen if it's close to the edges. One more condition here that says if this dot lives is more than zero, only do the regular left and right bounce in motion if the boss is not animating the final explosion. Now we are getting closer to the edge and when I shoot the boss, the explosion doesn't bounce anymore. It just flows and continues in the direction the boss was already moving. I think this looks better. I notice that when we defeat a boss wave, we don't get a bonus player alive to fix it. I cut this line of code, I paste it down here. Inside a new wave method, I defeat a boss. Yes, I get a bonus life Good. Every time we create a new boss, I want it to have, let's say five more lives. To make the game gradually more and more chal***ging. I will store boss lives value here on the main game object. We will start with ten lives. When we restart, we also need to go back to ten. I will pass boss lives as the second argument to boss class constructor for the boss in the initial first wave and then for every other consecutive boss we create, I will make sure that value is expected here on line 161. And we use it as the value for this lives property when we defeat a boss and it was destroyed before we call the next wave, we increase boss lives property on the main game object by let's say five, making the next boss a little bit more chal***ging. This boss has ten lives, I destroy it. The next boss has 15 lives that worked. We have waves of enemies that get larger and larger as the game goes on. And we have bosses with more and more health. Thank you everyone who commented on the videos and helped me design this game. If you have any more ideas and you want me to add more features, let me know in the comments, If you come up with something really good, I will do it and I will release it as a bonus lesson. More enemy types, super weapons, larger super bosses that actually shoot projectiles back at us. What do you want me to do next? Let me know. It's more fun for me if we design it together. As I play, I notice that the boss already loses some lives before it's even fully visible on the screen from the projectiles that are flying close to the top edge. Let's say I only want collision between boss and projectiles to happen after the boss floated all the way to its starting position. And it's fully visible on screen when the vertical position of the boss is more or equal to zero. Okay, I'm happy with this. What do you think? See you in the next part. 21. Extra features: Super weapons: As we filled our game with swarms of dangerous enemies, we need a better way to deal with them. Time for super weapons. Let me show you something. I collected enough plutonium to upgrade our reactor. I can focus its energy into a powerful column of light and use it as a weapon. Sounds like things can get very hot. Very fast. Yes, our solar shields will give us a source of renewable energy, but be careful not to overheat the cannon. The security lock will disable the valve. If we surpass the maximum safe temperature noted, we will manage our energy and avoid overheating. Sounds easy enough. The laser can burn through multiple enemies at the same time. It can destroy the entire enemy wave in seconds if timed correctly. Happy hunting. 22. 2 laser classes: In this Java script game development class, we add resource management with a rechargeable energy bar. And we will implement two more weapons, a long range laser and a super laser. These new weapons will be fundamentally different from our basic attack, because they will hit all enemies in a column in front of them, even the ones all the way in the back. It can be very effective, especially later in the game, when we face larger and larger enemy waves. We will have the parent laser class that will define the main properties and methods of both laser weapons. I will extend it into two subclasses, small laser and big laser. I do it because each laser will have different size and it will deal different damage. Those specific things will be defined separate on each subclass. Constructor will need access to the main game object to give us access to all important methods and properties we previously put on the game class. From inside laser class render method will draw and updated the laser weapon. It will need context as an argument. We will extend the constructor on both subclasses. Let's just first do everything on a small laser subclass to keep it simple. When we create an instance of small laser, we want to run all the code inside its parent class constructor. We know that the parent class can be also called a superclass. We call superclass constructor like this. And we know it expects a reference to the game object. I pass it here like this. It is expected here. And it gets converted into this dot game property. Only after we run the code inside Superclass constructor, we can use this dot here and define properties specific only to small laser subclass. We will do that in a minute. I also want to extend, I don't want to override it this time. I want the code from inside render from line five to actually run. This code block contains logic shared for both Small Laser and Big Laser subclasses. After that, I will add a little bit of code that is specific only to Small Laser subclass. Here. The syntax is a bit different. It's like this. Here, I'm calling superclass constructor. Here, I'm calling a method that sits on the super class, on the parent class. I hope it makes sense. Constructor is a special type of method. That's why the syntax is different here. In these two cases, even though both are just calling a method on the parent class, there is a reason why I'm putting render method on the subclass, but we will get to that later. Laser will need x and y width and height properties so that Javascript knows exactly where to draw it. Also, we will be checking collision detection between the laser beam and the enemies and bosses. We know that all objects involved in collision detection need x y with and height properties. X, y and height can stay on the parent class, but each laser type will have a different width. I have to put it on the subclass here. We want the big super laser to be much wider than the small laser, the small one. Let's try five pixels. The players sprite sheet will animate. With these weapons, we will get width to match the spaceship sprite in a minute. This, the horizontal coordinate of the laser will be moving with the player. As the player moves left and right. Initially I set it to zero. Vertical y coordinate on both lasers will always be zero because I want the laser beam rectangle to start from the top of the screen. The height of the laser will always be the same as well. I want the laser beam to come from here to somewhere around here. I guess from coordinate zero height of the laser beam will be this dot dot height minus let's say 50 pixels to cover this area. We know that all the code inside constructor is executed only once. At the point when we create an instance of the class, using the new keyword render method will be very different. The code inside render method will run over and over for every animation frame. We have to keep that in mind when we decide where to put the logic. When the laser is active, I want its horizontal coordinate to keep updating to match the position of the player. Let's just start with this and see what we get. Now I will draw the laser beam as a simple rectangle. I will give it two colors. I will wrap this Cod block in safe and restore built in canvas methods to make sure that these fill style colors affect only the laser beam and not the other shapes drawn on canvas. I said it's fill style to gold built in fill rectangle method. We'll draw the laser. I just pass it x, y, w from here and height. If any of this doesn't make sense, leave a comment and we can talk about it. I hope it's all clear. We have the basic version of small laser. Let's draw it so we can see it in game and we can tweak it and adjust it. I will create an instance of small laser class here. It will be created at the point when we create an instance of the player class using the new keyword. I could have also put small laser on the main game class, but I think it makes more sense here since it will be so closely tied with multiple properties on the player. Here we are checking if key is pressed and we are swapping player frames. I'm going to create an LF block. I have to be very careful about brackets when doing this. Single wrong bracket can break the entire game code. If one is pressed, we do the basic attack. When two is pressed we will trigger small laser player spreadsheet is already prepared for this from before. I just need to set frame X to two like this. We are inside a draw method which runs over and over for each animation frame. As long as key two is pressed, we will be displaying frame X two and we will be calling render on small laser drawing it and updating it. As soon as we release the key frame x will be set to zero and we stop rendering small laser. If we press number one, we do the basic attack. When we press number two, we draw small laser. It moves around with the player. I want to move it to the middle of the player. I adjust the code on line nine. Position of the laser is position of the player plus half of the player's width. Now it's almost centered. To center it completely, I have to offset it by a half of the width of the laser. Now it's exactly in the middle. As you can see, when we shoot the small laser, the arms of the space ship move inwards to help focus the thin laser beam in a small area. And the small muzzle jumps a bit backwards. I will set laser width to 50 pixels, just so we can better see it. And I will give it additional color because the middle of the laser is so hot, I want it to appear pure white. I copy this code block, I set it to white. It will be let's say 60% of the width of the laser beam, which leaves us with 40% to center the white beam in the middle of the gold beam. We need to push it by 20% of the width, the left edge, pushing it exactly in the middle. Now the middle of the laser beam is white, hot. I think giving it two colors makes it look much better. Since we used relative values, the white beam will be centered over the gold beam. Regardless of laser width, ten pixels is still too wide. I want the width of the beam to match the muzzle of our laser gun. Five pixels seems good. 23. Laser damage: Each laser subclass will also have a damage value. This will define how much damage to the enemies it will do per tick. Let's actually implement that damage and hit enemies with laser. Right now, it still doesn't interact with them at all. I can put the following logic in multiple different places in my code base. I decided to put it inside the render method on laser class because I like to keep the code organized and easy to navigate in. It makes sense because I only want to check collision between laser and enemies when we are actually drawing the laser. If you remember, we have an array that holds all currently active enemy waves in our game. There's always only one active wave in that array. But you can make the game more difficult and release the new wave before the previous one is fully defeated. For example, each wave object inside waves array has enemies array inside of it. As we defined here on line 280, that array holds all currently active enemies in that wave. To cycle through all active enemies, I will cycle through waves array. For every object in waves array, there will be only one. In our case, we access its enemies array, also call for each on that, for each enemy object in that array, we call our re, usable check collision method we wrote before we pass it enemy and this laser object. If enemy and laser collide, I'll call hit method on enemy And I pass it this damage of the laser. We defined it here on line 32. Before I test it, I will also cycle over all bosses inside boss array. Again, there is usually only one active boss, but if you want, you can push multiple bosses at the same time. Or you can push the next boss when the previous one has only a few hit points left. Leave the game design details on you. I'm giving you all the tools, Design your own game for each boss in boss array. We also call check collision method between that boss and this laser object. If they collide, we call hit method on the boss and we pass it damage of the laser as an argument. We have our render method which will run over and over as long as we are pressing number two key on our keyboard. When I test it, you will notice the laser is very powerful. It's fun to be able to destroy all enemies easily, but it takes all the chal***ge away from the game. We want to give the player fun, powerful weapons. But we don't want to make them overpowered like this. The reason it's so strong is that it hits enemies for 0.3 lives per animation frame. And we are running this at 60 frames per second or even faster. I want the laser damage to tick slower and I want to make sure the damage is same or similar for people on old computers and people on new gaming computers with high refresh rate screens. We already have a variable called sprite update that we set to true only for one animation frame every 150 milliseconds. We are using it to slow down how fast we cycle through animation frames in the sprite sheets. Here we can use the same variable to slow down how fast the laser ticks when it burns through enemies. Only when this dot game sprite update is true, only once every 150 milliseconds or so. We want to check collision and actually hit enemies and the boss with our long range lasers. Now we can see that the laser has a bit less power. I think this is so much better. We can always tweak this by adjusting this dot damage value on small laser subclass. Until now our basic attack was hitting for one life per hit. But now we have lasers that can deal damage is not exactly one. We can end up in a scenario like this, when the boss has less than one life, it should already having 0.8 lives. Doesn't count. In this game, I want the boss to explode as soon as its lives get below one. I go down to the boss class and I need to look at this code block. It says if lives are more than zero, which means that has 0.1 health is still considered a live. I will change it here, here, here, here, and here in all these places. I replace that check everywhere with this dot, lives are more or equal to one. Make sure you change it in all these places. Here. Also here. Sorry about this. Now let's try to use small laser on the boss. I will slowly burn through its tellurium shell. And notice that as soon as we get below one life, the boss explodes. Perfect. We can adjust the damage of the laser here. Good, It still works well. I put it back to 0.3 I think that's the right value for the small laser. The big laser will be much more powerful. Of course, we don't want the boss lives to display so many decimal points. I go down here to draw method on both class. Here we draw both lives. I wrap it in Matt floor to round it down and remove the small numbers that come after the decimal point. Let's test it again. The boss should start exploding immediately. As soon as it's health drops below one and we should never see zero lives. Yes, we are making a lot of progress. Okay, super laser. I come here and I copy all the code inside. I paste it inside. Big laser, subclass width will be 15 pixels. Damage will be 0.7 per tick. More than twice the damage of the small laser on the player class. We create an instance of big laser like this. Then we can add one more Lf block here. If key that was pressed is three, player frame is three. Which will give us the final frame where the arms open and make the room for the massive laser beam. And also to make sure that the tips don't melt from the heat. Big muzzle with laser lines inside pops out to fire our ultimate weapon, a super laser. We draw and update the laser by calling its render method small laser and big laser. You can see it deals more than double damage. It's actually too small. I want the laser beam to fully fill the cannon, maybe 25. Watch how the player animates to match the weapons. Basic attack, small laser and big laser. What do you think we can destroy enemies easily? Now the new laser weapons are especially effective against groups of enemies, since they damage the entire column of enemies all at once. I want to put the player and the laser beam behind enemies. But in front of game text, I cut it and I paste it here after we draw projectiles, but before we draw the boss, what gets drawn first is behind. In cases like this, when we draw everything on a single canvas element, try to play the game for a bit, and let me know what you think. Do you have any other weapon ideas, something completely different than this? Like what if we send out a swarm of small robots? Or how about electricity weapon? 24. Resource management: The game has become trivial and easy. Now that we use lasers without limits and actually there is no reason to use the small laser if we can use super laser nonstop. It would be much better if the player had a pool of energy they need to manage. Before we do that, I want to make sure the boss is only hit when it's fully visible. I don't want it to have reduced lives already by the point it floats on screen, we will check collision between the boss and lasers only when the vertical position of the boss is more or equal to zero. Once the boss has fully entered the game area, I test it. Yes, that works. Let's add resource management mechanic. The player will have an energy bar. Starting energy will be, for example, 50 max energy will be 100. If we don't pay attention to our energy levels, we can also overheat our laser which disables it for a short while. I will call this property, for example, cool down. We will display the energy bar down here inside Draw Status Text method. Again, we will use a four loop that will run once for each point in energy. For each energy point, we will draw a rectangle. We will space them out two pixels apart, vertically, I guess 50 pixels from the top. Each energy rectangle will be only two pixels wide and 15 pixels tall. Since we are drawing them one next to another, they create a bar. This value is the spacing between the bars, and this is the width of each bar. If they are the same value, we see one continuous shape. If the width is less than spacing, we see individual rectangles. You can play with these values and it will make sense when you see how it reacts to different values you give it. If I do 15 plus here, that will be margin from the left edge vertically. I want it probably 130 pixels from the top left margin. 20 spacing is two pixels, and the width of each energy rectangle is also two pixels. We are getting one continuous bar. Now when we shoot the lasers, it will be costing us energy. Up here I say this game player do energy minus equals this damage. Which means that now small laser is cheaper than big laser, Sometimes small laser is the better option. Now when I use lasers, you can see it actually depletes energy. The rate at which it depletes the energy is equal to laser damage. Small laser costs 0.3 energy per thick, Big laser costs 0.7 energy. I want the energy to slowly recharge. If the current energy is less than max energy, increase energy by 0.05 per animation frame, I test it, energy is recharging. If I deplete it, it will start recharging automatically. Again, good, we need to prevent the energy to go into minus values. Player has to manage energy and watch the energy bar. If they leave it for so long that the energy gets below on E, it will trigger the cool down. We overheated the cannon and now we have to wait. It's a small punishment for not paying attention. If we want to play optimally, we never deplete the energy below one. We never trigger the cool down I can do else here, because energy can never be below one and more than max energy time 0.2 in the same animation frame. This will save us a little bit of performance. If energy drops below one, cool down is triggered, the energy refills back to 20% of maximum energy cooldown is set to fall. Laser cannon had enough time to cool off and we can use our lasers. Again, I want to make it visually clear to the player when we entered a cool down, when we overheated our cannons down here where we draw that energy bar, we will change its color. I will wrap this in safe and restore to make sure these fill colors don't affect any other shapes we draw on canvas. We are quite far into this class. Instead of a standard F L statement, I will use ternary operator syntax here as a simple single line. If L, if player cool down is true. Question mark, set fill style to red L. Colon set fill style to gold, easy. Let's test it. Energy bar is gold. By default that means everything is all right and we can use our lasers when I use my lasers without paying attention to the energy bar and I let it slip below one, we trigger the cool down energy bar turns red, which means our lasers are overheated and we can only use the basic attack for a while. When we reach more than 20% of max energy. Now the bar changes back to gold color and we know we can use the lasers again, I have a feeling we are still dropping below zero energy. I can make this really clean by doing this. Here is the parent laser class and it's render method. We never call this render method directly. We are always calling it from one of the subclasses here. Let's make sure we only render the lasers when player energy is more than one. At the same time, if cool down is false only then we draw and update small laser. I copy this and I do the same thing for the big laser. Now for the reason why I'm putting render on subclasses. So far these methods are identical and we know when things are shared, they can sit on the parent class. Subclasses contain only properties and methods specific to that subclass. If I deplete my energy and I try to shoot the lasers, the player ship is still animating as if we are shooting the laser. But since we are on low energy and in cool down, the laser beam is not coming out. It might be fine for your game. I'm not sure what you prefer, but in my game I only want the players sprite sheet to animate like this when we are actually shooting the lasers instead of swapping player frame here. Here I delete these lines. We will actually swap players sprite sheet from here. Which means that the player will only animate these weapon attacks when we are actually rendering those weapons. Those laser beams. Small laser is frame x two, big laser is frame x three. Same as it was before. Now when I'm in cool down, no laser comes out and players sprite sheet doesn't animate that weapon attack. 25. Eaglemorph enemy class: We start by importing spread sheets into the project. Place both images into your project folder, and we reference them here image with a source. Eaglemorphngid will be Eaglemorph. We will also need their spiky, slimy, mutated projectiles, which will come as a spreadsheet of eight images. I call them Enemy Projectile. As usual, I will hide them with CSS on the first game load. Instead of pushing the first boss. We will start with enemy wave. Because today we will be adding a new enemy type to that wave. I copy this code block we used to create Rhino Morph enemy class. I rename it to Eagle Morph and I point its image property towards that new spreadsheet we just included in the project. I gave this enemy more detailed explosion animation with some extra frames. Max Frame will be eight. We count from the frame zero on the left on the wave class where we create each enemy wave by organizing enemies in a grid. I add one more L if statement block. I have to be very careful about the brackets here. When I'm doing this, I want the most of the wave to be made out of eagle morphs because we will be implementing and testing them. Let's say 80% will be eagle morphs, 10% will be rhino morphs, the remaining 10% will be beetle morphs. We are already getting eagle morphs, and because we copied and re used the entire code block we used for rhino morphs before already work quite well. You can see that every time I hit it, it loses one body segment. When the last segment is gone, explosion animation plays. So far it works the same as rhino morph. It's an enemy with multiple lives. And the spreadsheet reflects its current damage state. We want to make it spit those missing mutated body segments back at us as projectiles that the player needs to destroy or avoid. I'll start by making the eagle morph twitch a little bit. Every time it's hit, it will look good and it will make sense in a minute. When we give it projectiles, it looks like it's pushing forward and spitting the projectile towards the player. It's just a little twitch. I like it this way. All good. I will give it a shot method. We can either run that method randomly, making the enemies shoot, and spit the projectiles at us at random intervals. But what I will do today, because I like the game to react to player actions and be interactive. The shoot method will run when this enemy type gets hit by a player weapon. When we hit it, it tries to hit us back, it will react to being hit. Enemy projectiles will be an object pool. Since we already know how to manage that simple code structure from earlier in this class, I will actually copy this entire projectile class. We are using it to create a pool of player projectiles, the basic attacks of our spaceship. I copied the entire code block, I pasted it down here between my Eagle Morph and boss glasses. I will rename it to enemy Projectile with 50 pixels height 35 pixels. Enemy projectiles will travel down from enemies towards the player. The positive direction on the vertical Y axis speed will be a random value, 2-5 pixels per animation frame. This is an object pool member. We will create a re, usable object pool of let's say 15 enemy projectiles. Because it's more efficient to reuse objects rather than to constantly create new ones and discard the old ones. Each object pool member needs to have a property that indicates if it's free and available to be pulled from the object pool or if the object is currently busy. Active in the game. We only draw and update enemy Projectile if it's being used. If it's free property is set to falls. Every object pool member also needs a method to run when we take it from the pool and make it active in the game. In this case we call that method start and we pass it x and y coordinates of the enemy that will shoot this projectile. And we set its free property to falls. Because it becomes active, it's no longer free and available to be used. It also needs a restart method which will deactivate it. It will return it back to the object pool by setting its free property to true, which means it will no longer be drawn and updated. This is our enemy projectile class, An object pool member. We will manage this object pool from the main game class. It will work the same as player projectile pool we created in the beginning of this project. I copied these three lines of code. I have to be careful about camel casing. Here we will have an array that will hold all objects. I will call it enemy projectiles pool. The number of enemy projectiles will also be 15. We will create and re, use the same 15 objects over and over to improve performance and improve memory management of our Java Script project. As the game object is created, we will automatically trigger, create enemy projectiles method. Let's write that method. Now here we have two methods that handle player projectiles. Copy both of them and I paste them here. As we said, we will have a method that will create enemy projectiles object pool, create enemy projectiles method. We set the number of enemy projectiles, 215, so the loop will run 15 times. Each time it runs, it takes enemy projectiles pool array and it will push one new enemy projectile object into the array using the class we just created. Also need a method that whenever we call it, it will get one free enemy projectile object from the pool so that the enemy can shoot it. Get enemy projectile method will cycle over enemy projectiles pool array which we just filled with 15 objects. As soon as it finds the first one that has three property set to true, as soon as it finds the first inactive available enemy projectile object, it will stop searching and it will just return that object to us. All right, we have all the logic in place now we can use enemy projectiles object pool to shoot back at the player. Let's try it. 26. Enemy projectiles: I go up to my Eagle Morph enemy class. Here we created a custom shoot method. If you remember inside, we will pull one new enemy projectile object from enemy projectiles pool array. Using our custom get enemy projectile method, we check if we actually managed to get a free projectile because it might be that all 15 are used and not available. But if we did manage to get one from the pool, we will call its start method. We know that start method needs X and Y coordinates to tell the projectile where on canvas it should start animating from. We pass it X and Y coordinates of the Eagle Morph enemy that just shot this projectile. Now I have to go down here to the main render method. Same as we draw and update all player projectiles. I copy the score block and I run for each method, for every object inside enemy projectiles. Pull array, Careful about capital P here. For every enemy projectile in the array, I call its update and draw methods and we pass it context. Let's try. I shoot and hit the enemy. It's not shooting back at us yet. Okay, I go up here to enemy projectile class. Here we want the projectiles to animate downward in the positive direction. On the vertical y axis. This y plus equals this speed. Still they don't shoot. I change fill style to red. Projectiles travel down. This check needs to be more than, let's say 200 pixels. Okay, actually let's comment this line out for now. Consolo always helps us. Our consolo projectile, we pulled from enemy projectiles pull here. When I shoot and hit the enemy, I can see that this code block is not running at all. There's no consolo. Okay, I see it now. When we hit the enemy with player projectile, we want to call its shoot method like this. Now it will react. That's it. When I hit the enemy, it will shoot back at us. Now it works perfect. We want the projectile to start from the middle of the enemy, not from its top left corner. I pass it X of the enemy plus half of enemy with enemy, plus a half of enemy height. Now they come from the middle. That's better. We don't want to draw red rectangles. We want to draw mutated enemy projectiles from our custom spread sheet draw image. We pass it image we want to draw and x and y coordinates where to draw it, which will draw the entire image at its original size. We need to create this dot image property and we pointed towards the image we referenced in index HTML. Earlier, I gave it an idea of enemy projectile. We are drawing the entire sprite sheet. Now if I pass it width and height like this, it will squeeze the entire sprite sheet into an area of one frame. As always, we need to also pass it source X, source Y, source width, and source height to define a crop in area. Frame X will define horizontal crop in position, It will be zero, or one, or two, or three. Frame Y will handle the vertical crop in area and it will be zero or one. Source X argument passed to draw image method will be frame X multiply by frame width of 50 pixels. Source Y will be frame Y times frame height of 35 pixels. We pass it with height as source width and source height. Now each projectile is one of the random mutated baby aliens. I guess each ego morph has four body segments in total. Every time we hit it with the basic attack, it loses one segment and it shoots one projectile back at us. If we hit it with the laser, it releases more than four because the laser ticks faster and triggers this shoot method more often, we want to limit it to maximum of four projectiles per enemy. I call it for example, this shots. It will simply count how many shots have been fired by this eagle morph every time we shoot. We increase this do shots by one when the enemy takes damage from player attacks. If this do shots is less than four, it will shoot, it will shoot four times when this dot shot is 012.3 Now lasers release all four projectiles very fast, but the enemy will not be able to shoot any more projectiles back at us After that, with the basic attack, it will be one hit, one enemy projectile. Are there any backs? With this implementation, I will test it thoroughly a bit later. Right now we have 15 enemy projectiles in the pool. At some point, I will run out of them. I need to make sure they get reset and returned back to the pool when they float off screen. If the vertical coordinate of the projectile is more than the height of the game area, reset it and return it back to the pool of available objects. To do this, we will need access to this game. We pass it as an argument and we convert it to a class property. This is just a reference pointing to the place in memory where the main game object sits. This is not making a copy of the game object. When we create enemy projectile, we need to pass game as an argument. We are inside the main game object. Here I pass it this keyword to test it. I will have only two enemy projectiles in the pool. I want to check if they are reset in I should I only get two released and enemy projectile pool is empty. As soon as they move off screen, they reset and they can be used again. This works. I set it back to 15. 27. Projectile interactions: Right now, enemy projectiles don't interact with the player. Let's check collision between enemy projectiles and the player. If our custom check collision method between this enemy projectile, the player is true. Keep in mind that this code block runs only for active enemy projectiles, which is ideal. If active enemy projectile collides with the player, we reset the projectile returning it back to the pool. We will also reduce player lives by one. We check if player lives are less than one. If they are, we set game over to true. I shoot the enemy shoots back. We get hit 123. Game over. This works nice. I want the player to be able to shoot the enemy projectiles, but only with the basic attack. Mutated enemy projectiles are small and they have big eyes. They can easily avoid massive laser beams. We can only hit them with the basic attack. This is just my choice. I'm just trying to give the game play some complexity and give the player more reasons to use the basic attack. We are insight update method on enemy projectile class. This code runs only when enemy projectile is active. For every object in player projectiles pull array check collision between this enemy projectile and player projectile. Also, we only run this code if player projectile is active, if it's free property is false. If active enemy projectile and active player projectile collide, we take player projectile and we call its reset method. Returning it back to the pool. We will call custom hit method on enemy projectile, passing it damage of one. If lives of enemy projectile are less than one, we call its reset method, returning it back to the pool as well. Each enemy projectile will actually have five lives in my game, They're quite tough when they get hit. We reduce the lives by damage. We will also reduce their speed to, let's say 60% of the current speed. We have an option to destroy them completely, or just to slow them down and avoid them in that way. Again, giving us more strategic options, more choice and more control. Player can decide to destroy these tough projectiles or just slow them down and let them flat by I'm playing the game and I can see that new projectiles are becoming very slow and they have only one life. I play a bit more trying to control the projectiles with my basic attack. Yes, it becomes more clear now since enemy projectiles are an object pool, when we return them back to the pool, we need to reset their lives back to five. I can also randomize their Frame X and Frame Y to give them a different frame from the spread sheet, a different mutation. Since we are modifying their speed by hitting them, we also need to reset that speed to the original range of values. Down here, we handle enemy type distribution. 30% of the enemies in my game will be eagle morphs, 30% will be rhino morphs, and the last 40% will be beetle morphs. I'm rolling to random twice here. That will not work. I need to refactor the code. I hope that by now you are comfortable enough with this code base. You can tweak it and adjust the rules yourself. In my game, every Eagle morph enemy type can shoot a maximum of four projectiles. These projectiles are tough and they have five lives, so we can avoid them or slow them down. But only with the basic attack, They will ignore laser beam advanced attacks. An eagle morph with the laser will release all four enemy projectiles quicker. Basic attack will release one enemy projectile per hit. It's really fun for me to design a draw and code different enemy types like this. I could make ten more episodes implementing different alien species. You are the expert. Now I will give you another spreadsheet with squid morph. Now if you want, you can implement it as your own unique enemy. How will your quid morph work? Let me know in the comments. 28. Squidmorph Enemy Class: Now that we have everything, let me show you how easy and quick it is to add more enemy types into our existing code base. The spread sheet I'm giving you is quite flexible. You can give this enemy different properties and behaviors. I will give you a regular sized enemy version and also a both sized spread sheet. Let's implement both now to make our game even more diverse and fun to explore. You can download all art assets in the resources section below. I put it inside my project folder and I reference it here inside index HTML image with a source squid morph. Ng and ID will be squid morph. We hide that image with CSS because we only want to draw it with Java script on canvas. Squid morph is a soft, flexible space bug. It can absorb a lot of our projectiles, but we noticed that each time it absorbs one, it inflates a little bit. Let's just feed it projectiles until it pops. I constructed this spread sheet to create an inflatable enemy type. If we give it, let's say ten lives, each time we hit it, it just grows a little bit bigger. But this spread sheet will work even if you want to design your squid morph differently. If you give it only two lives when you hit it with the third projectile. The rest of the frames will just play in one quick sequence. This spreadsheet will also work for that, I hope it makes sense what I mean. But let me show you code as well. Basically, we have an enemy that you can modify however you want. The spread sheet I'm giving you will work if the enemy has anything 1-10 lives. If you remember here on line 161, we have our parent enemy class contains the methods and properties shared among all different enemy types. Then we are extending that class to add properties and methods behaviors specific to individual enemy types. Because we want each enemy type to have a different image, different number of lives, and so on. Beetle Morph is our basic simple enemy. Rhino morph is an armored back with a thick exoskeleton. Eagle Morph will sacrifice its own body segments and it will spit them back at us. Now we will add Squid morph, an inflatable enemy that eats our projectiles until it pops. At this point, it's very simple to add more enemy types because we already have so much of the logic in place from the previous lessons. I can just copy the rhinomorph code block. I rename it to Squid Morph. And we pointed to the Squid morph sprite sheet here. And that's it, It will work just like this. Down here on line 405, we have our wave class. Creates enemy waves and organizes them in a grid like formation using this custom create method we wrote earlier. I'm calling thotrandom here and here. Which is not the best way to do this because I want the code to be easy to read. I want it to be very easy to read. Which percentage of the wave is made out of which enemy type. I will roll maotrandom just once per enemy in the grid. From that one random value, we will decide which enemy type will be added. I will call that variable, for example, random number and it will be random value 0-1 Like this if random number is less than 0.3 enemy will be Eagle Morph. Roughly in 30% of the cases, 30% of each wave will be made out of Eagle morphs L. If the same random number is less than 0.6 when that random number is between 0.3 and 0.6 another 30% of the wave will be rhino morphs L, meaning that when the random number is between 0.6 and one, the last 40% of each wave will be made out of beetle morphs. I hope it makes sense. We actually have four enemy types. I will add one more else. If block here, I have to be very careful about brackets. When I do this, it's easy to break my code with a single misplaced bracket. We are testing squid morphs now. I will add them here. I can put eagle morph here, for example. It doesn't matter yet, because I want the most of the wave, actually the entire wave to be made out of squid morphs now, because we need to test them. As you can see, they already work. And all we did so far is we re used the code block for rhino morphs. When I play the game, I can see that we need to tweak a few things. The logic we have here is that time we hit an enemy, we swap its spreadsheet by one frame horizontally. When the lives of the enemy are less than one. As defined here on line 186, we keep increasing frame X to play the explosion animation. Once frame X is more than max frame, we know we can delete the enemy because its entire explosion animation finished playing. To actually see that explosion animation, I check my squid morph spreadsheet. And I see that I need to increase max frame to, let's say 16. To make sure all these frames get displayed before the enemy is deleted from the game. Now I shoot it. I deplete all four lives. It plays the rest of the spread sheet showing the enemy inflate and pop, I designed the spread sheet so that it will work when the enemy has one life or nine lives. For example, we just jump frame by frame as we hit it. Whenever we deplete the lives, it will just play whatever frames are left. If I do this, I notice we have a bug. Something is pushing frame Gs back when it was already showing the explosion frame. It's because we are moving frame eggs here and also here. Let's make sure these two lines of code are mutually exclusive. And they don't run at the same time in the same animation loop. Code block only runs when the enemy has less than one life. Here I make sure this line only runs when this lives is more or equal to one. This should fix the bug. If you go to line 243, you give your squid morph two or five or nine lives. You can test it and see that the spreadsheet will work in all these cases. I also prepared a Bo spreadsheet with squid. Moorphi added them to the existing Bo sprite. You can download this new version in the resources section below, called it boss eight because there will be eight different boss creatures. I bring them into the project. Here boss eight, dog, and ID is boss eight. We have eight different boss visuals on this spreadsheet. Eight different rows. I hide it with CSS. I go to my boss class and I reference that image here on line 347. Now I can set frame y to be a random value, 0-7 Like this, I commented out just to test the spreadsheet, I will set frame Y to zero. Down here, I want the waves to start with a boss to make it easier to test. I Sat Frame X20, Frame Y zero is this version of the mantis morph. Row one is this frame Y two will give us this row. Frame Y three is this frame Y four will give us the new squid morph. You can see it reacts to being hit by a saddle animation of its two front tentacles. Same as the other bosses from before. When we deplete its lives, it just plays the rest of the spread sheet in a nice low frame rate explosion animation. Frame six will give us this strange space creature. Notice that all of them animate a little bit every time we hit them with our basic attack frame y seven will give us this space squid. We know that everything works. So I will set frame y to a random value 0-7 giving us one of these eight bosses randomly down here. I want my game to start with an enemy wave. I want each wave to be made out of 25% squid morphs, 25% rhino morphs, Ego morph is actually very difficult to deal with. We make it only 20% of the wave, and the last 30% will be made out of beatle morphs, the simple, basic enemy. If you use the same settings I used for this game, try to play it as long as possible and let me know your score in the commands. It can become quite difficult and chal***ging as the game goes on. And both health and the size of the waves keeps growing. Well then if you managed to get this far, this was a big project and we learned so many different tricks and techniques. If you had fun coding with me, you can check out my other classes. I'll see you later. 29. Lobstermorph Enemy Class: Analysis, successful enemy contact confirmed. It seems that our lasers are triggering a cellular mitosis in this species. Al peculiar, what does that mean? If we shoot them, they divide into multiple smaller critters. Ah, so we first have to split them and then we target the clones. Yes, that seems to be the most potent strategy. Let's divide and conquer. I made other projects with art assets that are compatible with this game. Let me show you how to take a sprite sheet from that utter game and use it here. It's very simple. You can download the spread sheet in the resources section below. I put the image into my project folder and I reference it here. The source is lobster. Moorphpng ID will be lobster morph. We will hide the image with CSS here we already have all the logic in place. I can just copy this code block we used for Squidmorph. Max frame will be 14 lives will be eight, as long as lives are more than one. Every time we hit the eneme, we will increase the frame in the spreadsheet by one, slowly progressing the animation. This eneme splits into multiple smaller clones when we hit it. Now we just have to decide which portion of total enemies will be made out of this new enemy type. I create new L if block. Again, I'm very careful about the brackets because single wrong bracket can break my code. You can choose your own values. Here we have five different enemy types. I think it's appropriate to make each enemy type roughly 20% of the wave we are dealing with random numbers. Some waves will have more lobster morphs than others. I test it, it mutates. Every time I hit it, it splits into clones that works well. I made another game that focuses more on this particular space bug. If you are interested, I will see you in the other class where we build a planetary defense game. Having multiple enemy types like this makes the game more interesting to explore. And we add the enemies here to make the player think and strategize a little bit. As the game gets more difficult, we have to prioritize targets, use different weapon types, and position ourselves well. Here we are, achieving all of that by creating a variety of enemy types with different properties. This was fun. 30. Project 2: JavaScript Planet Defense: Every game is made out of a few basic building blocks. Once you understand these techniques, you can get creative, combine these elements in different ways, and create many unique games easily. In this class, we will cover many of them. From keyboard and mouse controls to performance friendly sprite animation tips and tricks. And the main focus this time is object pool design pattern. We will use it for enemies and for player projectiles. Because re using our objects rather than creating and discarding them over and over can be a massive performance benefit. Today we are building an animated two D game completely from scratch with no frameworks and no libraries using just plain van Java script and HTML five canvas analysis. Successful enemy contact confirmed. It seems that our lasers are triggering a cellular mitosis in this species al peculiar. What does that mean? If we shoot them, they divide into multiple, smaller critters. Ah, so we first have to split them and then we target the clones. Yes, that seems to be the most potent strategy. Let's divide and conquer the interrogam revolves around the planet. Literally, we control a spaceship and we need to defend the planet from asteroids and all different kinds of aliens and space bugs. This project is completely standalone and independent, but I designed the art assets to be compatible with Space Invaders game we built before. And at the end, I will show you how to take sprite sheets from that game and implement them in this project with just a few lines of extra code. This class is for creative coders who want to learn about the fundamentals of two D game development, as well as for Javascript beginners who want to practice their object oriented programming skills on a fun visual and interactive project. Let's go as usual, we start with a normal generic blank webpage where we link CSS style sheet, create a HML five canvas element with an ID of canvas one. And we link script JS file in style CSS. I give canvas a border, I put background PNG image into my project folder and I use it as a background for my canvas. You can download all project art assets in the resources section below. I want the canvas in the middle of the page both vertically and horizontally. So I use the absolute positioning technique. For example, everything else will be done with Javascript. In script JS file, we will use images and other resources in this project. We need to wait for all of the assets to be fully loaded and available before we run any Javascript code that depends on them. For that reason, I will put my code inside a callback function on a load event listener. When load event fires and all resources are ready, we will run a Javascript code. First, I point Javascript towards my canvas element using its ID. I sat context to two D. As usual, we always have to do this line. When we're setting canvas up, we are making a two D game. Today I set canvas to 800 times 800 pixels here, which will reveal the full background artwork. 31. Project 2: Planet and Game Class: I can define my planet class up here, outside the event listener. As long as I make sure I only instantiate that class from inside the load event listener. Later, let me show you all objects in this project will need XY coordinates and radius because everything will be a circle and we will be detecting collisions between them. Draw method will take context as an argument to specify which canvas we want to draw on and also to keep our classes as self contained as possible. Inside we will draw a circle representing the planet. We pass arc method XY coordinates of the centerpoint radius of the circle. Start angle of the circular shape path and angle which will be method pythons to a full circle. In radians, we call fill method to fill the path with the default black color. Inside the load event listener. I instantiate the class using the new keyword. Now I can use this planet variable which holds an instance of planet class. I can call draw method we defined on line seven. It expects context. I pass it CTX from line 15. We have our planet here drawn at coordinates 200, 200. I can change its radius, I can stroke it instead. Let's set stroke style to white and maybe line width to two pixels. We can move it around and resize it by adjusting these values. This is our planet class. I actually want to have a main game class, the brain of the code base. We will draw, update, and control everything from here. Constructor will expect canvas as an argument. Inside we convert it to a class property. From that property, we will extract width and height. Because I want width and height properties of our main game object to be the same as the width and height of the actual canvas element that we will be drawing and animating the game on. Instead of creating a variable called planet and instantiating planet class, that way, I will create a property here called this. Planet Game class will also have a render method. This method will be called over and over for each animation frame. Updating and redrawing our shapes and objects, we will need context as an argument inside. I will take this planet property from line 19, which now holds an instance of planet class. And I call its associated draw method from line seven, passing the context argument along like this. Now we are taking this planet class and we are instantiating it inside the game class constructor. I can delete these lines and instead I will create an instance of game class. It expects canvas as an argument. I pass it canvas from line 27 through that. Game will now have access to width and height properties of canvas and width and height of game is automatically set to 800 times 800 pixels. I can take that game variable from line 34 and I can call render method from it. We defined it on line 21 and we can see it expects context as an argument. I pass it CTX from line 28. Important thing to understand here is that the code inside a class constructor is executed once at the point when we create an instance of that class using the new keyword. When I create an instance of game class here on line 34, it also automatically runs all the code line by line and an instance of planet class is created and saved as this planet property here on line 19. I like to do it this way. I think it's cleaner and easier to navigate In structuring our code like this in classes and objects is called object oriented programming. This entire project will be a simple object oriented code base. Now planet class is connected to game class. And I can still change properties of the planet by adjusting any of these values. These same properties can now also be accessed from inside game object through this planet property, which will become important later. What if I want this connection to be two way? I also want the properties that sit inside the game class to be accessible from inside the planet class. Do it by passing a reference that points towards the main game object to the planet class constructor like this. Keep in mind that objects in Java script are so called reference data types. By doing this I'm not creating a copy of the game class here. I'm just creating a reference that points to a space in memory where the main game object sits. When any properties that sit on the main game object update their values, those changes will be immediately visible from inside the planet class let class constructor expects a reference to game as an argument here where I call the planet constructor, I need to pass it that game reference. Since we are inside that game class, I pass it this keyword which when used here, represents the entire game object. Now we have a nice and simple two way connection between planet and game classes. We can test it by accessing width property from line 18 from inside planet. Because I want the planet to be exactly in the middle of the game area game with Tams 0.5 If what we are covering here is too fast or too complicated for you, check out the previous class where I go much slower in a beginner friendly pace. For the rest of this project, I assume you already know the basics of Javascript and object oriented programming. You can download the planet image in the resources section below. I bring it into the project as an IMG element. Here in index HTML, I give it an ID of planet. We can see the image here. I want to hide it. We will draw it, but with Javascript on Canavas not like this. There will be more images in the project. I will put all of them inside a diff with a class of hidden in CSS. I set this hidden diff to display none. Great, we will bring it into the project here as this image property on planet class. Now I can call built in draw image method. And I pass it the image we want to draw and X and Y coordinates, where to draw it on canvas x and y of a circle represents the center point around which the circle is drawn. But with rectangles and images on canvas X and Y coordinates define its top left corner. If I want to align the rectangular image over the circular It box, normally I would offset it by radius, which for all other objects in this game, will be exactly half of its width. But for the planet image, I made it a bit larger because we have these clouds around it. And I don't really want those clouds to be active in collisions. Enemies and asteroids will only collide with the planet when they hit the actual body of the planet, not the clouds. For that reason, I have to offset it by a bit more. Let's say by 100 pixels. Now we aligned the circular planet at box over the rectangular image. We will keep the white circle for now. It will represent the collision area of the planet. 32. Project 2: Mouse Position: As we said before, any code inside a class constructor is automatically executed at the point when we create an instance of that class using the new keyword. I'm already taking advantage of that and I'm automatically creating an instance of planet class at the point when I create an instance of game class. At that same point when we create game using the new keyword, I also want some event listeners to be applied. We will listen for mousemove event normally with event listeners we would create a standard callback function and some code to be executed inside every time a mousemove event fires. The challenge here is that I'm putting the event listener inside a constructor on an object. We are inside game class and we are calling the event listener from window object with a regular callback function. We would lose access to this dot properties that sit on the game class to keep that access, to make sure that this event listener remembers that it was lexically defined inside the game class and to allow us manipulate this properties on game class from a callback function on this mousemove event listener, we have to either bind the function or much simpler we can use ES six arrow functions in tax here. Because one of the special features of arrow functions in Java script is that they automatically inherit this cured from the parent scope, it will have the autogenerated event object as an argument. I give it a variable name. For example, since this function has only one argument, the brackets are not mandatory. I can delete them like this. Now, whenever mousemove event fires, autogenerated event object will be created. Let's consolog that object so we can inspect it because we put the event listener inside the game class constructor. The event listener will be automatically applied when this line of code runs, when an instance of game class is created using the new keyword. Now I move mouse over canvas and I see those objects every time a mouse move event takes. If I open the mouse event object, I see it contains all kind of information about the mouse event that just happened. What I need is the X and Y coordinates of the mouse. We can see those properties here. I want those mouse coordinates to be available all over my code base, not only from inside the mousemove event listener. I will create this dot mouse object on the main game class, and I give it x and y properties. We use ES six arrow function here, so we can use this dot from inside the callback function. I can actually take this dot, mouse dot x from line 25. And I can set it equal to x to the current horizontal exposition of the mouse. I also do the same for the vertical Y coordinate. Okay, as we move mouse over canvas, we are taking x and Y coordinates from the event and assigning them to our custom dot mouse property to make them available all over the project. We can test how accurate these coordinates are by drawing a line from the middle of the planet to the mouse. We want to draw a simple line. So we start by begging path. Move two method will define the starting x and y coordinates of the line. It will be the middle of the planet. Line two method will define the ending coordinates. It will be the current mouse position. Now we stroke that line to actually draw it on canvas. The line doesn't react because we are calling render method only once on the first page load. We want to call it over and over for every animation frame to see some movement. Let's create a simple animation loop custom function. I call Animate. We put this render call inside. Then we call built in request animation frame method which sits on the window object. But that part is optional. I can delete it. Javascript knows where to find that method without us having to tell it that it's on the window object. I pass it animate to create the loop. I call it once on the first page load like this to actually kick off the first loop. Now as I move mouse around, render method runs and draws line from the planet to the mouse as we defined on lines 38.39 It looks like this because we see old paint. We see all the previous animation frames. We actually only want to see the current animation frame. I delete the entire content of canvas between every frame by using the built in clear rectangle method. We clear the entire canvas from coordinates 00 to width and height of the canvas area. Now we are animating the line and we can check if the coordinates we are capturing from mouse event line up with our game objects. It's all good now, but look what happens when I make the window larger because canvas is not full screen. Those x and y coordinates don't account for the white space between the web page and canvas element. Suddenly the coordinates are completely wrong. The line no longer goes from planet to the mouse. We can offset those mouse coordinates by accounting for the white space around canvas manually or even easier. Mouse event object already does that for us automatically. It gives us those adjusted coordinates. Instead of using these X and Y properties, we will use offset X and offset Y from here. Replace them here. Now the line will go exactly from the mouse to the middle of the planet. We know we are capturing the correct mouse coordinates. Perfect. Offset X and offset Y properties are useful for projects where your canvas is not full Screen. I delete the consolog. 33. Project 2: Player Spaceship: Time to create the player class. Its job will be to manage visuals, behavior, and controls of the player. I'm not sure if I made it clear, but we already have a fully animated code base. I'm not animating and moving the planet around, but I can already do that. If I want to look at this, we know that render method runs over and over for every animation frame. I can increase the horizontal position of the planet by one pixel per frame and we get movement. This code base is already fully ready for all sorts of animations. I'm just not moving things around yet. I can move the planet horizontally. I can move it vertically down and up. It just looks static now, because I'm not moving things around yet. We will get there soon. Same as we did with the planet class. I need access to properties and methods that sit on the game class. From inside the player class, I'll create a property, a reference pointing towards the main game object. As we said before, all active objects in our game need to have x and y coordinates and radius. So that we can use these values for collision detection between circles later. Also, all objects in this code base from now on will have radius of 40 pixels. Radius is a half circle. The rectangular sprite frames will be 80 times 80 pixels. Art assets from this project are fully compatible with the main Space Invaders game we built before. Feel free to take them and use them in that project as well. If you want, I will show you a fun way, how to do that in a bonus lesson on that project. I'm sure some of you can figure it out. Even without my help, it might be fun to add the unique enemy type we will be implementing in this project to that previous project as well. Just as an exercise, I made sure it's all compatible. As usual, player will have a draw method and we will draw a circle representing the player. Whenever we draw a circle, we have to start with the begin path. We use method to map the path. We actually draw it on canvas using built in stroke or film method. This is the player class. We will just repeat the pattern we did with the planet. I instantiate it as this player property. Here we will call player draw method. We defined on line 24 inside render like this, player will move around. I will need an update method if I want the planet to move around in some way, for example, rotate, I would have to give it update method like this as well. For now, let's just increase the horizontal exposition of the player by one pick Siler animation frame. Just a test it, I call the update method we just defined. From here player is moving because render is called over and over from inside animation loop on line 75. We could also attach players horizontal position to the mouse. Like this, I want the player to rotate around the planet and always face the direction towards the mouse. This part will be a bit more challenging to implement for beginners, but once we get that to work, the rest of the game will be easy. First, I will bring the player image into the project. You can download it in the resources section. Below, I give player class this image property and I pointed towards that new image we just included I call built in draw image method. And I passed the image and X and Y coordinates. Now if we move the player both circle and image move together like this. I want to offset the rectangular image so that it sits directly on top of the circular hit box. I offset X and Y by the half of the player width and height by the radius value. I prepared all art assets for this project at specific sizes that we will need in the game. Doing this saves me a lot of work now while I'm coding, because the images are ready to go, and I don't need to scale or resize anything with code, which would be wasteful anyway in terms of performance. 34. Project 2: A Little Bit of Math: I want to move the player around the planet depending on where the mouse currently is in relation to the planet. We will write all that logic in a reusable method. I call, for example, calculate Am doing it this way. We will be able to reuse this method later to make enemies face towards the planet as they attack us. Method will take object A and object B as arguments and it will calculate a vector direction between these two objects. Let's say we have two objects that have x and y position. For example, the center point of the planet and the mouse cursor. These two objects sit somewhere in the game area. We want to calculate the distance between these two objects on the horizontal x axis. First, it will be the horizontal position of object A minus the horizontal position of object B. We do the same for the vertical axis. Now we have two sides of an imaginary right triangle. And we want to calculate the distance between these two points, in this case between planet and the mouse, for example. We are calculating a distance between two points in a two D space. We need to calculate a hypotenus of this imaginary right triangle. Right angle would be here. This is the hypotenus of the right triangle. The longest side opposite to the right angle. This is a perfect use case for Pythagoras theorem formula which would look like this in Javascript code. But since we are using Javascript, it's even simpler because we have a built in method hypotenous method available. We just need to pass it this side and this side, and it will give us the length of hypotenus, which in this case is the actual distance between object A and object B. We passed here as arguments. Now I need just two very small numbers that point in a certain direction, vertically and horizontally. And combination of these two values will give us a direction vector between object A and object B. We will use that to make the player spaceship point away from the center point of the planet towards the mouse cursor, I will reduce my vectors to a value range between minus one and plus one by checking the ratio between x and hypotenus. Distance, that will be the horizontal direction because the distance the hypotenus is always more than x. Because mouse can be to the left or to the right from the planet. The resulting value here will be anything between minus one and plus one, but it can never be more than one because the Dx is always less than distance less than hypotenus. Keep in mind that the mouse can be to the right of the planet, but also to the left like this for example. That's why the resultant ratio value can be negative as well. Anyway, now we have everything we need. We know in which direction we need to push an object if we want to push it towards another object or away from another object, mx and my values are telling us that horizontal and vertical push I will make this calc Am method return an array of values because we will need multiple values. From here to position the player hit box and then to correctly rotate the player image, we have to remember in which order we are returning these values. We know that when we call Calc Am, it will return an array where the element with an index of zero is the horizontal direction between object A and object B. Value with an index of one is the vertical direction. The vertical vector index two is the distance between a and B horizontally. Index three is a D Y the distance between object A and object B vertically. I know this was a lot of math. Sorry, we are almost done. Now, if this is your first time using this technique, don't worry about it too much. Just follow along what I'm doing. You need to use it more often For other projects, it will eventually make more sense to you. Repetition really helps with this. For now, just understand that we wrote a method that gives us a distance between two points in a two D space. And we will now use those values to point and rotate objects towards or away from each other. I want to move the player around the planet, always facing the mouse. I can implement this in many ways. For example, I can give the player this dot am property for every animation frame. I will set this dot a property to that custom calc Am method we just wrote. We will make it calculate and produce those four values and return them as an array. That method gives us the distance and direction between two points. So I want to check those values between mouse and the planet. The relative position between mouse and the planet will determine where the player is facing. I will consulate this dot am and we will get that array with four values that Lkm method returns for performance reasons. It will actually make sense to only update this dot. Aim only when mouse move event fires. Because if the mouse doesn't move, we are recalculating the same value over and over for each animation frame, which is not necessary. As we said before, calc method returns horizontal direction, vertical direction, horizontal distance, and vertical distance, in this case between mouse and the planet. Because those are the two values we passed to it as object A and object B. I'll get here, so I delete the consolo. Now I can use these values to rotate the player towards the mouse. Horizontal position of the player will be always starting from the middle of the game area, which in this case is also the horizontal x position of the planet, the center point of the planet circle. We just want to add to it that small directional vector value. But because that value is very small between minus one and plus one, we would barely see the motion. I multiply it times, let's say 50. Perfect. That already works horizontally. I can do the same for the vertical y position. We go from the center point of the planet towards the mouse. And we enhance that vector again by multiplying it times 50. Yes, that works. The number we use here to multiply the vector by, will now influence the distance between the planet and the player spaceship. Let's say I want the distance to be equal to the radius of the planet. We get some interesting motion. If the vertical and horizontal values don't match like this, it would be useful if the planet was elliptical, for example. Now the center point of the players circle moves along the radius of the planet circle. If I want to move it out of the planet completely, we have to push it by half of the player circle further, plus player radius. Like this, we need to use brackets to make sure the addition happens first, and then the resulting value is multiplied by the vector. You can play with the values if you are coding along, and it will make it clear what's happening. 35. Project 2: Understand Canvas Rotation: We don't need this line anymore. We also want to rotate the player image to always face towards the mouse, away from the middle of the planet. I will give player a property I call, for example this angle. When you call canvas rotate, it will transform canvas state. So everything drawn after that rotate would be rotated. We only want the spaceship image to rotate. I restrict any changes to canvas state by wrapping it between built in safe and restore methods. We save the canvas state, we do any changes here, then we call restore and reset everything other shapes drawn on canvas after remain unaffected. Canvas rotation is a bit unintuitive if you never saw it before. Basically remember this. To rotate something on canvas, first you have to translate rotation centerpoint, which is the same thing as coordinates 00 on canvas. You have to translate that over the coordinates of the middle of the object you want to rotate. Then you call rotate, you pass it angle, you want to rotate by in radians. Then you draw that object you want to be rotated. But we draw that object not at its x and y coordinates, but at coordinates 00. Because the actual position of the object is now expressed in the values we passed to translate. I think it's safe to say that canvas rotation is much more complicated than CSS rotation. But it's actually easy if you do it a few times. Let's actually do it in code. I want to rotate the player spaceship. I translate rotation centerpoint over this dot x and z dot y coordinates of the player. Rotation centerpoint is also coordinates 00 on canvas. Now I'm pushing player too far because I'm expressing its position here by translate and I'm pushing it even further from there by dx dot Y coordinates. This might not be the best example to teach someone rotation because we have the player spaceship image here and also the hit box circle. So there's a lot going on here. Exposition of the circle is zero and the exposition of the image is minus radius. Because of the difference between how rectangles and circles are drawn on canvas, x and y is the centerpoint of a circle, but it's a top left corner of a rectangle or image when we're drawing shapes on canvas. Anyway, now we fixed it and we are successfully translating rotation centerpoint over the player spaceship. Now when I rotate, it will rotate from the middle of the player image, which is exactly what I want built in Canvas. Rotate method takes the rotation angle value in radians. I pass it this dot angle from line 25. This is rotation by 0 Radians method pi will rotate the spaceship like this by 3.14 radians, which is approximately 180 degrees. Half circle method pi times two is 6.28 radians, 360 degrees. We rotated the spaceship all the way around. Half pi is 1.57 radians, or approximately 90 degrees, we are facing upwards. Now I hope it makes sense. We need the angle to be value 0-6 0.28 radians, 0-2 pi. We need that angle value to match the direction between mouse cursor and the planet center point, so that the player is facing towards the mouse. For that, we have another useful built in method called method A 102, which gives us a counterclockwise angle in radians between the positive x axis and a line projected from coordinate 00 towards a specific point, towards specific x, y coordinates. The result in value is actually a value between minus pi and plus pi. Important thing to note here is that we pass it DY first and x second. We pass these arguments the other way around. This is just how the built in method works. We are already calculating these values in calc method. They are being returned as values with index 2.3 in this array. Because we count indexes in array from 00123. I don't have to run calm method again. We are already running it on line 38. I will just take this aim that holds that returned array. And I take element with an index of two, element with an index of three x and D Y values. Okay, so we can see that it can work in, this is useful for so many things in creative coding and game development. By the way, I need to fix this just buried me a second until I figure this out. How about if I swap these two values? Trigonometry can be tricky, okay? That if I multiply these values by minus one, right? Give me one more second, okay? I made a mistake here. I said that math 8102 needs DY first and dx second. But yeah, I'm passing it x and DY, I need to swap them around. Yes, this is exactly what we need. Perfect. This was a lot of math. If you made it this far, the rest of the project will be easy and fun. We did the most challenging part already. Now we have our reusable calc M method. And we can use it again whenever we need to get a distance between two objects and point them towards each other or make them move away from each other. I will show you how to do that when we implement enemies a bit later. 36. Project 2: Debug Mode: We define event listeners here. Let's implement another event listener. This time for a key up event. Inside I consologe the auto generated event object. Now when I click on Canvas and I start typing on the keyboard, we see the key that was pressed. I can say if the key that was pressed is a lower case D, set this back property to true. We will create this, do debug here. When we press letter D, we will actually set this dot D bag to its opposite exclamation mark, Like this. I consolok this dot D bag when I press D on my keyboard. Now I toggle debug mode on and off. If it's true, letter D will set it to false. If it's false, it will set it to true. This trick is useful for many other things as well. It's good to remember this technique inside the draw method on player class, we are drawing the player image, the spaceship, and we are also drawing a circle around it. This circle will represent the collision area. Players hit box. It's a useful thing to see sometimes, but I want to have a way to show and hide it. I will say only draw the collision area circle around the player if D bug is true. Now when I press letter D over and over, I'm showing and hiding the hit box. It's the same with the planet. We have the planet image and wide collision circle around it. Let's only draw it when this game do debug is true, like this. Again, I can press letter D on my keyboard repeatedly and it will show and hide these collision elements. We can show and hide all kinds of helpful information in our game. Like this, we are now able to enter the debug mode in our project, which will help us to develop the game. At the same time, we can easily hide these elements to see what the final result for the user will look like when the hit boxes and maybe some other support elements are hidden. 37. Project 2: Object Pool: This is starting to look pretty good. We have a planet, a player that rotates around it, and we implemented a debug mode. Now I want the player to be able to shoot laser projectiles. We need to make sure those projectiles fly in the correct direction from the tip of the player spaceship towards the mouse cursor. On top of that, we will optimize performance of this project by implementing projectiles as a reusable object pool. It means that instead of constantly creating and discarding these projectile objects as the player shoots, we will create a pool of objects. And we will pull from the pool when we need them and we will return them back to the object pool instead of destroying and deleting them. Object pool design pattern helps us to better manage automatic memory allocation and garbage collection processes. We allocate the memory just once when we create the initial object pool, which is more performance efficient. Garbage collection is an automated process where Java Script reclaims memory by removing objects that are no longer referenced anywhere in the code. Garbage collection happens automatically, and it can sometimes happen at inconvenient times. For example, at a time when we need to animate a large enemy wave. And as a result, it can cause lower frame rate and animation stutter. We want our game to run smooth and fast and to always respond quickly to player inputs. So we will completely eliminate the garbage collection process by reusing the same, let's say 20 projectile objects over and over, rather than discarding the old ones and creating new ones. This simple performance enhancement technique can do a lot for your projects. Let's learn how to implement it on Projectiles, and when we understand it, we will use it for enemies as well. Class Projectile will be used as a blueprint to create that initial pool of let's say 20 reusable projectile objects. As usual, we need a reference to the main game class to get access to properties and methods that sit on the main game object. Projectiles will be involved in collision detection, so we need to make sure they have x and y coordinates and radius property. I will make them large at first so we can clearly see them. The objects created by this projectile class will be so called object pool members. We need to give them a property that indicates whether the object is available in the pool or if it's currently being used. Initially, free property will be set. The true projectile object is sitting in the pool inactive. It's waiting to be used. It's ready and available, it's free. Every object pool member needs two methods, start method that will run when we pull the object from the object pool and make it active in the game. At that point, we set free property to face. This object is no longer free and available. It's being used, drawn and animated in the game. We also need a reset method instead of deleting the object. When we are done with it, we will call its reset method that will set its free property back to true. It means the object becomes inactive, ready to be used again when we need it. When we shoot a projectile, we will call its start method to activate it. When the projectile collides with an enemy or when it flies off screen, we will call its reset method to deactivate it. We will give it a draw method. We will only draw the object when its free property is false, when it's active in the game. We don't want to draw it when it's just sitting in the object waiting to be used. Update method will move the projectile around. Again, we only want to run the update code for active projectiles if this free is false inside the draw method, we draw a circle representing the projectile begin path R method. Don't get confused here by the line breaks, it's all on one line, it just breaks for me to another line because my code editor window is too narrow. Because I want to show you the code and the project side by side inside update. If the projectile is active, we will update its X and Y position by speed X and speed Y values created the horizontal speed property and I set it to one pixel. One pixel per frame means it will move from left to right. Speed Y will also be one pixel, which means movement from top to bottom. These two speeds will combine to determine the final direction. The combination of these two particular speed values, 11, will result in a motion in the bottom right direction. The Projectile class is ready. It is an object pool member. It has a free property, start and reset methods. And the code inside the draw and update only runs when the object is active, when its free property is set to fall. We will manage the object pool from inside the game class from the main brain of this code base. Projectile pool will be an array that holds all active and also the inactive projectile objects. Number of projectiles will determine how many objects we want to create and have available in the pool. If we have too few of them, we can run out and don't have any available when we need them. If we create too many, we might be wasting memory if we are never using a large portion of the pool we created. We will get to the right number later when the game is playable and we can test how fast we are using and re using them. As the game is created, we will automatically run a custom method. I call create projectile pool, which will fill projectile pool array with five inactive projectile objects. I will write that method down here. Inside I create a four loop which will run five times. Each time it runs, we take projectile pool and we push new projectile inside. I can see it needs game as an argument. I pass it this keyword. The main game class will manage our projectile pool. We store five object pool members in projectile pool array and we create them on the first page, load as soon as we create the game object. Because as we said before, all the code inside the class constructor is automatically executed. When we create an instance of a class using the new keyword, we need a method to create that projectile pool. And we also need one more method. I will call, for example, get projectile. When we call this method, it will cycle over the projectile pool array we created. As we cycle through the indexes in the array we created earlier. As soon as we find the first projectile object with free property set to true, we know this object is currently inactive. It's free and available. We take it and we return it. Get projectile method, finds the first free object in the pool and it returns it again. Please don't get confused by the line breaking here, it's all on one line. It's just that my browser window is too narrow. If free is true, get projectile method returns the object and it stops searching initially. All projectiles are free, they are inactive and free to be used. If we run start method, we activate them and they are no longer free. I add one more event listener, this time for a mouse down event. When we click the left mouse button on mouse down set mouse X and Y to X and Y of the event and call shoot method on the player class. This player is accessed through this reference here is that class. Let's give it a custom shoot method. When we should we create a temporary helper variable, we set it to that custom get projectile method we just wrote. We access it through this game property here and it sits on the game object down here. This method cycles through the pool and it returns the first free projectile object. Let's say we are currently drawing all projectiles. They are all currently active and we run out of free available ones that could break our code. To fix that I say if we found a free projectile, if get projectile method was actually able to find one that is free and available only then take that free projectile and call its start method to activate it. Here some properties of the projectile object change values as we animate and update it. We need to reset them to default at some point. We can choose to do it when we activate it, but also when we deactivate the object. I will do everything inside the start method. When we activate the object, it will be simpler to implement in combination with other choices we already made with this particular code base. Start method will expect x and y coordinates as an argument, and we set those values as tx and ty. At first, let's start all projectiles from coordinates. Let's say 100, 100. I should have also consologed the pool just to check if after this method runs, it was actually filled with five objects. All good. I inspect one to make sure we don't have any errors here. If you see any non value, not a number, it could mean we have a problem somewhere as we calculate these values. All is good here. I delete the consolog inside render method. I delete this begin path. I take the entire projectile pool array, and for each projectile object inside the array, I call its draw method, passing it context and I also call update. If I click, nothing happens. I follow the code to find my mistake. First I check if this mousedown event is actually running. Quick. Consolog will help me here. Yes, I know the problem is not here. The next step would be to see if the shoot method is actually running icsolog projectile from inside here. When I click, I can see that Get projectile method is correctly returning projectile objects from the pool for me, great, that means the problem must be somewhere on the actual projectile class. I come down here and I see I forgot one line. Arc method doesn't actually render shapes on canvas. To actually draw it here, I need to call either stroke or fail. Now when I click on canvas, we are drawing projectiles. I want to give them a different color, but I want that color to be restricted only to the projectile drawing code and don't affect any other shapes we draw on canvas. Later I wrap this code between safe and restore methods at fill style to gold projectiles move towards bottom right. Because of the combination of these two speeds, one pixel to the right and one pixel down per animation frame will result in this direction of movement. Start method expects X and Y coordinates as arguments. I actually want the projectile to start from the player who shoots them. I pass it to this doxy because here we are inside that player class that worked. 38. Project 2: Player Projectiles: If I keep clicking the mouse, we shoot five projectiles. And after that, instead of returning a projectile, get projectile method starts returning undefined. It's because we run out of objects in the pool and it can no longer find any free available objects. There is no projectile object with three properties set to true anymore. Because we activated all five of them, I will make sure that projectiles automatically reset when they move off screen. The horizontal exposition of the projectile is less than zero, if it's more than game width, or if the vertical position is less than zero, or if it's more than game height. If any of these four conditions is true, we know the projectile moved all the way to the edge of the screen. So we can call its reset method, which will set its free property to true. It will deactivated. It also means that because of these checks, that projectile will no longer be drawn and updated. Now I can shoot if all five projectiles are active, we are still getting undefined. We click more, but as soon as one of them moves off screen, it gets reset and we can reuse it and we shoot it again. Great job. We have a working reusable object pool. Now I want the projectiles to fly in the correct direction. We already have a custom Calc Am method that takes two circular objects. It gives us horizontal and vertical direction. We can use it to make them move towards or away from each other. We are already calculating that value from before and we are setting it to this Dom property on the player class. We can use the same value because we still want the direction of the movement of the projectile to be determined by the relative position between the planet and the mouse. We want the projectile to fly from the middle of the planet towards the mouse. First I pass start method speed x of minus one and speed y of one. We make sure that start method expects these values and it sets its speed x and speed y properties to those values. They are being added to its position coordinates here minus one pixel per frame horizontally and plus one pixel per frame vertically will result in this direction of motion. Minus ten and plus one will give us this. Let's use the values we get from calc method. We know that vertical vector is index zero in the array, the horizontal vector is index one. We are using these values, which are the ratio between horizontal distance and hypotenous distance. Now we can fire projectiles in any direction. They move quite slow. I can create a speed modifier property. As long as I multiply both of them by the same modifier value, it will just scale the vector keeping that correct direction. We are running out of projectiles. Let's create some buffer. Maybe I want to create 30 in the pool to make sure we don't run out. It does depend on how fast they move off screen and how fast they reset. We can test it and adjust the value later. The projectiles come from the middle of the players circle, which is not ideal. I want them to come from the tip of the spaceship. Here on the player class inside shoot method, we extend the starting x coordinates of each projectile by that horizontal vector value scaled to the player's radius that should sorted horizontally. I also use the vertical vector here, it's all on one line. I hope you can read my code. We are passing a lot of stuff to the start method. Now I'm using radius here, because I want the projectiles to come directly from the tip of the players spaceship. If you use different values here like this, it should make more sense what exactly is happening here. If you play with these values for a while, if I use this dot radius here here, the projectile will come out from exactly the point that I want. We shoot when we click alternatively. I can also say if the key that was released is number one on the keyboard or any key that you choose. Also call player shot. Now I can shoot by clicking the mouse or by pressing a key on my keyboard. Every time we shoot, get projectile method. We'll reach into projectile array from line hundred seven. It will give us one free projectile object. Start method will position it at the tip of the player spaceship. And calm method will give it horizontal and vertical speed that matches the relative distance at the point in time between planet and the mouse to send the projectile out in the correct direction. As soon as projectiles move outside the canvas area, we reset them and they are ready to be re, used whenever we need them. We implemented an object pool in our code base. I make them move faster and I make them smaller. Yes, this is closer to what I actually want them to look like in the final game. I can delete this consolog now. 39. Project 2: Enemy Pool: Now that we saw how to implement an object pool in our code base, let's solidify that knowledge by repeating the same logic to create a reusable pool of enemy objects. Remember that each object pool member needs a property that indicates if it's active or inactive. We only draw and update if it's active. Start method will activate the object. It will set properties to some values that the object needs at the start of its life cycle. In this case, we position the projectile depending on the player position, and we give it direction of movement depending on the mouse position. Reset method is here. To deactivate the object, we have an array that holds the objects. We set the number. And we need two helper methods, one to create the pool and another one to get a free item from the pool. Let's implement something very similar for enemies to solidify this knowledge and clarify anything in case you're still not entirely sure how some of this works. Repetition always helps I create an enemy class. It needs a reference to the main game object. It needs X and Y, and radius. For example, let's set the starting X and Y coordinates to 100, 100. Just for now, we will be cropping rectangular frames from the sprite sheet By jumping by the width and height of the frame around the sprite sheet. I created the art assets to match what we need in game collision. Circles have 40 pixels radius. Individual sprite frames will be 80 times 80 pixels. This frame size also matches the Space Invaders game we did before. The enemy spride sheets are fully compatible and can be easily used in that game as well if you want to expand it. Speed x and speed Y will determine in which direction the enemy will be moving. Since this is a object pool member, it needs free property. Initially we said it, the true start method will set free to face to activate it. Reset method will set free to true to deactivate it. Draw method will expect context as usual. And the code inside will only run for active enemies. Update method will also run its code only for the active ones. At first, let's draw the enemies as simple circles. The usual combo of begging path arc method, I stroke them. Update method will move its x and y coordinates around depending on speed x and speed y values. Same as we did for projectiles. We need an array that will hold all active and inactive enemy objects. Enemy pool number of enemies will be 20. And we will automatically create and fill that pool with 20 enemy objects. At the point when we create an instance of game class, same as we did for projectiles. Create enemy pool will create and push 20 enemy objects into enemy pool array. Enemy class constructor expects game as an argument. I pass it this keyword, Get. Enemy will cycle over the enemy pool array we just filled with 20 inactive objects. I will check free property for each one. And as soon as it finds the first enemy object with three property set to true, it returns that object and it stops searching I consulate enemy pool. At this point, it should be filled with 20 enemy objects here. After we call the create method, yes I see them. I open one just to check. All seems good here. I delete the consolo. Same as we draw and update projectiles for each animation frame, we take enemy pool, call for each on it. For each enemy we call its draw and update. We remember that these methods will only run if the object is active, if it's free property is set to false. Initially, all enemy objects have a free property set to true. Calling start will activate the object. I want the first object in the enemy pool array to be automatically activated. Immediately as the game starts, I take one object with an index of zero inside enemy pool array and I call it start method. I can see it here. Let's activate the first five objects. To do this, we have to be careful. If we don't have enough objects in the pool, this would break the code because I'm not doing an if statement. Check first, make sure the number here is high enough. I'm drawing all five enemies at the same coordinates. If I move them, all of them move, I could set the starting x and y coordinates to 00. When start method runs, let's set X to a random value between zero and game width, vertical y position to a random value between zero and game height. Now when I refresh the page, the five enemies are scattered randomly around the visible game area. As always, we are adding speed x and speed y values to their x and Y coordinates for every animation frame to give them direction and speed of movement. Combination of these values will determine their movement vector. I set speeds 200. We will set their speed when start method runs. I want the enemy to move directly towards the middle of the planet. They are attacking us. We need a vector between that random enemy starting position and the planet. We already did something similar. I create a temporary helper variable called am. It will run our utility method, but this time we want directional vectors between the enemy. This keyword, we are inside that enemy class as object B. We pass it the planet. If you remember, it returns an array of four values. The first element, the element with index of zero is the horizontal direction. Element with an index of one is the vertical direction. It doesn't work and it's right. It's because we need to calculate the aim after we position the enemies. Enemy Position is of course, very important in this calculation to get the correct direction between the enemy and the planet. First I set my position, then we call calm. Now the enemies are moving towards the planet. Perfect. 40. Project 2: Collision Detection: I want the enemies to go through the planet like this. I want them to collide with it. Let's create a reusable check collision method. It will expect object a and object BS arguments. In this project all objects will have circular it boxes To check collision between two circles, circle A and circle B, we have to check the distance between the center point of circle A and the center point of circle B on the horizontal axis. That gives us this site. Then we do the same on the vertical y axis to get this side. Now to get the actual distance between these two points into the space, we need the length of the hypotenus, which we can get by ptagoras theorem formula or built in mathod hypotenus method. We have a distance between two points, between the center point of circular object A and circular object B. We calculate the sum of their two radii. If the distance between the center points is more than sum of radii, we know that the circles don't collide. It's the same, the circle touch. If the distance is less than the sum of radii, we know that the circles collide. I will just directly return the expression like this, making this method easy to use. We call it, we pass it object A and object B. And this method will directly return true or false depending on whether or not these two objects collide. Let's see if it works by going up to the enemy class. And inside the update method, we check collision between enemy and planet. When collision happens, we will reset the eneme which will deactivate it and returns it back to the pool of available objects. I copy this code block. We do the same thing for the player. If enemy collides with the player spaceship, we reset the eneme. Let's see. Yes, that works. 41. Project 2: Periodic Events: When we reset the enemies, they are gone. But now I need more enemies to keep coming. Right now we only activate the first five enemies from the pool. Here I want to activate new enemy periodically. Let's say every 1 second request animation frame method automatically generates a timestamp. And it passes that timestamp value as an argument to animate method. Imagine it's passing it here like this. Even though it happens invisibly behind the scenes, the timestamp value is simply the number of milliseconds that passed since the first request animation frame in this sequence was called. All we need to do to get access to that timestamp value is to give it a variable name. Here, the Java script will automatically know that we wanted the timestamp. We also need to keep track of the timestamp from the previous animation loop. I'll call it last time I put it outside animate here. Initially I set it to zero. Then we use these values to calculate delta time. Delta time is the number of milliseconds it takes our computer to serve one animation frame. It's the difference between the time stamp from this animation loop and the time stamp from the previous animation loop. If you have a fast computer, your computer can serve frames faster. Your delta time will be lower because that fast computer needs less milliseconds to generate each animation frame request. Animation frame method also automatically normalizes the animation speed. If it can do it, it will adjust animation speed to the screen refresh rate because there is no point to calculate and draw animation frames that your screen isn't able to display. Once we calculated delta time we set last time to the current time stamp. So that it can be used as the old time stamp from the previous animation loop. In the next animation loop, most of us have screens that serve 60 frames per second. 1,000 milliseconds divided by 60 is around 16.6 my delta time is 16.6 my animation is running at 60 frames per second. If you have a high refresh rate screen or if you have a very old weak computer, your delta time might be different than mine. Using delta time like this will make sure we account for that, we count the actual time, actual milliseconds. This allows us to make sure the timing in our game is the same. On fast and slow machines, I delete the consolog. I pass delta time to render method. I will make sure render method expects that value as an argument, and I consolog delta time from here. Yes, it still works. Always make sure you delete your consologs. Leaving a consolo like this can slow your application down. These variables relate to enemies. I will only add one enemy at the start of the game. I will need two helper variables, enemy timer and enemy interval. Enemy timer will count delta time from zero until 1,000 Then we add new enemy and we count again. We want to periodically activate an enemy object from the object pool every 1 second, every 1,000 milliseconds. If enemy timer is less than enemy interval, we keep adding delta time value to the timer for every animation frame, over and over until we get more than 1,000 And then this L statement will run when timer accumulated enough delta time. We reset timer back to zero so that it can count again and we activate one new enemy help er, temporary variable called enemy will be equal to our custom get enemy method. If get enemy was able to return a free and available enemy object from the pool, we call its start method to activate it. Nice, We are pulling a new enemy from the object pool every 1 second. I don't really want the enemies to appear somewhere in the middle of canvas randomly. Let's try something. If I call method random on its own like this, it will return a value 0-1 if that value is less than 0.5 Roughly in 50% of the cases we said horizontal position of the enemy between zero and game width, and vertical position will be zero. Enemy will appear somewhere in this area. In the other 50% of the cases we set x to zero. Y will be a random value between zero and game height. The resulting position will be randomly, somewhere in this area. Nice, now we can do it for the other two sides as well. How to do that? For example, we can use a so called ternary operator. The only Javascript operator with three operands. We use it as a simple one line FL statement. It goes like this. A condition to evaluate if true question mark, do this ls colon, do that. If method random is less than 0.5, vertical position of this enemy will be zero L In other 50% of the cases dot y will be dot height. If this code block runs, enemies will be coming from here or from here. Yes, we do the same in this code block. If method random is less than 0.5 this dot x is zero, x is game width, while at the same time, vertical position is random between zero and game height. If this code block runs, enemies will be coming from here or from here. Now we have enemies randomly coming from all four directions. When they collide with the player or with the planet, they get reset and they disappear. I also want to be able to shoot the enemies. I want to check collision between enemy and projectiles. I take the entire projectile pull array for each projectile object. I check first if the projectile is active, if its free property is set to false. Keep in mind that this code block also only runs for active enemies. We only want to check collision between active enemy and active projectile. If the projectile is active, we also check collision between this enemy and the current projectile we are cycling over. If projectile and enemy collide, we reset the projectile to deactivated and return it back to the object pool. When I test it, I can see that projectiles get destroyed when they hit enemies. Great. I will also reset enemy when the collision happens. Nice, now we can shoot the enemies. We have a full game loop and we implemented projectiles and enemies as object pool which involved some extra logic. But it's worth it for performance reasons. The code is still clean and easy to read. I think I don't like how the enemies just pop in. I want that to happen off screen, and the enemy just floats into view smoothly and seamlessly. I will push the enemy starting positions outside the screen. I account for the radius, here, here, here and here. Now they start off screen and they float into view much better. I can make the enemies comma more often. How about new enemy every half second. 42. Project 2: Asteroid Enemy: The planet is really under attack. Now white circles are attacking us. Let's use some graphics. First, we do a simple enemy type, an asteroid. We can download the enemy spread sheet in the resources section below, Give it an idea of asteroid. This is the parent enemy class. It contains all methods and properties shared among all enemy types. I will create a child class called asteroid class. Asteroid extends eneme. Now enemy is a parent class, also called a superclass. Asteroid is a child class also called a subclass asteroid class. Constructor will expect game as an argument here. First, I want to run all the code inside the constructor. Inside the parent enemy class inside its superclass. I want to run all the code here. I pass the game reference along. We know it's expected there on line in 98. Asteroid child class will contain properties and methods that are specific only to this enemy type. Asteroid will have this dot image property which will point to that asteroid spread sheet we imported a moment ago. Shared properties are on parent class. Specific properties and methods are on the child class. Because we are using the extent keyword here. Javascript automatically sets up a prototype chain behind the scenes when we call draw and update method on asteroid class and Javascript can't find them here, it will automatically travel to the parent enemy class. It will try to find those methods there since all enemy types will have images. I can go up here and I can call build in draw image method. I pass it the image I want to draw and x and y coordinates. Where to draw it, we get an error because we are instantiating the parent enemy class and the Java script can't see this image property on it. I have to create an instance of asteroid child class instead. Now we are drawing the entire spreadsheet. I will reduce the maximum number of enemies to two so that it's less busy and easier for us to see what's happening. We can pass draw image method, optional width and height like this. Now the entire image will be stretched or squeezed to fill that predefined area. In this case, I'm squeezing the entire asteroid spread sheet into an area of one frame. We can also pass, draw image nine arguments to get the maximum control over the image we want to draw. We pass it the image we want to draw source x, source Y, source width, and source height of the area we want to crop out from the source image. And we pass it destination X, destination Y, Destination with and destination height to define where on destination canvas we want to place that cropped out piece of image on two. First, I crop out this frame from coordinate 002 with and height of one frame. Nice again, as we know, circles and rectangles are drawn differently on canvas. To align the rectangular asteroid image over its circular head box, I need to offset the horizontal position destination x argument by the radius. Like this, I also offset the vertical Y coordinate by the radius. Like this planet is being attacked by asteroids. Now I increase the size of enemy object, pull back to 20. I want a new enemy asteroid every, let's say 1,700 milliseconds. I only want to draw the collision circles on enemies. If debug mode is active, I want to be able to show and hide them by pressing D on the keyboard, by totaling debug mode on and off. 43. Project 2: Sprite Animation: We can navigate around the spreadsheet and decide which frame we are currently cropping out by adjusting the value we pass to draw image method. Here source x argument can be like this. Zero times width of a single frame will give us this one times width, we get this frame. Five times width is this frame. The way I structure this spry sheet. Horizontal navigation around the spry sheet will play explosion animation frames. Source y argument will go up and down around the spread sheet. Zero times height is this frame, This is one times height, two times height, three times height. Source y argument passed to draw image method will determine which one of these four available asteroids we are drawing. I will put this multiplier into a variable. I call frame Y. I can put it here, but maybe each enemy type will have different spreadsheet with different number of animation rows. I put frame Y here on the asteroid subclass. I want to randomize it. Each asteroid object will be randomly assigned one of the four variations of the asteroid I created for you. I need to wrap it in method floor to round it down to integers because there is no row 1.5 For example, frame Y will be randomly zero or one, or two, or three since enemies are an object pool. If I play like this, I'm constantly just re using the first one or two objects over and over, returning them to the pool, taking them again, that's why the images don't change. I can, for example, randomize the row every time enemy object is activated here, inside the start method. For now this is fine, although it can give us issues if other enemy types don't have force sprite roles. I can also make the enemies more challenging by giving them multiple lives. I give enemy object a custom at method. This method will take damage value as an argument. When it method runs, we reduce lives of enemy by damage. Here we check collision between enemy and projectiles. Instead of resetting the enemy immediately, I will call that hit method and I pass it one as damage. Doing this means that when we hit an enemy with a projectile, we reduce its lives by one if lives of the enemy are less than one. I want to keep increasing frame X to play the explosion animation, we need to use that frame X value here. As it increases from 01234, we are cropping out different horizontal sprite frames and we are playing the animation. I could put frame X on the parent class, but let's keep it on here on the child class next to frame Y. Now when I hit asteroid five times and deplete its lives, the rest of the spread sheet will play the explosion frames. Now we need to also reset that asteroid when all its horizontal animation frames are played. I will give it a max frame property and I will set it to seven. We know that once all seven frames were displayed, we are safe to reset it and return it back to the pool. If frame X is more than max frame, we call reset since enemies are object pool members, we also need to reset these values. As we reuse these objects, I will give it max lives property and it will remember what was the original amount of lives of that enemy before we started damaging it. Now when I shoot the asteroids, they don't come back because their frame X is stuck at a high value and they keep resetting. When we start an asteroid, we need to make sure it's Frame X is set back to zero. Its lives need to be set back to max lives. Nice, now it all works. When the debug mode is active, I want to display the number of lives as a big number drawn over each asteroid. We will do it here inside this conditional code block that runs only when debug is active. I call built in fill text method that takes at least three arguments, the text to draw and x and y coordinates of anchor point in relation to which the text will be drawn. The text I want to draw is lives property of the enemy and we want that number to travel around as the enemy moves, I give it xy coordinates of the enemy. Down here where we set our canvas up, I will define canvas font property. Let's set it to 30 pixels. Helvetica fill style will be white. I increase the font size. As you can see when we position the text anchor point exactly in the middle of our circular asteroid, the text is drawn towards right top. From there, the anchor point sits on the left bottom edge. Text Align Property defines where the text we draw on canvas sits in relation to its anchor point on the horizontal x axis. I set it to center text Baseline property defines the relationship between text and its anchor point Vertically, I set it to middle. Now the text is centered over the asteroid. Nice, when we destroy the asteroid, the explosion, animation frames play too fast. We are using sprite sheets with limited number of frames to help us with performance. Now we need a way to slow down the speed at which the sprite sheets swap frames so that users can actually appreciate the details of the animations. We will use the same technique we used here with timer and interval helper variables. Sprite update will be false. It will switch to true periodic ledges for that one animation frame to allow all the sprite sheets in our game to jump to the next frame. Sprite timer will count delta time from zero to sprite interval value over and over. Every time it reaches the interval it triggers sprite update and resets back to zero so that it can count again. Let's say I want to trigger sprite update every 150 milliseconds, we will write the logic to periodically update sprites. Here we are repeating the same logic we used to activate enemies. If sprite timer is less than sprite interval, keep increasing sprite timer by delta time, which we are already calculating from before. It's the time in milliseconds. It takes our computer to serve one animation frame else, meaning that sprite timer is higher than interval. It accumulated enough milliseconds through delta time, we can reset sprite timer back to zero so that it can count again and set sprite update to true. I want sprite update to be true just for that one animation frame. Here, I will set it back to false. Now this code block means that sprite update is set to true for one frame. Every time sprite interval value that we set, 250 milliseconds is reached. When I consolo sprite update, we see it is false and it is periodically set to true. Great, every time it is true, I want to animate sprite sheets, I want to jump to a new frame in the sprite sheet. Let's not forget to delete the consologe. We will handle sprite animation logic here if the lives of the asteroid are less than one. Only if sprite update is true, only ten. We increase frame x by one. Now the explosion animation play slower. We can set that speed to anything we want using sprite interval property. The problem is that now when the explosion play slower, I notice that the projectiles still collide with asteroid that is already exploding. I want the projectiles to ignore explosions. We only check collision between enemy, asteroid and projectiles if the lives of the enemy are more or equal to one. If the lives are less than one and explosion animation is playing, projectiles will fly through it. Yes, this is much better. I can show and hide hit boxes by pressing letter D, by enabling and disabling the D bug mode. 44. Project 2: Lobstermorph Enemy: I want the asteroids to have only one life. It will be a simple, basic enemy type. Our lasers are calibrated for asteroid defense and we can easily destroy each one by a single hit. Let's add a more challenging enema type. You can download Lobster Morph Spread Sheet in the resources section below. As usual, I put it into my project folder and I included it here, giving it an idea of lobster morph. At this point, it's easy to implement more enemy types because we already have most of the logic in place. I copy this entire code block for asteroid and I rename it. I point this dot image property to the lobster morph spreadsheet. I can set max frame to 14. We know that when we reach that point, it's safe to reset the enemy. I created the spread sheets with a specific plan in mind. Asteroid will have one life when we hit it. The rest of the spreadsheet will play the explosion animation. Lobster morph will have eight lives. Each time we hit it, we jump by one frame until we deplete all eight lives. Then the rest of the frames will play in one animation sequence. Down here I comment out asteroid class, and instead I will push lobster morph enemy type into enemy pool array. Okay, we have some aliens incoming. I play to see what we have so far. I can press D to disable debug mode. I can see that when I hit them eight times and deplete the lives, the entire spreadsheet plays. I can go here inside hit method. And when we hit the enemy and we decrease its lives by the damage value, I can set frame X to be max lives minus the current lives. This will work already. It goes to a new stage every time it loses a life, and then the explosion plays. I can do it differently here. I can say if enemy lives are more or equal to one, every time we hit it. Increase frame X by one we get the same behavior. Enemies get instantly reset when they collide with the player or with the planet. When enemy collides with the planet, I instantly set its lives 20 which will play the spreadsheet. I also want the enemies to stop moving at the edges of the planet. I set speed x20 and speed y20. Collision with the planet happens when enemy hit the planet. Now they stop and they play their animation sequence. I think this looks more interesting. They play the sequence when the current frame is more than max frame, they reset and return back to the object pool. When enemy collides with the player, I will just set lives to zero. To make it animate. I'm not going to stop its movement. You can make your own choices Here, design the game how you want it. I'm just showing you how the code base works. We have a bug if you consulate enemy. Each time we activate one, you will notice some of them are stuck off screen, not coming from one side of the screen at all. Because their horizontal position is none, not a number. It's because I said this game dot radius here, I need to use the radius of the enemy instead. You probably noticed that before. Anyway, now it's fixed. I want to rotate the enemies to make sure they face towards the planet in the direction of their movement. Every time we rotate canvas, it adds up and it affects everything drawn on canvas. I want each enemy to be rotated by its individual angle value. I will restrict any changes I make to each enemy drawing code by wrapping this code block between safe and restore methods. We save canvas state, we make any changes here we want to be applied to these drawing calls. Then we reset back to what it was before to make sure the shapes drawn after this remain unaffected on canvas. I can't just simply rotate if I rotate by 0.1 radians. Here you will notice that everything is a bit off to rotate anything on navas. First we have to translate rotation center point, which is the same as coordinate 00 on navas over the center of the object. We want to rotate. I translate to zx dot Y of the enemy we are about to draw. Now that we translate it, we have to keep in mind that we are translating rotation centerpoint as well as the point that is considered coordinate 00 on canavas. We are translating it over the enemy position. Then we are going further from there to actually draw the enemy. We effectively doubled the enemy position, pushing it further to the right and to the bottom of screen. Enemy position is now defined by the translate. So we have to actually draw everything at coordinate 00. If I draw enemy collision circles at coordinate 00, we get this. I also have to do that for the text coordinates that display enemy lives. For the actual image which is centered over the circle. By offsetting it by radius, we do minus radius here and here. To rotate something on canvas, we translate over the object we want to rotate. Then we draw that object at coordinate 00, because the object's position is now defined by translate. Now I'm free to rotate it and it will work if I rotate by 0.1 radians, 0.5 radians. Instead, I will use a distal angle property. I define it here, 1 radian means all enemies are rotated like this, 2 radians. I want the rotation angle to depend on the relative position between the enemy and the planet. We already wrote helper Lkm method and we are using it to set enemy speed. Lkm method gives us directional vectors as well as DX and DY vertical and horizontal distance between the two objects we pass to it as arguments I will need. I can see these are elements with indexes of 2.3 returned in this array. Initially, I set angle 20. It doesn't really matter because when start method runs, we set this angle based on the relative position between this enemy and the planet. We already did that when rotating player spaceship away from the planet centerpoint. It's the same thing here. We use built in method 102 method that will give us an angle between positive x axis and a line projected towards a specific point. We know it expects dy first and dx as the second argument. I have to pass these arguments in this order. Enemies are not pointing where I want them to. But it doesn't matter because we know the angle we are getting is relative to the starting position of the enemy and the planet. Start method runs just once to set the enemy up and I can adjust that resulting value in many ways. I could rotate the entire lobster or spreadsheet in my graphics editor, and then I could use that, but I could also easily do that with code. I can see I simply need to rotate the enemy by 90 degrees, by a quarter of a circle, to make sure they face the planet. I add method pi value here. If I add method pi, I'm rotating it by 3.14 radians, by 180 degrees, half circle. I only want to rotate by a half pi, by 90 degrees, by a quarter of a circle. Even if you don't fully understand method 8102 yet, just remember how to use it. Pass it the points that are relevant in the rotation you want and see what result you get. Then you can easily adjust that angle further like we just did. There might be even a simpler way to do this that I'm not thinking of right now. I know some of you will give me your tricks and improvements in the comments, and I appreciate that. Anyway, enemy aliens are now facing towards the planet. Every time we hit them, we push the spreadsheet to the next frame when lives are depleted. Animation, Play animating spread sheets like this is very cheap. Performance wise, your game will run smooth If you are happy with a low frame rate sprite animation like this, I think the game looks alive. Even with this performance friendly sprite animation techniques, I like how it reacts to player actions. It makes the game feel very interactive and responsive. 45. Project 2: Game Text : Draw status text method will display score, player lives, and game over messages. It will expect context as an argument. Font will be 30 pixels impact. For example, you can easily use any custom Google fonts here if you want. Just import them in index HTML. Give canvas that font family property in style CSS and use the name of that font family here. Instead of impact it will work. I use custom fund in other games many times before this time let's just go with default impact fund and focus on other things I call built in fill text method. Text will be score coordinates will be 2030. I want the text to be drawn over the planet but under the player and projectiles and enemies will create a nice layer effect when the text is in the middle of game objects. When I call draw status text and I pass it context, I can see that score text is center aligned and enemy lives are now drawn in different font. This declaration changed the entire canvas state again. I wrap it in safe and restore so that I can give status text specific settings without affecting other texts and shapes drawn on canvas. I said text align to left. I create this score property. I go to the main enemy class when enemy finished playing explosion animation and is reset back to the object pool. I increase the score by enemy max lives, which means easy asteroid, enemy will give one scorepoint. Lobster morph, enemy will give eight scorepoints. It has eight lives here, I add score to actually draw the value. Every time I destroy an enemy and the explosion animation finishes playing, I get rewarded eight scorepoints. You can see that every time enemy explodes, we get eight score points. I only want to award the player scorepoints if we destroy the enemy by shooting it, the enemy gets destroyed because it collided with the player or the planet. We don't want to give score points for that. I will give each enemy a property called collided. Initially, I set it to false. When we start the enemy, we always have to reset it back to false. If enemy collides with the planet, we set collided to true. Also, if the enemy collides with the player. If enemy collides with a projectile, we do nothing, which means collided will stay false. Here, we only add score if collided is false. If I shoot the alien, I get eight score points. If the enemy collides with the player or the planet, we get no score points for that grade. I create a property called winning score. Initially for the testing purposes I set it to ten. We will handle win or lose condition here inside the render method. If score is more or equal to winning score, game over is true. Down here inside the draw status text method, we will handle game over messages Game over is true. I want two big messages in the middle of the screen. We set text a line to center. I can, for example, create two Led variables called message one and message two. They will be assigned a different text when we win and when we lose. If we win, if score is more than winning score, message one will say you win. Message two, your score is, We display the score value plus an exclamation mark like this. Now we will draw them. Message one will be large, 100 pixels. Impact, Again, you can use your own custom font here instead of impact. Filltext method will draw message one in the middle horizontally and 200 pixels from the top vertically. Another fill text for message two, again, in the middle horizontally, and let's say 550 pixels from the top vertically. Let's try to win the game. I need ten or more scorepoints. Nice, I want the second message to be smaller. How about 50 pixels impact again? I shoot enemy one, enemy two. Here we go. Yes, that looks better. I want the enemies to stop coming when game over happens on a pool, a new enemy object from the pool, if gameover is false. 46. Project 2: Player lives: Now, how can we lose this game? We can, for example, give the player a limited number of lives. I put those lives here on the main game object. I go down here. Oh, this restore needs to be down here. Otherwise the numbers we use to display enemy lives will change. 250 pixels impact when game over message appears, now it's fixed. I want to draw player lives under the score. I create a four loop. It will run once for each life, and it will draw a rectangle for each one. Left margin will be 20 pixels. Horizontal position will determine the space in between rectangles, so it will be 15 pixels. We space them out by multiplying that space in Tams index in the four loop vertical position will be maybe 60 pixels from the top. The width of each rectangle should be less than space. In, for example, ten height will be 30 pixels. You can change these values to see what they do. This is the left margin, this is horizontal spacing. If the width of each individual rectangle is the same or more than the spacing, they will turn into a single bar. You can build loading bars like this if you want. I want them to be separate here, so I go for ten, I guess. If enemy collides with the planet, I take this game lives and I reduce it by one. Also, when collision with the player spaceship happens, I test it. When we collide, it immediately takes all five lives. Because it's taking one life per animation frame. We only want this code block to run for enemies that have lives more or equal to one. We enter this code block and we set lives to zero, which will prevent the same code block from running. Again, this should fix it. I do the same for player collisions. Yes, now one collision takes away only one life Perfect. Here inside win and lose condition code block I say if score is more or equal to winning score or if the lives is less than one in both cases, set game over to true, which will stop enemies from coming. And it will display big message one and message two. If we win, we set messages to these else, meaning we lost all lives. Message one will say you lose. Message two will say try again. I test it. I shoot enemies, I win. Enemies collide with the planet. We are losing lives, we lose all lives and losing message appears great. We have a complete game loop. Initially, I will set D bug to false. We can still toggle it on and off by pressing letter D on the keyboard. I want to bring all enemy types into the game at the same time. Here where we create enemy pool, I create a random number variable. I set it to random value 0-1 if random number is more than 0.25, in 25% of cases we create an asteroid L. The other 75% of cases we create lobster Moorph Asteroid is the easy enemy type with one life. Lobster morphs are tough enemies that morph and split so they take longer to defeat. I want to add a new enemy more often. Let's say every 1 second I want to be able to make enemies move faster or slower. We did the same thing with player projectiles. I create a speed modifier property. I want to slow them down. In this case, speed modifier will be a random number between 0.1 and 0.6 Then I include speed modifier here, where we calculate horizontal and vertical speed. I'm scaling the vector here. I prefer the game like this. We have many more enemies on the screen, but they all move slower, giving us more time to strategize. It's up to you to choose if you want the game to be more about fast reactions or positioning. End strategy, you can tweak enemy frequency and movement speed based on what kind of gameplay you prefer. How about enemy interval, 800 milliseconds and 30 lives, 50 winning score? I will adjust these values later. 47. Project 2: Beetlemorph Enemy: I built another space game recently inspired by the classic Space Invaders. I made sure that the spread sheets from that game are compatible. Here let me show you how we can take them and easily use them in this project. If you follow that class, you already have the sprid sheets. If not, you can download them in the resources section below. I import beetle morph spreadsheet into the project. To add more enemy types into this game is extremely easy because we already wrote all the logic. I can just copy this code block. I rename it to Beetlemorph. I adjust this dot image property, I check the spread sheet, max frame will be three and lives will be one. This enemy is easy to defeat. Down here where I create enemy pool, I can say if random number is more than 0.5 Add Beetle Moorph. I have to be careful about brackets here. I have to change the condition here. If random number is less than 0.25 we create asteroid. If the number is less than 0.5 we create Beetle Moorph. In the other 50% of cases, we create a lobster morph. That was easy. Now the game has even more variety. 48. Project 2: Rhinomorph Enemy: Now that we understand the process, let's take one more enemy type and use it. I copy this code block and I create rhinomorph enemy type, the armored enemy. Again, you can download the spread sheet down below if you don't have it from the Space Invaders project. Here I add one more L if random number is less than 0.75, we push Rhinomorph into enemy pool array Code editor colored this class name differently to remind me that I still haven't written that class up here. I copy this code block. I rename it Rhinomorph. I point its this dot image to the new spread sheet. Max frame will be six, it will have four lives. Now our game has four different enemy types. Simple enemies with one life will be asteroid and Beetle morph, an armored eneme eneme that splits into smaller clones. When we hit it said enemy interval to 1,200 milliseconds and play lives to ten if you watched the extended Space Invaders class over there. We also have Squidmorphan inflatable eneme that absorbs player projectiles until it pops. We also have Eagle Moorph, an eneme that sacrifices its own body segments and spits them back at us as mutated projectiles made out of slime and tentacles. All of those art assets are fully compatible with this code base. A challenge for you is to take them if you follow the extended class and implement them in this game. If you want, you can also take the unique enemy from this class, the Lobsta Morph, and implement it in the Space Invaders game. These two games are completely cross compatible. I only want to increase the score if game over is false. Like this, it's easy to do and if you need my guidance, I implement Lobster Morph into Space Invaders game in the extended class. If you are watching this on my Youtube channel, the most popular and recent extended bonus classes are linked on the about page. Hope you had fun on this space adventure. This was a big project. Well done. If you go this far, let me know if you found some value and learn something new by leaving a quick comment, I wonder which part of this project was the most interesting for you. Can you just leave a quick comment and tell me which is your favorite enemy type Out of all of them, it can be either what it looks like or its unique behavior and mechanics. Looking forward to see what you think and which one is your favorite. See later. 49. Project 3: JavaScript Mobile Game: Headquarters. Let's build a mobile game. Don't get any closer to that gas giant, something is stirring in the upper atmosphere. First we will write all the game logic and implement all the main features. You can reuse that boilerplate later for many different touch based full screen games. And then we add graphics, animations, and sounds, turning it into a cartoon space horror game. I want you to build projects you can be proud about and you can show to your friends. This one will be a full screen game. Touch events look layable on any device from a big horizontal computer screen to a small vertical mobile phone so you can carry it around with you if you want to show everyone what you learned and what you can do with Java Script. Our presence triggered a feeding frenzy. They seemed to be attracted to the life signs of our non mechanical crew members. Immediate retreat advised endemic to the supercritical fluid layers of this distant gas giant. This creature lives in an extreme pressure. They can face through solid obstacles. We need to hit them when they're in their solid state to time your attacks carefully. 50. Project 3 Setup: In index HTML, I create a simple blank web page. I give it a title, I link CS style sheet, I create HML five canvas element with an ID of canvas one. And I link my Java Script file in style CSS. I do a global reset to make sure we get a consistent behavior across different browsers. By removing the default styles, I give canvas a border position absolute. I center it in the middle of the page vertically and horizontally. You can download two background images in the resources section. Below. I take the horizontal background and I set it as background URL. Here, background size is cover, which will scale the image to the smallest possible size That still completely covers the width and height, leaving no empty space. I create a diff with a class of controls. We will have a full screen button and a reset button. We will also control full screen and reset with keyboard, but we will need these patterns for mobile devices. I will give these buttons with height, black background, and white text if you want. You can also use a custom font. For example, I can go here to Google Fonts. I search for a font called bangers. I select the font here and it gives me links that need to be included in index HTML. Ideally, up here before I include style CSS like this. Now I can use bangers all over my code base. For example here for font on the buttons, I also give them a white border. 51. Make Everything Responsive: We will write all the logic here with Java script in main JS file. Maybe I will split this into multiple files later. Here we can define our classes, but we make sure we only instantiate them after load event has fired. After all the resources are loaded and available. All the style sheets, scripts, HTML elements, images and so on. Once the page has loaded and we know HTML cannavas element is available, we can set our project up. I point to Java script towards my canvas element using Get element by ID, I define CTX. That will store an instance of built in canvas to D API. I said canvas width and height to cover the entire browser window in sty Sss, I said background position to center to make sure the planet is always in the middle. On any screen size, I position the controls left bottom Like this. I can also organize the buttons vertically using flex box, transparent background, and no border on controls. Here, margin on buttons five pixels, I can give it box shadow and text shadow. For example, transition 0.3 seconds on hover, active and focus. We animate box shadow and text shadow, and also the button background game class will be the main brain of the code base. It will manage the state of our project. It will expect cannavas as an argument. Inside we convert it to a class property, and from there we extract width and height, because I want to make sure that width and height of the game is always the same as the width and height of cannavas. We give it a custom resize method. It will expect width and height as arguments. And we will resize canavas element to these new values. It will also set the width and height properties from lines 8.9 to these new values. I create an instance of my game class expects Canvas. So I pass it canvas variable from line 20. When we create an instance of a class, all the code inside a class constructor is automatically executed line by line. I can take advantage of that and I can put my code in here that I want to run. At the point when an instance of this game class is created using the new keyword, I can even put event listeners here. We will listen for resize event. The only problem is that the event listener is on the window object and I'm placing it lexically inside my game class. If I want to access this keyword from inside this callback, it will refer to the window object. For that reason, when I try to resize my browser window and built in resize event triggers Using this dot resize here will result in an error. Game object is not visible from inside here. We need this keyword in here to point towards the game object to allow us access to properties and methods that sit on the game class, including our custom resize method. I can do that by using ES six arrow functions here instead of a regular callback function. One special feature of arrow functions is that they inherit this from the parent scope. Now using this dot here will point towards the game object which is exactly what we need. Now when resize event triggers, we are setting width and height of navas game to 150 times 150 pixels. If I consologe the auto generated event object itself, I can explore it. This object gives us all kinds of information about the event that happened, in this case the resize event. For example, here inside target, we can find in width and inner height properties which will give us the new dimensions we resized to. I can take these values and resize my canavas and game to these new values. Now when we create an instance of game class on line 29, all the code inside the constructor is executed. Resize event listener is automatically applied. Now I can resize my browser and canavas will also cover the entire available browser area. We can also click down here to emulate mobile devices. It is not always 100% accurate compared to testing your code on that device natively. But it is close enough to get started. This is Google Chrome browser, by the way. It might look different for you if you are using a different browser. I recommend using Google Chrome for this course. I can now select different devices from this drop down, and I can see what the game will look like. Sometimes the preview glitches out. When we swap between devices, I need to manually refresh the page. This doesn't really matter because in the real world, no one will be swapping between iphone and Samsung phone without reloading the page. Reloading the page always fixes the positioning problems. If they come up, you can see that our simple prototype works relatively well already. Let's keep working on this. I can also create a media query for small screen sizes. I will assume this is a mobile phone. And in that case, I will use a different background image that is more vertical, suitable for vertical mobile screens. I'm giving you both of these high resolution images in the resources section below. You can also crop this image and use it for other projects if you want. Now we have a very simple responsive game world that works on wide horizontal screens as well as on tall vertical screens. Perfect. 52. Enemy Class: To keep this code base easier to navigate in, I will create another Java script file called enemy JS. Here we will have our enemy class and we will extend it into multiple enemy types. I could use Javascript modules here, but then I would have to show you how to run a local server. I will keep this simple and I will just include MGS file here like this. It needs to come before main GS. When we do it this way, the order in which we include individual Javascript files can be important. I can cut enemy class from maina JS and I paste it here inside NMS, enemy will expect a reference pointing to the main game object as an argument. Inside we convert it to a class property. Through this reference, we will be able to see and access all the properties and methods on the main game class. Each enemy will need X and Y coordinates, so that the Java script knows where on canvas to draw it, it needs speed x and speed Y. And within height, I will set it to 50 50. Initially, custom draw method will draw the enemy on screen. Game will have a render method that will draw all enemies as well as all other game objects. As we build our project up, it's good to test it step by step so we catch any potential errors at first, render will expect context as an argument. From there we will call built in fill rectangle method to draw a simple rectangular shape. I call this render method using the game variable from line 28. It expects context. I pass it CTX from line 24. The default fill style, if we don't override it, is black. We are drawing a black rectangle at these x and y coordinates. With this width and height, I can set fill style to a different color. Here, for example, green. We are building a game and things will be moving around. We achieve that by drawing, updating, and redrawing the objects over and over to create an illusion of movement. Custom method I call, for example, animate. I will call game dot render from inside. And I call built in request animation frame method sits on the window object. But we don't need this part Javascript, we'll know where to find that method automatically. I pass it animate, and I call it here to start animating. We are already animating. I can prove it by creating position x property, using it here as X position on the rectangle. I increase position x by one for each animation frame. We see old paint. I can also clear canvas from the old paint between every animation frame using built in clear rectangle method. Now we have a moving green rectangle we are animating. I can delete this when I resize browser window Resize event listener will trigger our custom resize method which sets canvas to the new within height. As a side effect, when we resize canvas, it sets canvas state to default. All the properties will be reset, including fill style, which will be reset back to the default block color. For that reason, when we resize, we need to redeclare these styles. One way to solve this is to make sure we have access to this CTX variable from inside our custom resize method to make sure the green fill style applies. Even after resize, I can pass CTX from line 24 game class constructor as the second argument here up here, I make sure it is expected, I convert it to a class property. Now I can call built in canvas drawing methods and properties from this. While inside the game class, this line gets overwritten when resize method fires. Instead, I will set fills style to green here. After we resized, I will give our game a custom start method that will run just once when the game starts or when it restarts. And it will set everything up first. I just call resize to make sure the green fill style applies when the game loads it expects with and height as arguments. Initially, I pass it window in width and window in height. Same as we are automatically apply in the event listener here. We will also automatically trigger this start when an instance of the game object is created in the new keyword here. Now the color we give to Phil style will stay even as we resize the browser window. Perfect. Now I can take this Dogamex from here. Access through this property I call Phil rectangle representing the eneme. We pass it xy with in height of the enemy object. I can also give the eneme a different Phil style here. We need to give it some X and Y coordinates. Here I'm including enemy GS before main GS. Enemy class should be available from inside the game class. Here I create a property called dot enemy one and I set it to an instance of our custom enemy class. It expects game as an argument. Here, here we are. Inside that game object. I pass it this keyword through which enemy object will have access to all properties and methods on the game class. From render, I want to call draw method which is defined on enemy class. I say this enemy one from line seven, draw from line 11. Here, nice, we are drawing an enemy. And this confirms we have successfully established a two way connection between game and enemy classes. Nice work. This render method is called over and over for each animation frame. Here we are just redrawing the same red enemy at the same position. But we can also move it around by calling its update method. It doesn't exist yet. I define it here. For each animation frame I want to increase horizontal position of the enemy by speed x and vertical position by speed y plus one pixel on the vertical y axis will result in movement from top to bottom. Can also say if enemy moved all the way to the bottom, set its vertical position back to the top, I make it move faster. I can also randomize the initial horizontal exposition. I also randomize it every time we reset. I can create multiple enemies like this. You don't have to do this part. I'm just showing you a very inefficient way how to do this. It could work if we have just one or two objects maybe. But in this game I want to have tens, or maybe even hundreds of enemies. I can randomize speed Y to make them move at different speeds. If I randomize this on the first lo, start from a different vertical position, I can make them reset all the way behind the top edge. So they slide in from the outside of canvas area. We know that everything works. And we have an enemy class that can be instantiated multiple times to create a swarm of enemies. I delete all of this because there is a better way to structure this code. 53. Object Pool Design Pattern: I'm going to turn each enemy object into a reusable object pool member. It means that we will take it from the object pool and activate it when we need it. And when we are done with it, we will just return it to the object pool rather than deleting it, and we will reset its properties. Reusing our objects. Using object pool design pattern like this can massively improve performance of our code bases. Because we avoid issues related to automated memory allocation and garbage collection processes that run automatically. When we create and destroy many objects in a code base, we will reuse our enemy objects over and over saving memory. Every object pool member needs to have a property that indicates if it's currently active or inactive. I will call it free. If the object is free, it is inactive waiting in the object pool to be used. If free is false, it means the object is currently active in the game. It is being drawn and animated and it is not free. It is not available to be taken from the pool. Each object pool member needs two helper methods. Start method that will run. When we activate it site, we set free to false reset method that will run when we are done with the object. For example, when enemy gets destroyed, reset method will set free property back to true, returning the enemy into a pool of free and available objects. We will only update and draw the active enemies. We will run update and draw methods only if this dot free property is false. Enemy is an object pool member. It has a property that indicates if it's free or if it's currently being used. It has a method to activate it and a method to deactivate it, update and draw Methods Only run their code for active objects. When the enemy moves off screen, we call reset method to deactivate the enemy and return it back to the object pool some properties on the enemy object. For example, the x and y coordinates need to be reset every time the enemy object goes through its life cycle. We can reset them at the point where we take the object from the pool. Or at the point when we return it back to the pool. I will choose to reset the properties. Inside the start method, we will randomize the enemy horizontally, and we will set it just behind the top edge of canvas vertically. This is how you turn a regular object into an object pool member. The second part to this would be managing the object pool itself. We will do it from our state management class. Enemy pool will be an array that holds all active and inactive enemy objects. We need to choose how many enemies we create. This number will be static. It needs to be high enough so we don't run out, but also not too high because we would be wasting memory. We can adjust it later When the game is playable, 50 seems like a reasonable number game class will need two helper methods to manage the object pool. A method to fill the pool with 50 enemy objects. We will run a for loop. Each time it runs, it takes enemy pull array and it will push new enemy. In there, it expects game as an argument. I pass it this keyword here. We did that before. 54. Periodic Triggers: I want to call create enemy pool automatically. When we create an instance of game class I will cons log that enemy pool After we created it. I need to use this dot here in console I can see we have an array of 50 enemy objects. I open one to check, we don't see any undefined or null values which could indicate a problem. Now I want to periodically activate a new enemy. Let's say every 1 second, every 1,000 milliseconds. We are using request animation frame, which is automatically generating time stamps for us. Let's use them. I will create a helper variable I call last time. Here we will hold the time stamp from the previous animation loop request. Animation frame method is auto generating time stamps. All I have to do to access them is to assign them a variable name. Here it will know that we want that time stamp value. If we do this for every animation frame, I want to calculate delta time, which is the difference in milliseconds between the time stamp from this animation loop and the time stamp from the previous animation loop. After we calculated delta time, we will set last time to the current time stamp so that it can be used as the old time stamp. In the next animation loop, delta time tells us how many milliseconds it took our computer to generate one animation frame. Then we can pass that delta time value to render, where we will write some simple logic that will accumulate the small millisecond values until a certain breakpoint is reached. Then we can trigger an event request. Animation frame automatically adjusts the speed at which it serves the next animation frame to the screen refresh rate because it would be a waste to calculate positions for frames that your monitor or your phone screen is not able to display. In most cases that would be 60 frames per second. In render, I make sure delta time is expected. I consologatee thousand milliseconds divided by 60 frames per second is around 16.6 It takes my computer around 16.6 milliseconds to calculate and redraw each animation frame. Perfect. As the code runs, we are generating time stamps, calculating delta time and passing that to render method. From there, we can make this value available all over our code base to create any kind of periodically repeating event. Let me show you how it's easy. We will need two helper variables, anime timer and anime interval. Animate timer will accumulate delta time 0-1 thousand. Then it will activate one enemy and it will start counting again. We need one more helper method that when called, will search enemy pool for a free and available enemy object and it will give it to us. Inside we run a for loop over enemy pool. As soon as we find the first object in the pool with free property set to true the first inactive object, we will return that object. I can put that logic that activates new enemy every 1,000 milliseconds directly into the render method. But to keep the code a bit cleaner, I'll write it in a separate method handle. Enemies will expect delta time as an argument. If enemy timer is less than enemy interval, enemy timer starts from zero and enemy interval is 1,000 as long as the timer is less than the interval, we keep increasing timer by delta time, else meaning that the timer has accumulated 1,000 or more milliseconds. We set it back to zero so that it can count again. And we call get enemy to activate one object member, set it to a variable, and I call start method on that inactive enemy object to activate it. It will reset the object properties to default and it will mark it as active. There is a chance we don't have any inactive enemies in the pool when this code runs which would break our code. I only want to trigger start method if get enemy method was actually able to find an available inactive enemy object. I delete this consolo, I will call handle enemies from inside render method. Which means it will be called over and over for every animation frame I will consolo enemy. Here I see that it is correctly activating one enemy. Every 1 second I delete the consolo. Each enemy object has update and draw methods. These methods only run when that object is active, when its free property is set to false. I can now run for each method on the enemy pool and for each enemy object, both active and inactive ones. We call their update and draw methods. I put with and height up here. I want the initial vertical position to be minus height like this. This is how you implement a simple object pool design pattern with Java script. We are activating new enemy object every 1,000 milliseconds. We are returning them back to the object pool when they move off screen. Reusing our objects like this, rather than constantly creating new ones and deleting old ones, will improve performance of our code base. Especially in projects where we have large quantities of objects, I can make them float into view very fast and then start moving at their regular speed like this. As soon as the entire object is fully visible, it will slow down. This small detail will look even better when we add graphics and animated spreadsheets. We want this project to be fully responsive. When users play on mobile devices, they will not be able to change the screen size, but we could have some situation on computer screens or devices where we are swapping between landscape and portrait mode. Or when we are switching to full screen, mid game. Where the game area changes in size. To account for these unlikely but possible scenarios, I will make sure that all the active enemies are always inside the visible game area. If the right edge of the enemy rectangle is past the right edge of game area, move it. Now if the game area changes size mid game, it will just push the enemies into the visible game area, making sure we don't have any active enemies floating off screen where we can't hit them. 55. Mouse Controls: We will hit enemies by mouse and by touch events. We will create a customer mouse object and we will give it X, Y and pressed properties. This will help us to make the mouse position available all over the code base, not just inside the event listeners. Same as we did with Re size. I will automatically apply mouse down event listener here inside the game class constructor. I need to use ES six arrow function here to make sure this keyword points to the game object from inside its call back inside. I could call prevent default in case the event is doing something we don't like. It might be more relevant Later with touch events we will test it and see for now I don't think I need it here. From here I set X and Y position of the mouse down event to X and Y properties of our custom mouse object, making them available in an easier way. All over the code base I will consulg the autogenerated event object. And we are accessing these X and Y properties here. If your canvas is not covering the full browser window, we would have to use offset x and offset y from here. Instead, I will consulg these values just to check if everything is working, I click around and I'm getting x and y of the click. Nice. 56. Collision Detection: I will create a reusable check collision method. We will use it to check collisions between enemy and mouse, but it can be used for other features later as well. Custom check collision method will take rectangle one and rectangle two as arguments. It will use the usual four lines of code to check if two rectangular objects collide. Both objects passed to this method. Both rectangles need to have x and y position, and width, and height properties. For this to work, I will directly evaluate the expression and I will just simply return true or false whenever this method is called. The usual common formula for collision detection between two axis aligned, meaning non rotated rectangles. Check if the left side of rectangle one is to the left of the right side of rectangle two. At the same time, we check if the right side of rectangle one is to the right of the left side of rectangle two. If both of these checks are true, we already know that the rectangles collide horizontally, but they can still be far apart vertically. We need two more checks at the same time. We need to check if the top edge of rectangle one is above the bottom edge of rectangle two. At the same time, we also need to check if the bottom edge of rectangle one is below the top edge of rectangle two. Only if all four of these checks are true, we have a collision. Even if one of these four checks is false, we know the rectangles are far apart and they cannot collide. This entire expression will return false. Now we need to make sure that whatever object we pass to check collision as rectangle one or rectangle two needs to have x, y, width, and height properties. Otherwise the collision check wouldn't work. We will check four collisions. Here we are inside update method on enemy class. If check collision method which is defined between this enemy object and mouse object returns true, we call reset on the enemy returning it back to the object pool. I get an error. I need to make sure mouse object has with and height properties. It will be just a very small rectangle, one times one pixel. The problem is that when I click somewhere and move the mouse away, that mousedown event placed my custom mouse object there and it is still colliding with enemies. When mousedown event fires, we set mouse pressed the true, I create another event listener for mouse up event there. I will also update X and y coordinates to that last known location. And I will set mouse pressed to false. Now I can add one more condition. If this enemy and mouse objects collide, and only if mouse is pressed at the same time, only then reset the enemy. Now I can click the enemies and they will correctly reset and return to the object pool. I could do other things here. For example, when I click them, they slip down like this. We will use that for something later with our phasing dimension shifting alien. I go back to reset here. I can clean this code up. Since we are defining values of x and y inside the start method, we can just declare the properties here without any values. Because we know that the start method needs to run anyway before the object is drawn in the game. It's cleaner because now if I want to make any changes to these values, I just do it inside the start method. I don't have to check these values in two separate places. Enemies can also have multiple lives. I can just define it here, but I will only assign it value in side start method. That way when we reuse an old enemy object, its lives will be reset back to the original value. Each Neme will have two lives. We need to hit it two times. I will draw the lives here using the built in fill text method. We pass it three arguments, the text we want to draw, and x and y coordinates of the anchor point in relation to which we want to draw that text. I will put that anchor point exactly in the middle of the red enema rectangle. We need to set fill style of the text to a different color. For example, blue in Maine GS. Inside the resize method, which also runs on the first page load, we will set cannavas font property to 50 pixels bangers. We put the text anchor point exactly in the middle of enemies. There are two Navas properties that handle the relationship between the text and its anchor point. We can set text align to center to align it horizontally. We can set text base line to middle to align the text vertically exactly over the anchor point coordinates as we define them on line 49 in enemy GS file. Now instead of immediately resetting the enemy, when we click it, we will reduce its lives by one. The collision registers once per animation frame, so the lives decrease very fast. Before we fix that, we also say if the lives of the enemy are less than one, we reset that enemy returning it to the object pool. We will need this check later in multiple places to make the code easier to read. I will put it inside a separate helper. Method is alive, method will directly evaluate this expression and it will return true if the enemy is alive and falls if its lives are less than one. If enemy is not alive, reset the enemy. Now we need a flag that will indicate if the mouse click was already used to fire our weapon. Because we only want to fire once per click, I give mouse a new property called fired. Initially, it will be false. The shot hasn't been fired yet. We only decrease enemy lives by one if fired is false. And then we immediately set fire to true. To make sure this code block runs only once, then we need to reload our weapon and set fired back to false so that we can shoot again. I think we can set fired back to false on either mouse down or mouse up. Let's try. Yes, this works. Now we remove only one life per click. We need to click each enemy twice to deplete both its lives and reset it. I remove the fill style here. Instead, I set it to white here. I will also set stroke style to white as well. It's better for performance to put these declarations here inside the resize method that runs only once on the first load. Or when we resize, the screen draw method runs 60 times per second. Declaring fill style here is less efficient when it comes to performance. I delete this fill style, smaller font, we have a responsive world that resizes to accommodate for any screen size, vertical or horizontal. It will work on a massive, super wide computer screen. It will work on tablets. And it will work on mobile in landscape well as in portrait mode. Let's make it even more mobile device friendly by including touch events. 57. Touch Events: I could create a separate custom touch object, but I will actually use mouse object which will work perfectly here. It will automatically work for both mouse clicks and touch events. Touch start will basically do the same thing as mouse down. Touch end event will do the same thing as mouse up event. This will not work yet because for touch events, this autogenerated event object structures the information about the event in a different way. I consologate here in Google Chrome browser, I click Device toolbar to trigger responsive screen view, which will allow us to emulate touch events in the responsive view. I click on screen, and I know it worked because we are consologing touch event object. I'm looking for X and Y coordinates of the touchstart event. And I can see that the browser organizes the contact points with a touch surface inside this touch list property. I think we can treat it as an array. We will test that later. I can see that to access x and y coordinates of the touch event, I need to access the event changed touches element with an index of zero dot pagex and pagey. I also do the same for the touch end event. 58. Game Text: Now we have a responsive game world. And we can use touch events to shoot enemies. I will disable device toolbar in Google Chrome. Now we are viewing our game in a regular computer browser view. I can put the code to display score and other game text directly inside render, but I want to keep this clean. Again, I will put it into a separate method, make our code base easier to navigate in. Inside the draw status text method, I will call built in fill text method and I pass it the text I want to draw and X and Y coordinates of the anchor point in relation to which I want to draw that text. I call it from inside render, I can see that the score is not fully visible. I want the text that displays enemy lives to stay centered, but I want the score text to be left aligned. I wrap it between built in safe and restore methods that will restrict any changes I make to canvas state to this area. All the drawing code outside this block will remain unaffected. That way I can have text line left for score and text line set the center for enemy lives score. Text will now flow to the right from this x and y anchor. Let's actually count the score. I define it here, start method inside, we set score to zero because this will also be used as a restart method. Now I add this variable here, smaller font. When we deplete enemy lives by shooting it, we reset the enemy. Returning it back to the object pool. We increase game score by one. I need to spell score correctly if we have multiple enemy types. We could also here at score that is relative to enemy lives for example. Or each enemy type can have its own score property that will define how much score it awards. Now when we click enemies, we get scorepoints. I also want to give the game lives. These are the player lives. If we lose them, we get a game over. Don't confuse it with lives on each enemy. These indicate how many times we have to hit each enemy. These are player lives. When we start or restart the game, we set player lives to, for example, ten. Inside the draw status text, I will create a four loop that will run once per each life. I will draw a simple rectangle representing each life. At first it needs x, y, width, and height. Now I'm drawing all of them on top of each other, okay? This is x, y, width, and height. This value will be the margin from the left. I multiply horizontal x position by the index from the four loop, which will align them in a row next to each other. If the width of each life rectangle is more or equal the space in value, it will look like a continuous health bar, which might be something you want. If the space in is more than the width we get to see individual lives. I will go for this view because later I want to change each life into a different humanoid alien species. It will add more stakes to our space horror game because we don't want the enemies to eat our unique crew members. If this is not clear, just play with the values. Watch what happens. It's pretty straightforward if enemy manages to travel all the way across the screen, all the way down and we don't interrupt it, we don't shoot it. It managed to catch up with our escaping fleet and it will eat one of our crew members. Reset the enemy and we reduce game lives by one. If we change the number of lives, the rectangles representing each life will appear. This works well. Let's close the game loop. Winning score will be three. We will display three messages on screen. When the game is over, we will have three sets of these messages. One message will get displayed only on the first load. Before we press the button to start the game, I remove this value from Game Over. When we start the game, we set game over to false. I will create a separate trigger game over method to make sure this code block runs only once. At this point, I could put this logic inside the render, but if I put it into a separate method, it will make it easier to play a special horror sound later when we win and when we lose the game. It will run only once when called. And we make sure of that by only running its code when game over is false inside, we immediately set game over to true. We triggered game over, which could mean we lost the game. Player lives are less than one or we won the game when the score is more or equal to winning score. When we lose, we set some unique text to message one and message two. If we win we give those same variables different texts then we need to call that method. I can do it from render or from draw status text here, if this lives is less than one or if this score is more or equal to winning score, we call trigger game over which will set game over to true and it will set the messages up. Then if game over is true, we want to draw message 12.3 in the middle of the screen. Text align center, large font may be 80 pixels bangers, we call fill text message one, x and y coordinates will be the middle of the game area. Message two and message three. We do the same. I adjust their vertical coordinates to try and align them. -25 message one, plus 25 for message two, and plus 50 for message three. I play. I wait until we lose. Okay, that worked. I want messages 2.3 to be drawn in a smaller font. I try 20 pixels, that's the losing message. I refresh the page, I play again, and I win win message. We have one more message, we will make a display in a minute. I said game over to true. 59. Start Restart: I created this reset button here, I want it to trigger start method when clicked. First I create a property on the main game object and I pointed towards that button element using its ID. Then I add event listener on that button. We listen for a click event. Again, I have to use an arrow function here to make sure we have access to this dot from inside the event listener to make sure that this keyword points towards the game object. From there I call this Do Start. Now I can see the start messages, but they are not formatted. Well, I fix that by calling this, resize automatically from inside the game class constructor. Doing this fixes fill style and text baseline settings, but now score is undefined. I will initially set it to zero here inside handle enemies method, we periodically activate new enemy object and add them to the game. I only want new enemies to keep coming if game over is false. Now when I refresh the page, we just see the starting set of messages and nothing is happening until we click on button R here to start of the game. Having a button that starts the game by user interaction will also solve issues with game sounds. We will talk about that later. But basically in modern browsers, sounds will play only after the user interacted with the document. User click in this button will count as an interaction which will allow the sounds in our game to be played. I create another event listener. This time for a key up event, I caso log the event object. We are looking for this key property. I say if key, the key that was pressed on the keyboard is Enter, or if the key is R, I use to lower case method here to account for both lower and upper case being pressed. We run a start method to start the game. R needs to be in quotes here. Right now, start method will basically just reset the score back to zero and it will replenish our lives. I also want to reset all active enemies. I run over all objects inside enemy pool array and I call reset on them. Maybe I want to activate two enemies quickly. Immediately as the game starts. I could do a four loop like this. I tried to get enemy if there was an available free enemy object, we found we activated by calling enemy start method. Don't get confused here. Start method that sits on the game object starts and restarts. The game start method we defined inside enemy GS on the enemy object activates enemy object pool member two different methods. Now we can start or restart the game at any time by clicking or tapping on this R button or by pressing Enter or letter R on the keyboard. This is just to show you how you can give your players different options. We can also create a faster initial wave by immediately activating a few enemies in the beginning here. Then the rest will be coming in 1 second intervals. 60. Fullscreen Games: Modern web development has a lot of cool features. Have you tried to use built in full screen functionality before? Basically, it just removes the browser buttons and navigation bar, and it will expand your application to take up the full screen. This will work on computer monitors, on tablets, as well as on mobile screens. We will use it to make a proper full screen game. Now, it's very simple to implement it. Let me show you, are you interested in full screen games? Let me know by leaving a comment. And if people like it, I can use this feature more often for other projects. You can go to this web address to read the documentation if you want more details. All we need to make this work is this simple if L statement that basically says, if full screen is currently not active activated. If it is currently active, deactivated. All these properties are built in into every modern browser. So you can simply just copy this small code block I pasted here on the main game class togal full screen method. Whenever this method is called from anywhere in our code base, it will check is full screen active, If not activated. If it is active, deactivated, we test if it works here, else if the key that was pressed is space bar or if the key that was pressed is letter. Feel free to use different control keys here if you know what you're doing. Now I press letter or Spacebar and my game toggles between full screen and regular browser view. I'm not really showing it off well here because I'm not recording the edges of my screen. But if you are coding alone, you can do it yourself with your code base and see that this is a very nice, proper full screen functionality. We also want to be able to toggle full screen on mobile devices where there is no keyboard that we have, this full screen button I created earlier. You can also enable and disable full screen by gestures, for example, by swiping up and down. If the swipe is longer than a set number of pixels, when it is in a specific direction, we can trigger our custom code, which could be, for example, enabling and disabling full screen. I did that in a different tutorial for this simple mobile friendly endless runner and jumper game. It was some time ago on my Youtube. Same as we did with the reset button. I reference full screen button in my code. I attach event listeners to it. In the call back, I call togal full screen method game is fully playable in the full screen mode. What you see now is not completely right because I'm not recording my entire screen. The planet and the text is a bit of center and the buttons are not here. But if you are coding along, you can see in your project that everything is working well. We have a blank slate of a game with a full set of features, complete game, loop, win and lose state, mouse keyboard and touch controls, reset, and full screen functionality. This game will work on large horizontal computer monitors, as well as on small vertical mobile screens. You can adjust winning score on line 16 or lives on line 77 to tweak the win and lose conditions in the video description. I'm giving you a full source code from the project. At this stage, you can compare it with your own code if you encounter some problems. You can take this code and use it to create many different games, get creative with the themes and graphics, and make it your own. In the next part, I will turn this into cartoon space horror game with sounds and randomized crew that we have to protect from phasing flesh eating aliens. This concludes the beginner friendly part of the course. In the next part, I will show you an improved implementation of state design pattern and I will go a bit faster. Well done. If you go this far, let me know by leaving a comment saying, I finished the beginner project. 61. Simple Crew Members: We have a game that works on small and large screens, portrait and landscape, vertical and horizontal. Now it's time for fun. We add some graphics and animations. I set lives to 15. I create a diff with an idea of assets inside. I will put our project images and sounds. You can download everything I'm using here. In the resources section below crew PNG image and the ID will be Crew I give assets, display none. We want to hide everything in there. We just want to load those images in memory so that we can draw them with Javascript on Canvas. I want to draw lives as little crew members. Let's start simple. I bring crew image into my project using get element by ID here. Inside the draw statistics method, we draw rectangles to represent player lives. Instead, I will use built in draw image method. We pass it the image we want to draw and X and Y coordinates. Where to draw it, I adjust with and hide here to match the image we are using. This is the left margin, this is the space in between the little crew members. I can make them have space around or I make them stuck up closer on top of each other. When we lose all crew members when they were eaten by the aliens, we lost the game. 62. Simple Enemy Type: I want to create different enemy types. This is the main enemy class. It contains all methods and properties that will be shared between all enemy types. I will first do a simple enemy with the most basic implementation, but my ultimate goal is to show you how to use a complex enemy with multiple states. And how to structure your code where each state is in its own dedicated code block using so called state design pattern. Basic simple enemy with one life, no special features, no special abilities and interaction. I call it Beetle Moorph. I will go back to my Space Invaders game from a different tutorial and I will get the spreadsheet we used there in this project. The enemies are a bit bigger. If you are watching the extended version, I'm giving you all larger exports of all enemy types we used in this entire space game series. If you want, you can play with this later and implement whichever one you want. For now, I will just grab the Beetle Moorph spreadsheet in the resources section and I'll put it into my project folder. Beetle Moorph subclass extends the enemy superclass constructor will expect the game as an argument. And I will pass it along to superclass constructor when we call it here I'm calling class constructor on the parent enemy class we are extending. That class is defined here that will make all this code here run first. These are all the shared properties. The properties that are the same for all enemy types on the beetle morph subclass. I will only define properties specific to this particular enemy type. It will have a unique image I imported here. Download Link in the resources section below, I point Javascript towards the image using get element by ID. It will also need its own start method. First, we will call the start method on the parent enemy class. On the superclass like this, when we call start method on Beetlemorph enemy, it will first run all the code inside this parent start method. Here from line 13, I copy speed x and speed Y. When we call start on betlemorph, I will give them values. I want this enemy type to move directly down speed x zero and some positive speed Y. I remove these values on lines 8.9 They will be set to something different for each enemy type inside their associated start methods. I also remove lives from the shared start method, because each enemy type will have a different number of lives. In the extended version, I'm also going back to Space Invaders and Planet Defense projects, which are all part of the same big course, including this game and others. I'm adding bonus lessons implementing the new phase in enemy type that can only be hit when it is in the same dimension as the player. We are extending a class shared properties sit on the enemy superclass. Properties unique to each enemy type will sit on the subclass. First we trigger constructor and start method on the superclass on the parent class. Then we add some properties and values specific to this particular enemy type inside update method. Here we check for collision between enemy and mouse. I will cut this and I will put it into a separate method. It's mainly because we will have a phase in enemy type that cannot always be hit. I need to be able to better control when we check for collision. Now it's in a separate hit method. All this code inside update will be shared and executed for all different enemy types in our game. Beetle Moorph will have its own update method that will override it. If this enemy object is currently active, we call all the code inside the update method from line 31. Then if this enemy is alive, we call hit method checking collision between this enemy and mouse. Now I need to call that subclass. Here we push New Beetle morph into the enemy pool. Right, I forgot here I have to call update method on the parent enemy class. That works. 63. Sprite Animation: Now we want to draw the spread sheet. I can put this code inside the draw method on the shared parent enemy class. Because all the enemy types will have a spreadsheet I call built in draw image method. And I pass it the image I want to draw and x and y coordinates, Where to draw it. This will just draw the entire spread sheet with all its frames at its original size. We can give it optional width and height here, which will squeeze or stretch the spread sheet into the area we defined. We need the longest version of draw image method with nine arguments. It will give us complete control over this spreadsheet. We pass it the image, we want to draw source x, source y, source width, and source height of the area. We want to crop out from the source image and destination X, destination Y, destination width, and destination height to define where on destination canvas we want to place that cropped out piece of image onto the sprite sheets we are using have individual frames size on 100 times 100 pixels. I define those properties here I set within height relative to that. These two values are for crop in. These two values determine the size at which we will draw the image on Destination Canvas. These two sets of values don't need to be the same. We can scale this and we will do it later. What if I want to crop out the top left frame from 00 to sprite with sprite height. Nice, We are using draw image method to crop out this frame from the sprite sheet Frame Y property will help us to travel around the spread sheet vertically. The way I organized this spreadsheet, you can see it will give us different variations of the same enemy type. All enemies will have four sprite rows, four variations. So I can randomize frame Y here inside the shared start method. If each enemy had a different spread sheet, we would have to put this on each separate enemy subclass method random times four wrapped in method floor means that every time start method runs and we pull an enemy from the pool, it will randomly be assigned frame y zero or one or two, or three. Source Y argument passed to draw image method will determine the vertical crop in coordinate. So we pass it frame y times sprite height. Frame y can be 01230 times sprite height, is this one times sprite height is this two times sprite height, three times sprite height. This is one simple way how to randomize your sprite sheets a little bit and give us some variations of the same enemy type. They all have the same features and color pallet, but they have different details makes it more interesting. I think we will also need frame X to navigate around the sprite sheet horizontally. I will also have last frame property to define how many horizontal frames we have per row when the start method on enemy runs To activate it, we set frame X to zero. Each enemy might have a different Last frame Beetle morph has a very simple sprite sheet, only three frames per row. Inside the shared update method, we will handle horizontal sprite navigation when the enemy loses all lives. When this dot is alive is false, we keep increasing frame X by one. When frame X is more than last frame, we know that all the explosion animation frames have been displayed. And we know it's safe to reset the enemy and return it back to the object pool. If game over is false, we increase score by one, and I can delete this. Finally, as the source x argument passed the draw image method which determines the horizontal coordinate of the cropping area, we pass it frame x times sprite width. When frame x is 00 times bright width, we draw this frame one times sprite width, two times bright width. I hope it makes sense. I play, I click each animate twice, deplete its lives, and the animation plays that worked. 64. Animation Timing: It is playing very fast. I want to be able to control how fast we jump from frame to frame. When animating our sprite sheets, we will do another periodic event, same as we did before when we activate new enemy every 1,000 milliseconds. We will update all sprite sheets in our game. Every, let's say 200 milliseconds. Sprite update will be false. Every time sprite counts to 200, it will set sprite update to true. I can put that logic directly into my render method, but to keep our code cleaner, I will separate it out to its own code block. I will call it, for example, handle sprite timer. It will expect delta time as an argument. If sprite timer is less than sprite interval, we keep accumulating delta time. Else once we accumulated enough, we reset timer back to zero so that it can count again. And we will set sprite update to true, allowing our sprite sheets to jump from frame to frame. It will be true only for that single animation frame. All other times it will be set back to face. Now we call handle sprite timer here, this delta time value will get passed along. That should be all good here. Inside the update method on enemy class only if the enemy is not alive and if sprite update is true only then jump from frame to frame in the sprite sheet. I will adjust this code block. We have to be very careful about the brackets here. It's easy to break our code with a single missing bracket. It doesn't work because I have to use sprite update here. Actually, one more mistake I made somewhere. I see I misspelled sprite interval here on line 24. I can slow it down or I can speed it up by giving different values to sprite interval here, 1,000 milliseconds will make them animate Very slow. 50 milliseconds is very fast. 150 milliseconds seems like a good value here. For now. Now it all works well. We get one behavior I don't like here. If two enemies overlap and we click them, it destroys the enemy in the back. Why is this and how do we make it destroy the enemy at the front? We are cycling over the enemy pool and calling update and draw. We are drawing all enemies on the same canvas element in a single animation frame. As we run this for each method we draw enemies one by one enemy. We draw first will appear behind the enemy that was drawn after. At the same time, the collision checks inside update method will run first for the enemy that was drawn first and that enemy gets destroyed. One way to fix this would be to run over enemy pool from one direction to call update and then from the opposite direction to call draw. That way the enemies that are drawn last, meaning on top, will get checked for collision first With this code structure. When two enemies overlap and I click them, the one on top, the front gets destroyed. That's better since we separated the crop in size and the drawing size. We can actually do some scaling here. I can multiply width and height by the same size modifier value. I can make the sprites larger or smaller. How about a random size modifier between 0.4 and 1.2 Makes the game a little bit more interesting, maybe. How about random value between 0.6 and 1.3 65. Debug Mode: I want to be able to show and hide some helper elements in the game such as these white collision boxes and numbers displaying enemy lives. Let's create a debug mode on the main game class. I created this bug property and initially I set it to true inside key. If the key that was pressed to lower case is letter D, we will set back to its opposite value. If it's true, we set it to false. If it's false, we set it to true. Inside draw method on enemy class, we only draw the white rectangle around enemies and enemy lives. If the bag is true, I make sure I save changes to all my files and now I can press D on my keyboard to toggle debug mode. On and off I give Beetle Morph only one life. Because when we don't display enemy lives, that first click doesn't have any visual feedback and we don't know if we hit the enemy. I adjust size modifier range here on line six, I said winning score 220. Initially, back will be set to false. If you are happy with having just simple enemies like this, you can implement them the way we just did. I created a series of games and projects with this art style, and all the art assets are compatible and can be used between the projects. If you want, I will now grab one of the more complex enemies we implemented before and I will try to implement it in the same way we just did. Then we will add a third enemy type using state design pattern. Which has a little bit more complexity but gives us much more freedom while keeping our code clean, modular, and organized. In the other projects, we have for example, an armored enemy, inflatable enemy, vengeful enemy that shoots back at us. We have an oversized bost enemy type with a massive health pool. We have a charging enemy that will speed up and hit us. I will grab, for example, this one, an enemy that splits into clones when we hit it. Because I have an interesting idea on how to use it in this particular project with this type of gameplay. 66. Enemy Variety: In this class, we are using slightly larger sprite sheets with frames 100 times 100 pixels. You can use the sprites you already have if you followed the other classes, they have frames 80 times 80 pixels. In the extended version of this project, I will also include exports of all enemy types in 100 times 100 frame size to better match this project. If you want to play with this code base later and include the other enemy types as well, you can use those bigger sprite sheets. I included my image in index HTML and I referenced it here. Last frame will be 14. Again, start method will first trigger start on the parent enemy class. Horizontal speed x zero. Speed y will be a random value between 0.2 and 0.7 This enemy will have three lives, so I need to make sure it's a bit slower to give the player enough time to deal with it. My plan is this enemy has three lives. We hit it once. The frames will play until here, we hit it again. The frames will play until this point we hit the third time and the rest of the spreadsheet will play. This would be best implemented using state design pattern, when each of these states has its own code block. But I will try to implement it somehow in a simple way like we did with the beetle morph. Then we can compare it with the last enemy, where I actually show you how to use state design pattern. You can compare the relative complexity between these two approaches and you will see the advantages of the final approach. Update method will first run all the code inside the update method on the parent superclass. Then, if this enemy object is currently active, if the enemy is alive, we will make it react to being hit by the mouse. We will have a horizontal frame range defined by min frame and max frame helper variables. If frame X is less than max frame, if sprite update is true, we increase frame X by one. Okay, what I'm doing here, frame Y handles vertical sprite navigation. Frame X handles the horizontal sprite navigation. Last frame is the last horizontal frame. Once it was displayed, we know the enemy can be deactivated. Mint frame and Max frame will define some animation range we are currently working with. Depending on which state the enemy is currently in. There are many ways I can implement this. I want to do it in the simplest way possible. We are going to do if else if enemy lives are more or equal to three. Max frame is zero, if enemy lives are two. Max frame is three When we hit the enemy once, because of this line of code, it will animate from here and it will stop here. Else if enemy lives are one, we will let animation go all the way to max frame seven. I think that might be enough because we have some other animation code inside the shared update method that when enemy is not alive and has less than one lives, it will animate the rest of the spreadsheet, the explosion frames automatically. Let's see here where I create the enemy pool. I want to randomly create beetle morph or lobster morph enemy types. I can, for example, roll a random number 0-1 The random number is less than 0.8 In roughly 80% of the cases we create a lobster morph. In the other 20% of cases we create a beetle morph. Okay, both enemy types are coming. I click the enemy once, twice, three times. That all worked perfect. I adjust sprite interval to make the animation a little bit faster. This code block is working well, but when you write your code, always think about which code is running once and which code runs over and over. This code is running all the time and I'm setting max frame to the same value 60 times per second, over and over. So what if I want to play a particular sound when the enemy morphs into the next stage. I don't really have a good place to put that code here, since this code block is running over and over. So that sound would be played over and over if I call it here. Ideally, I need some code block that runs only once to play that sound for me. We will solve all these issues in a minute. First, let's use spreadsheets for crew members. 67. Randomized Space Crew: Right now, all our crew members look the same. Let's give them a little bit more personality. An intergalactic crew of different kinds of humanoid and robotic crew members. All the art assets are available to download in the resources section. Down below, I bring crew sprite into the project, give it some ID, and I point crew image to this new spreadsheet. How do we do this? I will actually have to hold the randomized coordinates to these frames out somewhere. Maybe here inside crew members property, I set it equal to an empty array. I create a helper method. I call generate crew inside. I set crew members to an empty array, deleting everything in there in case it's not empty. When we call this method, then I run for loop. Each player life will have a random crew member image assigned. Each crew member will be a simple object with frame X and frame Y property. Frame X will be a random number 0-5 and we use method floor to round it down to the nearest lower integer. It will be zero or one or two, or three, or 44 frame Y. Each time we push new crew member, it will get some random coordinates somewhere on the spreadsheet. We will call this method every time we start or restart the game. After we set value of dist lives. That's important here in row status text, I define with and height of a single frame in crew members spreadsheet. I need to add four more arguments to define the cropping area. For example, I can crop out the top left frame from the Corint 00 to width and height. I will also use with and hide here in destination width and destination de arguments to define the size at which they will be drawn on canvas. We always have to start our game to see the lives by pressing Enter letter R on the keyboard or by clicking or tapping on this R button. Nice, Now let's use frame coordinate from crew members array. We created that property here on line 100 As we cycle in this four loop 15 times, because we have a total of 15 lives, we use the index from that four loop, access the corresponding element inside crew members array. And we access those frame x and frame y coordinates. We multiply them by width and by the height of a single frame to correctly travel around the spreadsheet. Now every time I start or restart a game, we generate a set of humanoid and robotic alien species. I hope it puts a little bit more pressure on the player to try and make sure none of our unique crew members get eaten by the aliens. This value here defines the left margin. This value here is the spacing between the images. We have a simple enemy type and more complex enemy type implemented in the simplest way I could think of. We have a randomized set of crew members and we need to protect them from eating aliens. If you are watching the extended version, there is a source code available to do from this stage of the project. If you struggle with something, feel free to use it and compare your code with mine. If the spacing here is a little bit less than the width of a single frame, we will get them stuck up behind each other. You can play with these values and use whatever looks good for you. 68. State Management in Games: Now it's time to learn how to use state design pattern to implement a phasing enemy type that can only be hit when it's in the same dimension as the player, when it's in a solid state. If you hit the enemy when it's phasing when it's in the invisible state, it will boost it and speed it up, making it even more dangerous. We will also attach sounds to different phases and actions. Because it's important that our games give player feedback when you click or interact with something. We will give visual feedback by animating the enemies. We will also get audio feedback by playing a specific sound. Small buck to fix. I only want to reduce player lives when game over is false. Like this, I bring a phantom morph spreadsheet into the project and I give it an ID. Here we have the shared enema class with all shared methods and properties. We are extending it into a simple beetle morph eneme and a more complex lobster morph enema type. Now we will extend it into the most complex phantom morph enema type. I was having a lot of fun with this and if you are watching the extended class, I went back to Space Invaders and Planet Defense projects and I added a bonus lesson to each one. As well as the full source code where I implement this Phantom Morph phasing enemy type into both of these projects. You can also just take the spreadsheet I'm giving you here and try to implement it yourself if you follow those classes. But if you need my help, those lessons are there for you. Phantom Morph will have last frame 14, some speed x and speed Y. We will change these in a minute. It will only have one life, but it will not be that easy. Because you can only hit it when it's not phasing when it's solid. If you hit it at the wrong time, you can accidentally give it a boost and cause one of our crew members to be eaten. And it's probably not going to be pretty because if you listen to the sounds that will play. When that happens, I go to the main GS file here inside create enemy pool and I will only create phantom morphs. I have to be careful about the brackets. I save changes to all my files and here we go. I'll copy update method from beetle morph code block and I use it here. Now when I hit it once, it will just play the rest of the spread sheet. As expected, vertical speed will be a random value between 0.2 and 0.7 I also want to make them move left and right. Horizontal speed will be a random value between minus one and plus one. We want to make sure they can't move off screen, so I will make them bounce left and right if the horizontal x coordinate of the enemy is less or equal to zero. Or if the right edge of the enemy rectangle is touching the right edge of the visible game area. In both of these cases, just flip horizontal speed to its opposite value. Making the enemy bounce, move in the other, in the opposite direction. Perfect that worked. The other enemy types were static, always showing a single animation frame. Unless they were animating into another state. This enemy type will be different. I want it to always animate in a certain frame range. Initially in frame minimum frame will be zero and maximum frame will be two. I give this enemy type its own special method that will handle animation frames. For me, if spray update is true, we move horizontal frame. If frame X is less than max frame, we keep increasing frame X, we reach max frame, we set it back to min frame so the cycle can continue. I will call handle frames from inside update here. Nice. This will be the frame range for the basic flying state. I try three to five probably. That will be the phasing state animation range. Okay, if you are a beginner, now comes the complicated part. We are going to implement state design pattern that will allow us to define properties and behaviors of this enemy for each state separately in its own code block. 69. State Design Pattern: I create a completely separate class called enemy State constructor will expect game and enemy as arguments. We will need these to be able to point towards and access our main game object and also the particular enemy object that will be in these different states. Then we will define each state in its own subclass. All these three subclasses will extend the main enemy state class. Here we will store the shared properties inside each of these code blocks. We will define properties, values, and behaviors we want the enemy to have. Only while it is in these particular states. It gives us a lot of freedom and flexibility. And it makes our code easier to debug. Because if we get an error and we know which state the object was in, we know where in the code to look to fix it. The only challenge for beginners will be to keep track of how all these objects connect and communicate with each other. If you are a beginner, the next part will be challenging, so don't worry about it too much. This is one of those techniques you have to use a few times to create a mental map. It helps if you use this for a few different projects. It becomes easier to navigate eventually as you get used to it. All you need to understand now is that we have a separate enemy state class. We are extending it into three state subclasses, flying, phasing, and imploding. Each of these classes will have its own start method, where we define, for example, frame range for the animation while the enemy is in that state. We can also play a specific sound from here. When the enemy enters that state, each state will also have its own update method that will first call the shared update method on the main enemy class. Then it will add a little bit of unique logic that will only apply when enemy is in that particular state. For example, maybe we only want to check collision detection when enemy is flying. When the enemy is phasing, it cannot be hit, so we will not run check collision method from there. Things like that. Each enemy object will have an array of all possible states it can be in inside. We instantiate all three state subclasses like this. Here on line 174, I can see enemy state constructor expects game and enemy S arguments. I pass it this game reference. Along through this reference, we will be able to see player lives score or game over state, all the things we might need that sit on the main game object. Then I will pass it this keyword representing this particular enemy object. This keyword used here in this court block means the enemy. Through this second reference, we will be able to access all the methods and properties that sit on the enemy object, on the enemy class. This is probably where it's getting a bit more complicated for the beginners, just keep going. I'll try to guide you now. Phantom Morph will have a current state property that will be pointing towards different states we have here inside this states array. Through this connection, we will be able to set enemy to a different state. Custom set state method will expect state as an argument. This state will be a number representing index. In this states array from 93090 will be flying state because this is an array and arrays start from the index of 01 will be the phasing state and two will be imploding state. When we call set state, we take this dot current state property from 940 and we pointed towards one of the objects inside this dot states array zero, or one or two. At that point, this dot current state holds an entire instance of let's say flying class. We gave that class its own start method. I said and state to flying class and I call its associated start. We define that method here on line 186. And the job of this method is to set properties on the Phantom morph eneme to whatever values they need to be. When Phantommorph enemy type enters this state, we need to make sure each state subclass has its own start method. We have multiple layers here. Now when we call start on the Phantom morph enemy type to activate it from the object pool, we first run the code that is shared for all enemy types. Then we run the code that is specific only for phantommorph enemy type. Then we call set state method. We set the current state to an instance of flying state subclass. From there we call start method on the flying state which will set properties to that particular phantom morph state. It will be the same inside the update method when we call update on Phantom Moorph enemy class. First we call all the code inside the update method on the shared parent enemy class. Then we add some code specific only to phantom morph enemy type. On top of that we trigger that last bit of code specific only to the current state phantomorph enemy is currently in. Depending on which code block current state is pointing towards at the moment. It could be this code block from 191 or this code block from line 200, or this one from line 209. Now we have all the layers and you can place your logic wherever you need it. Do you have an idea for a behavior that is specific only to one of these states? We created a space for you to put that code in. I will show you some examples of how this is done. This is the entire state design logic loop. I'm not sure if I explained it well enough. If you still don't fully understand it, let me just expand each code block and see what happens. Hopefully, while we work with this, it will become more clear. This code structure, we have a complete and detailed control over our objects. We can do so many different things. Basically, we can do anything we want with our space creatures. Now we can access properties on the enemy through this enemy reference. When we enter flying state, we set min frame to zero and max frame. This means I can remove those values from here because they will be triggered when this line runs anyway. When we enter facing state, we will set min frame to three and max frame to five when we enter imploding state in frame will be six and max frame will be equal to last frame plus one. Maybe when we activate the enemy it is set to state zero flying state. This start method sets the frame range as we just defined. We can also make them start from the phasing state. I can see they start from frame X zero. I actually want them to start from whatever the min frame is in that range. I can say sdtenemetframex is equal to didot enemy in frame I do the same thing here and here. Now they are immediately invisible. They start from the correct frame range. When they enter a particular state, I want them to be randomly, starting from either flying or from phasing state. I want zero or one here. Math at random times two wrapped in Mathot floor will do that for us. Now we get some enemies start invisible, some start invisible. I want the enemies to automatically switch between flying state and phasing state. We already used periodic events to activate enemy every 1 second, and also to allow sprite sheets to update every 120 milliseconds. We can use the same technique for this. Each eneme will have its own switch, timer, and switch interval. I put them on each eneme object. Each eneme having their own timers will allow us to, for example, give each enemy different interval. If I wanted all enemies to switch states at the same time for performance reasons, it would make sense to put this logic on the main game class. For now, I want each eneme to switch state every 2 seconds, every 2000 milliseconds. We will randomize this value in a minute. When we get this work in, I can put that logic here. The enemy is alive. We will make it periodically switch between flying and phasing state. If switch timer is less than switch interval, keep increasing switch timer by delta time, else, meaning if switch timer accumulated enough milliseconds, set switch timer back to zero so that it can count again towards the next periodic event. And call custom switch method, which we will define. Now switch method will simply check if this dot current state from 940 is equal to this dot states index zero which is the flying state as we defined it here on line 139, we call set state and we pass it index one phasing which will reassign the current state to phasing. It will call start to adjust the frame range and so on. Index one is here. I could have created an Enum object translating 01.2 indexes into something more readable, but I think since we only have three states, we can work with numbers. We just have to remember, index zero is flying, index one is phasing, index two is imploding else, meaning the current state is phasing. We set state two to activate the imploding state. Just to see what happens, we are using delta time. Here we are calculating it on line 215 inside main GS. We are passing it to the render method, then we are passing it along to update method on enemy objects that goes here inside enemy GS. It is available to the main update method on the enemy class, but we don't really need it here. We can just go directly to the Phantom Morph class and just access delta time here. Then it will be available to our state switching logic. We are switching state between flying and imploding, which results in this. We actually want to switch between flying and phasing. That's better. I can randomize this interval to make it more unpredictable. I want the enemy to be destroyed when we click it. Only in a flying state. If we hit it when it's phasing, we will give it a speed boost. This will encourage the player to time the clicks properly. Here on the Phantommorph subclass, if the enemy is alive, we call this method that sits on the main enemy class. I will actually intercept this. I will give it its own hit method that will first run all the code inside the hit method on the parent enemy class, here on line 34, to check collision between mouse and the enemy object. When we hit the enemy by clicking it with the mouse or tapping on it with our touch events, we will check if the enemy is not alive. We will switch it to the imploding state set state two. I'll cut this code block. We want to call hit method only from while we are inside the phasing state or inside the flying state. I will remove hit method from phasing state. Maybe the enemy cannot be hit when it's phasing, When it's invisible, it can only be hit when it's flying. I can see that we are displaying explosion animation frames too fast. I will remove this handle frames method that cycles between min frame and max frame. I will only call it while we are in flying state or in phasing state when the enemy is imploding. We don't need to handle frames anymore because this code block on the shared parent enemy class will take over. And when the enemy is not alive, lives are less than zero. We keep increasing frame X until we reach last frame and then we reset the enemy. Okay, get we clean that up. I can do all kinds of things here. Maybe when we click the enemy, I copy this code block, I put it here inside the phasing state. If we click the enemy while in phasing state, give it a speed boost. We push it vertically by 25 pixels. Maybe I can remove this mouse fired check for this. We are inside state subclass I have to say this anime here. If we click an enemy while it's phasing, we make it jump forward instead of destroying it. If we click when it's in a flying state, we switch it into imploding state. And when explosion animation frames finish playing, we get a score point. I could, for example, copy these two lines. Every time we enter flying state, I add enemy here and here. Every time we enter phasing state as well we randomize speed x and speed Y again to make sure the enemy changes direction. If we click the enemy while in phasing state, we make it move directly down speed X zero. And speed Y will be two pixels per animation frame. When we click the enemy, when we are not supposed to, we are giving it a speed boost making it more likely to eat one of our crew members. Okay, we have a shared enemy class. We are extending it into a Phantom morph subclass. This enemy type can be in flying, phasing or imploding state. We are switching between these states by pointing current state property to different state subclasses. Using this set state method, we are calling update on the current active state subclass from here. With this code structure, we have a separate code block for each state. And we can add any behaviors and properties to the enemy here. This allows us to control every detail and keeps our code clean and organized. We gave our enemy a flying state where we animate this frame range and enemy can be hit and destroyed. Phasing state where we animate this frame range. Enemy will get a boost if we hit it in this state and imploding state. Which will just animate the destruction of the enemy. The way I structured my code, we need to keep this update method here or our code would break if you don't want it here, because we are not using it for anything right now. You can also put it on the parent enemy state class, and Javascript inheritance will make sure the code will still work. Structuring our code in this way has so many advantages. I prepared a set of sound effects for this game. Let me show you how easy it is to implement it now. 70. Sounds: You can download my horror sound set in the resources section below. We will bring them into the project. Here inside the assets stiff, I create a HTML audio element and I pointed towards my new game P three file, and I give it an ID of new game. One more. Let's take boom one P three ID will be boom one. Up here in main GS, I create a class called Audio Control Constructor Will just have a property for each sound pointing to the audio element using its ID. I create an instance of this class, so the sounds will be available from disdotoundpperty sitting on the main game class. When we start the game, I can simply just take didotundegame and I call built in play method. Most modern browsers will not play audio automatically. When a web page loads in our project, user has to press Enter R or click this R button to start the game. That is considered a user action, and it will allow game audio to play. We have another sound called Boom One. Here I go to NeMGS down here inside the imploding state. When the enemy enters this state and start method runs, we can play it now, You'll notice a problem when I quickly destroy multiple enemies because we are accessing the same audio element. The sound will not start playing until the previous loop finished. I want the sound to play each time we destroy an enemy. We could create multiple instances of that sound, which would not be performance friendly. I think I can use Web audio API here, which gives us much better control over sound. Or the simplest solution here is to simply rewind the sound to the beginning every time it's supposed to play. It might sound strange, but it will actually create the effect we want. Let me show you. I create a custom play method here. This method will take audio as an argument, which will be one of these. It will rewind it to the beginning by setting its current time property to zero, and only after that it will automatically call the built in play method. I need to call the custom play method like this, and I need to pass it the audio. I want to rewind and play like this. Now, even when I quickly destroy enemies, the audio reacts. We will improve this sound even more. But before we do that, I import slide P three. I give it an idea of slide. I want to have visual and audio feedback to every important action the enemy takes. I bring it into the project here inside the phasing state. If we click the enemy while it's invisible, while it's phasing, we will play the slide. Sound Now if the players click the enemy when they shouldn't, while the enemy is phasing, it will give the enemy a speed boost. And we will also get an audio confirmation that it happened by hearing the slide. Sound I bring more boom effects, boom, 234. And I give it ideas of boom, 234. I bring them into the project here inside the audio control class. When we destroy an enemy, I want to play Boom two, a slightly different version of the sound. I save changes to all my files, I press Enter or are to start the game. Nice now, boom to play. Let's test, Boom three. I added some squishy slime undertones when I mixed this one to make it extra juicy. Boom four has some cracking and flapping noises in there. Let me describe an enemy. I want one of these four sounds to be played randomly. I create an array called Boom Sounds, and I put all four of them in there as elements. When we destroy an enemy. The sound I want to play is one of the indexes in boom Sounds array. Instead of hard coding index one, I want a random number 0-3 When I do this, it will give me an integer, either zero, or one, or two, or three. I destroy enemies and random sounds are playing perfect. We also have a victory sound when we win a game, scary horror sound when we lose. And we have a horror scream when one of our crew members gets eaten. To figure out where to place the code that plays these sounds, we need to understand which code blocks are running over and over for every animation frame and which code blocks run only once. I want the losing sound to be played only once when game over happens. I can do it here inside our custom trigger game over method. If the player lost all lives, if all the crew members were eaten, we play the lose. Sound If the score is more than winning score, we play the win. Sound Go to enemy GS here on line 57, inside the update method on enemy class. If the enemy moved all the way across the screen from top to bottom and we didn't destroy it, player will lose one life. One crew member will be eaten, and we will play the scream. Sound Okay, I set winning score to three so we can test this easily. We have 15 lives here on line 108. 15 crew members. When the enemies get to the bottom, they will start getting eaten. It's a bit strange when multiple enemies reach the bottom, The stream Sound gets reset from the beginning as we designed it, but I don't think it works well in this particular scenario. When we lose our lives, we get lost. Sound That worked. I restart the game and I killed three enemies. I win the game. And the winning sound plays. We have a nice set of sounds and they don't have only an aesthetic effect, they also have a gameplay effect, giving the player audio confirmation that the interaction was registered and actioned. I don't want to rewind the scream, so I only want it to play again when the previous scream fully finished playing, I will play. Let's lose some crew members and see now when multiple enemies get to the bottom, we don't get a scream sound for each lost crew member if they get lost too fast. But I think it's clean when we are not resetting this particular sound until it's finished. Now it might be a good idea to adjust your winning score and play your lives to make the game as difficult or as easy as you want it to be. If you are testing it on a mobile device, you can leave a quick comment and let me know if it worked for you, or if you had any issues on some specific mobile phones and which browser was used. I recommend using Google Chrome for this. If possible, you can just leave a quick comment. For example, Galaxy S 22 Firefox browser, it works, or something like that. If you do that and test this game on your phone, it would help me to make the next mobile game tutorials better. We can test our code and emulate other devices in Google Chrome, but the emulation might not be 100% accurate. The only way to be absolutely sure is to run the code on an actual device. This was a big project, well done, if you managed to get all the way here. A.