Build Animated Physics Game with JavaScript | Frank Dvorak | Skillshare
Search

Playback Speed


1.0x


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

Build Animated Physics Game 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.

      Introduction

      0:46

    • 2.

      Basic setup

      3:51

    • 3.

      Object oriented programming in JavaScript

      4:21

    • 4.

      Drawing the player

      7:10

    • 5.

      Mouse controls

      5:59

    • 6.

      Making the player move

      7:39

    • 7.

      Creating obstacles

      6:33

    • 8.

      Non-overlapping obstacles

      6:35

    • 9.

      Randomized images from a sprite sheet

      5:14

    • 10.

      Positioning rules

      5:59

    • 11.

      Reusable collision detection method

      4:04

    • 12.

      Physics

      8:07

    • 13.

      8 directional sprite animation

      4:13

    • 14.

      Animation angles

      7:05

    • 15.

      Debug mode

      3:33

    • 16.

      Player movement boundaries

      2:56

    • 17.

      FPS

      9:39

    • 18.

      Egg class

      4:53

    • 19.

      Periodically adding new eggs

      6:59

    • 20.

      Egg physics

      5:34

    • 21.

      Draw order

      8:17

    • 22.

      Enemy class

      11:19

    • 23.

      Larva class

      3:26

    • 24.

      Egg hatching

      9:58

    • 25.

      Larva sprites and collisions

      4:37

    • 26.

      Gaining score points

      2:40

    • 27.

      Particle effects

      8:55

    • 28.

      Particle motion

      7:04

    • 29.

      Randomised enemy skins

      4:24

    • 30.

      Win and lose condition

      10:31

    • 31.

      Restart game

      6:32

    • 32.

      Extending enemy class

      5:55

    • 33.

      Simple fullscreen mode

      3:07

    • 34.

      Player sprite sheet full animation

      2:36

    • 35.

      Larva sprite sheet full animation

      1:43

    • 36.

      Enemies sprite sheet full animation

      6:38

    • 37.

      Bonus project (optional)

      0:46

    • 38.

      Bonus project setup

      1:36

    • 39.

      Enhancing game worlds

      6:56

    • 40.

      JavaScript setup

      5:52

    • 41.

      Keyboard controls

      7:27

    • 42.

      Player character

      11:21

    • 43.

      4 directional sprite sheets

      12:00

    • 44.

      How to control FPS

      9:02

    • 45.

      Randomly positioned game objects

      8:19

    • 46.

      Layering and draw order in 2D games

      5:33

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

164

Students

1

Projects

About This Class

What makes a great game? Is it about beautiful, polished visuals or about gameplay that feels good and responsive? Is it about unique ideas, or maybe it's the little details, special secrets and Easter eggs? What are the ingredients in a perfect game development recipe?

 

In this class we will dive deep into sprite animation, interactivity and 2D physics. We will learn 10 important techniques every game developer needs to know and we will apply them in a real project. 

 

Students of this class will get a lot of 2D professional high resolution game art for free. I provide environmental and character art assets in the form of ready to use sprite sheets, as well as source files with separate pieces for those of you who want to edit the colors, piece together your own mushrooms and creatures or to rig your own animations. 

 

Today we will learn:

- How to use the built-in drawImage method to draw randomised game environments and animated characters from a sprite sheet

- How to control the FPS of our game and how to measure time to trigger periodic events

- How to restart the game by pressing a button

- How to apply collision detection, resolve collisions and use that to simulate physics

- How to implement a very simple AI to make the creatures feel alive

- How to capture mouse position and animate an 8 directional sprite sheet based on the relative position between the mouse and the player character

- How to use HTML5, CSS3 and plain vanilla JavaScript to build a game from scratch. We will write and understand every line of code, we will not rely on any external frameworks or libraries

... and much more

 

The pace and techniques in this course are beginner friendly. Existing knowledge of HTML, CSS & JavaScript is needed to follow the course. If you understand JavaScript basics and know what functions, for loops and arrays are, you will be able to get the maximum value out of this class.

 

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: Beginner

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. Introduction: What makes a perfect game? Detailed, handcrafted visuals, fantasy environments, and a wide variety of animated characters? Or is it more about the game mechanics, physics for interactions, and AI to make the creatures feel alive. What is the special ingredient in game development recipe? In this class, we will dive deep into the secrets of JavaScript, web animation and front end web development. Let's try to discover what makes a great game and how we can build it from start to finish using just our own JavaScript code with no frameworks and libraries. This class is for beginners, but some basic knowledge of front end web development is required to get the maximum value. Let's go. 2. Basic setup: I'm giving away a ton of free game art when this class, I'll be like it. We will control the blue ball. Its job is to protect hatching eggs from waves of hungry enemies. Player can position all the game objects by pushing them around. We can push the X and hatchlings to safety, or we can push the enemies out of the way while building this project, I will show you how to use HTML, CSS, and plain vanilla JavaScript to implement many important web animation and game development techniques, we will apply physics to make a game objects interact with each other. We will learn how to restart our game by pressing a button, how to control FBS of the whole game, how to trigger periodic events. We will apply most controls. Learn how to manage and animate a directional spreadsheets. We will trigger and animate particles when a certain event happens, and much more. Let's take it step-by-step to make sure we really understand the code. And by the end of this class, you will have all the skills you need to build your own games and animation projects. I create an IMG element with an ID of overlay. The source will be overlay dot PNG. You can download all project are the assets in the resources section below, there are individual images and sprites as I'm using them in this class, as well as a bonus folder with source files where each game object Gmb, split into high resolution pieces. You can edit and animate. So if you want, you can mix and match, combine them with art I gave you for other classes where we are using this mushroom forest theme. And you can create your own unique game environments. All the art in this class is copyright-free. Feel free to download them, modify them, and reuse them in your own projects in any way you want. I'm already giving you all art you will need to follow this course. But for those of you, I want to take it further. If you have a graphics editor like Photoshop, you can e.g. color shift the images to create even more visual variety. Character source files can also be raped and animate it in 2D sprite tools like dragon bones or spine, check out the source files and use them however you want. It's my gift to you as a thank you for spending your time with me. So we have a basic setup in index.HTML and style CSS. Gammas defaults to this small size of 300, 150 pixels. If I set its size with CSS, I would be setting only its element size. And that would stretch my drawings. Html canvas has actually two sizes. Element size, the drawing surface size that can be set independently. I want both sizes to be the same to prevent any distortion. So I will size my canvas with the JavaScript here. I wrap everything inside load event listener because we will use a lot of art assets. And I wanted to make sure all my images are fully loaded and available before any JavaScript code runs. First, we need to point JavaScript towards our canvas element using get element by ID. We save that reference in this custom variable I call e.g. canvas. Then I take that variable and from it I call built-in getContext method, passing it to D as context type argument. This will initialize a built-in object that holds all Canvas properties and drawing methods. We can now call them from this CD x variable. So as I said before, I want to set the canvas size, both elements size and drawing surface size to the same value. We can do it like this. Canvas dot width is 1,280 pixels and canvas height is 720 pixels. Now, the full background artwork I prepared for you is revealed perfect. 3. Object oriented programming in JavaScript: I wanted to write this game as object oriented code base to make it more modular, we will have a class for player and another class for game to manage all the game logic. The main brain of this code base. We will also need animation loop to draw and update our game over and over to create an illusion of movement. Game class constructor will expect a reference to canvas element as an argument like this. Inside, we convert it into a class property and we will need to width property. And the value will be this dot Canvas from line 15, dot width. Like this. This will give us 1,280 pixels as we set it up online for, we do the same thing for this dot height. We are taking a reference to canvas element and we're setting the width and height of our game to be the same as the width and height of Canvas. We will finish this setup by connecting this canvas argument to this canvas variable a little bit later when we create an instance of our game class using the new keyword, we will get there sooner. I'll show you. Before we do that, I also need the player to have access to width and height properties of our game because the player needs to know e.g. when it moves outside the game area and so on. I will give it access to the entire game class and all its properties and methods by passing it a reference to this game class as an argument like this inside, we convert it to a class property. Keep in mind that I'm not creating a copy of Game Object when I create player objects in JavaScript are so-called reference data types. So this dot game here on line nine doesn't create a copy. It just points to a space in the memory where our main game object is stored. The code inside a class constructor. It gets triggered when we create an instance of a class using the new keyword, we will do that in a minute. I want our codebase to automatically create player when we create an instance of our main game object. So I can do this inside the class constructor. I create a property called this dot Player and I set it to new player like this. I can see that player class constructor, online aid expects game as an argument. So I pass it this keyword, since here we are inside that game class. This keyword here refers to the entire game object. Here on line 18, we are creating an instance of player class and we're saving it as this dot Player property on the game class structure in our code like this will automatically create player. When we create a game, we create an instance of game object like this custom variable I call e.g. game, and I set it equal to new game. On line 14, I can see that the game class constructor expects Canvas as an argument. So I pass it canvas variable from line to this variable will get converted to a class property and the width and height of the game area will be extracted from it as we planned. Let's check if everything worked by consolidating this game variable. Nice, I can see the correct width and height properties and we have an instance of player class in there as well. This is one of the ways how you can organize and connect your objects in an object oriented JavaScript code base. Keep in mind that the order in which we define the classes matters. Javascript file is read line by line from top to bottom. Javascript classes are hoisted, but they are not initialized until that particular line is right. So player class needs to be defined before it's used. A very good idea would be to split our JavaScript into individual modules and import and export our classes between files as needed. For this project, I will write all the code in a single JavaScript file to keep it as beginner friendly as possible, using JavaScript modules would require us to run this code through a local server. It wouldn't run the code by simply open an index HTML file in a web browser anymore, if you are more experienced, it will be very easy for you to finish the project with me. And then if you want, you can split individual classes into separate modules yourself. This class is for beginners, so let's focus on object oriented principles and animation techniques. 4. Drawing the player: The function that sits on an object is called a method. Player will need to draw method to draw and animated. It will expect context as an argument to specify which kind of us we want to draw on. We will connect this context argument to our CTX variable from line three, when we call this draw method a little bit later, I will show you. I wanted to draw a simple circle at first, representing our player. To draw a circle on Canvas, we take contexts and we call begin path to tell JavaScript, we want to start drawing a new shape. We want to close previous shape. If there are any, then we call built-in arc method, which expects at least five arguments. It expects x and y coordinates of the center point of the circle. Its radius start angle in radians measured from the positive x axis and an angle where the arc ends, again in radians measured from the positive x-axis. There is an optional sixth argument for counterclockwise. If we don't define it, it will default to false, which means that the arc will be drawn clockwise. So start angle is 0 rad, and end angle is math.pi times two, it's a full circle. Now we can choose to call fill, to fill the shape with color, stroke just to outline the shape. Or we could use both. We will do that soon. How do we actually draw the player on Canvas? Now, on the game class, I create a method I call e.g. a. Render. This method will draw and update all objects in our game. It expects contexts as an argument. Inside, I take this dot Player from line 23 and through this reference we access the draw method on player class we just defined from line 11. This method contains the code to draw a circle representing the player. I can see it expects contexts as an argument, so I pass it along this context, we passed to the render method. Now I can take this game variable that holds an instance of the entire game class. And from there I call render, and I pass it to CTX. From line three, that CTX will be assigned a variable name context here, and it will be passed along to draw method on player class. Nice, we are drawing a black circle representing the player is here. Maybe you can't see it. So let's give it a different x and y coordinates to move it. Instead of hard-coding all these values, I want you to create properties on the Player class. Then use those here. We will need x and y coordinates for player position. But because in this class we are learning about position and hit boxes and character images that can have very different shapes and sizes. I will have to create property for X and Y position of player ID box. And I will need to have a different x and y property for player sprite sheet image. It will make more sense as we build it. I want to be very explicit with my variable names to make it absolutely clear which value is the position of the collision box and which value is the position of a spreadsheet. So instead of naming these properties just x and y, I will name them collision x and college and Y, X and Y position of the collision hit box of the center point of the collision circle. All objects in our game today will have circular hit boxes because I wanted to show you how to make them push and slide along each other on the starting position of the player to be exactly in the middle of the game area. So collision x will be this dot game from lines nine. And from that property, I will extract width from line 23. And in the middle, so times 0.5 collision y will be the same. This dot games with height times 0.5. Now I can use these values as x and y arguments to Canvas arc method like this. Now we can move the player around by changing values of collision and collision. Why properties? We will also need a property called collision radius, which will define the size of this circular player. He'd books. I use it here inside the arc method as well. Default fill color is always black. I can override, adhere by certain kinds of us fillStyle property to white like this. Instead of filling the shape with color, we could also just stroke it. Again. By default, linewidth of stroke is one pixel and the color is black. I set the line width to three pixels and I said stroke style to white. Notice I'm defining these Canvas properties outside of any class or method. I do that on purpose because this code will only run once on the initial page load. You can't always do that if you have multiple objects with different fields, styles, and stroke colors. In that case, you will have to define these properties inside the draw method and switch between them over and over. The problem with that is that the draw method will be called 60 times per second. And change in a state like this could get performance expensive. It's a good idea to structure code in a way you change a state as little as possible. And when I say canvas state, I mean anything from transforms to changing colors of fillStyle and stroke style. That's why I put this code here instead of placing it directly inside the draw method to make it run as little as possible while still applying the colors and settings as I need them. I can also call fill here. So now we are filling and stroking the same path defined by arc method. I want the fill to be white, but I wanted to be slightly transparent. Kind of us has a global alpha property to set opacity of the shapes we are drawing. The problem is that when I said global alpha to a different value, everything drawn after that will be semi-transparent. I want the transparency to only apply to the fill color of player collision circle to limit certain kinds of settings only to specific draw calls. We can wrap that drawing code between safe and restore built-in Canvas methods. Than if I said global alpha to 0.5, it will affect only that specific drawing action. In our case, it will only affect the fill of this circle. So save method creates a snapshot of the current state, including its fillStyle, linewidth opacity, as well as the transformations and scaling. If we are doing that, then I can do any changes to that kind of a state I want. In this case, I just set opacity to 0.5. This fill color will be affected by that change the opacity. And then we call restore, restoring all kinds of settings to what they were when we first called its associated save method. For that reason, the stroke will not be affected by a reduced opacity. Save and restore methods allow us to apply specific drawing settings only to select the shapes without affecting the rest of our Canvas drawings. 5. Mouse controls: I want to move the player around using mouse. We already know that the code inside the game class constructor will be executed at the point where we create an instance of this class using the new keyword. We are taking advantage of data by automatically creating an instance of player class here, we can actually run any JavaScript code in here. I can even put event listeners here to make sure they are automatically applied. When I create an instance of game class, I create an event listener for mouse down event. When mouse button is clicked, the code inside this callback function will run. I tested by just console logging the word mouse down. If I save changes because I'm already instantiating this class online for D6. D7 listener is automatically applied. Now when I click on Canvas, console log is triggering nice callback function on EventListener auto-generate an event object that contains all kinds of information about the event that just happened. To get access to that object, we just need to give it a variable name. You can name it whatever you want. But the convention is usually event or E. Let's console log this event. I click on Canvas and I see it here. I inspected. You can see it contains a lot of information about that mouse-click, e.g. we see x and y coordinates of that click here. There are many other properties that tell us which mouse button was pressed and many other things. I want you to take the coordinate of the click and save them as properties on the main game object. And from there, we will be able to access them from our player object as well. I create a new property on game class called this dot mouse. It will be an object with x property with default value of this dot width times 0.5. And y will be this dot height times 0.5. So the middle of canvas, horizontally and vertically. We will also want to monitor when the mouse button is pressed down. Initially, it will be set to false. If I console log e dot x and y, you can see we are getting x and y coordinates as we click around us. The problem is that the coordinates are from the top left edges of the browser window. I would like to measure the clip coordinates from the top-left corner of Canvas instead. So when we click here in the top-left corner of the canvas, we get x and y zero-zero. For that, we can use a different property on this auto-generated event object called offset x, which will give us horizontal coordinate of the click on the target node. In our case, the target node, the target of the click is kind of as element. Now you can see the values get very close to zero as I click close to the edge of Canvas. I could also add the event listener to the canvas element itself rather than the entire browser window object. If I click closer to the top-left corner, we are getting values close to 00. Perfect. Probably it would make sense if I use this dot Canvas property here from line 31 instead, since we are inside a class and we have the reference to Canvas available here. So now we are getting coordinate of the click measured in pixel distance from the top-left corner of Canvas. Even when we resize the browser window, this is working well. I want you to save the cyclic coordinates inside our customer mouse property so that they are available to other objects in our code base, such as the player inside the mouse down event listener. I take that this dog mouse dot x property from line 36, and I set it equal to E dot offset x. This dot mouse dot y will be e dot offset. Why? I create another console log and I will look at these newly updated mouse properties. When I click on Canvas, we get an error that says cannot set properties on undefined certain x online for D3, it's telling me that I can't set x property on something that is undefined. For some reason, this dot mouse is undefined when accessed from inside Event Listener. It is because when this callback function on event listener runs, it forgot it was originally defined inside this game class constructor. It forgets what this keyword stands for. This is expected to make the event listener remember where it was first defined, where it sits in the lexical scope of our code base. We can simply use ES6 arrow function here instead. One of the special features of ES6 arrow functions is that they automatically inherited the reference to this keyword from the parent scope are all functions. Remember where in the code base they were originally declared lexically. And they adjust their desk keyword to point to the correct object, to the parent object. Now, this mouse dot x and this look mouse dot y are correctly updated to the new values, making the current mouse coordinates available all over our code-base whenever they might be needed. Later, I delete the console logs. When mouse down event happens. I said priced from line 38 to true. I copied this event listener. This one will be for mouse up event. When the mouse button is released, everything here will stay the same and reset breast to false. I also create an event listener for mouse move events. Let's consulted to check. Yeah, that's working. Let's make the player move. 6. Making the player move: Create a custom method I call update. Inside I said collision x from line 14 to the current mouse X position. And collision y will be the current mouse Y position, like this. To run this code, we actually need to call the update method. I will call it from inside render down here. I delete this console log. If we wanted to see any movement, we need to be calling render over and over. So let's put it inside the animation loop here. I call built-in Request Animation Frame a method which sits on the browser window object, but we can also call it directly like this. If we want. I pass it, animate the name of its parent function to create an endless animation loop. Now I need to call animate to actually start the animation. When I move mouse over us, we get trails. I only wanted to see the current animation frames. So between every loop, I use built-in clear rectangular method to clear the old paint. I wanted to clear the entire canvas area from coordinate zero-zero to canvas width, canvas height. Now, the player sticks the mouse as we move it around cannabis, perfect. I wanted to create a line between mouse and the player to clearly show the direction in which the player will move. Inside the draw method on player class, we start a new shape by Colin begin bath. Move to method will define the starting x and y coordinates of the line. In this case, I wanted the line to start from the coordinates of the player object. Line two methods, we'll set the end in x and y coordinates of the line. In this case, it will be x and y coordinates of the mouse. Then we call stroke to actually draw the line. This works, but since the player is always able to catch up with mouse cursor so fast, we can barely see the line. Let's give player speed, speed X horizontal speed. Initially, I set it to zero speed. Why vertical speed also initially set it to zero. Inside update method, we will calculate speed x. First, I set it to hard-coded one pixel per animation frame. And I increase player exposition by horizontal speed. That worked. I also do it for vertical position. There are two ways we can make player follow the mouse. One way would be to simply take the difference between the current mouse position and the player position on the horizontal x-axis. And set that difference as horizontal speed. And we also do that for vertical movement. Now, the player position is correcting for the difference by the entire amount of the distance. So it makes the movement instant. What if I make it move only by the one-twenty-fifth of the difference between player and mouse position for animation frame horizontally. And also vertically. I create a class properties for dx, distance between mouse and player horizontally and vertical distance. I replace those values here. It's easier to read it this way. I don't want the player to follow all the time as we move mouse over Canvas. I want only when we click somewhere or when we hold the mouse button down and move around. Inside mouse move event listener I say only update x and y mouse position. If mouse is pressed. Now I can click around to make the player move to that location, or I can drag that point around while holding the mouse down. Perfect. The problem with this technique is that the speed is not constant. Moves very fast at first, because one 20th of the distance is at first a big chunk when they are far apart. But as they get closer, one 20th of that distance becomes smaller and smaller amount of pixels to be travelled per animation frame. You might want this particular emotion for your project, but for the game we're building today, I wanted the player to move at a constant speed. We will have to use the second technique for that insight update method. I calculated the distance. We already have dx, the distance between mouse and the player horizontally. We also have d, the distance between mouse and the player vertically. We want to calculate the distance between these two points. We can do that by calculating hypotenuse, the longest side of this imaginary right triangle. We can use Pythagoras theorem formula, or in JavaScript, we have this built-in math dot hypotenuse method. This method will calculate the length of the longest side for us if we pass it to other sides of the triangle as arguments, keep in mind, it expects d, dy and dx second, which might be a bit unexpected if you never saw this before. Horizontal speed is the ratio between dx, horizontal distance between mouse and the player and the actual distance. Sandwich speed. Why? It will be the ratio between the distance on vertical y-axis and the actual distance between the two points. As a backup, when some of these values are undefined at first we say or zero, like this, we are divided in horizontal and vertical distance, these sides by the actual distance represented by the longest side of a right triangle. Dx and DY is always a smaller number than the distance because the distance is hypotenuse, the longest side. For that reason, the values we get a speed x and speed y will be somewhere 0-1. That will give us the correct direction of movement at a constant speed. There is much more to be said about this technique. But for now, this is all we need to know. I'll get back to this. Now. The player is moving at a constant speed towards the mouse. I can have a speed modifier. I set it to five, e.g. I. Use it down here and I multiply speed x and speed. Why by that modifier, after we add the speed modifier, the player circle will actually never stay still anymore. It will be swinging back and forth, in this case by 50 pixels because the speed modifier pushes it too far in both directions. I can fix it by saying, only move the player when the distance between mouse and the player is more than speed modifier. Else said speed x to zero and speed y to zero as well. This works perfect. So we covered one simple and one more advanced technique to make the player move towards the mouse. Now it's time to add solid, randomized, non-overlapping obstacles. 7. Creating obstacles: I create a class I call obstacle. Constructor will expect the game as an argument. And inside I converted that reference to a class property, same as before. It will be pointing towards the main game object. And we needed here because through this reference we have access to game width and height, mouse positions, and some other properties. We will be added later. We will have access to all these values from inside obstacle class through this.name reference from line 54. As I explained before, the objects in our game, we will have a circular collision heated box, and a separate rectangular spreadsheet. For that reason, I will be calling these properties with a very descriptive names to make sure it's very clear what's happening when we are moving and animating everything later. Collision x, the central point of collision circle of each obstacle will be a random value between zero and the width of the game. That width is coming from line 62 here. And we're accessing it through this dot game reference we created on line 54. We will also need collision. Why vertical central point of collision area circle. It will be a random value between zero and game height. This value collision radius will be 60. We will also need to draw a method that expects contexts as an argument. I want that circle that represents a hit box area of each obstacle to look the same as the circle representing the player. So I take the drawing code from up here, just for the circle. So this code block, I copy it and I paste it down here. This code will work here because the same as with the player we gave our obstacles property is called collision x, collision and collision radius. We will also need the same name in on all these properties between different object types. In case we want to have a reusable collision detection function. I'll show you how to use that one later. It's simple. Anyway, here we have a code to draw a circle with a radius of 60 pixels with 50% opacity, white fill and white, fully visible, full opacity stroke. This obstacle class here is a blueprint. We will use it to create individual obstacle objects. The actual logic to create and manage these objects will be down here inside the main game class, which is the main brain of our code base. I create a property called this dot obstacles. It will be an array that holds all currently active obstacle objects. It will start as an empty array at first, the number of obstacles will be e.g. five. I create a custom method on our game class, I call e.g. in IT, initialize its job for now will be to create five randomized obstacle objects and put them inside obstacles array we just defined. Inside, I create a for loop. It will run five times because we said number of obstacles to five up on line 76. Each time it runs, it will take this dot obstacles array from line 77 and on it, it will call built-in array push method to push method as one or more elements to the end of an array, and it returns the new length of the array. I will pass it a new obstacle like this. The new keyword will look for a class with the name obstacle, and it will trigger its class constructor up online 53, I can see that obstacle class constructor expects game as an argument. Down here, init method sits inside that game class, so I pass it the, this keyword, which here represents the entire game object with all its properties and associated methods, making all of these available from inside obstacle class. Now, I console log game and I can see obstacles array is completely empty. To fill it, all I have to do is called init method. We just wrote like this. Now I can see the array contains five obstacle objects. I double-check to make sure all properties have values. If you see undefined in any of these, it means there is a problem in your code base. All is good here. Same as I'm drawing an update and the player from inside the game render method here, I would like to draw all five obstacle objects on Canvas. I take obstacles array from -77. We already know that it contains five objects and that each of these objects was created using our custom obstacle class from I'm 52. They all have access to this draw method we defined on line 59. So here inside render, I take that obstacles array, I call built-in array for each method, the forEach method executes a provided function once for each array element. First, we need to define a variable name which will be used within this forEach method to refer to individual objects in that array. I will call each object obstacle. So for each obstacle object in obstacles array, I call their associated draw method from 1959 online 59, I can see that it expects a reference to context as an argument to specify which kind of Us element we want to draw on. I simply pass along this context that was passed to the parent render method. Nice. We are drawing one player and 12345 randomly positioned obstacles. I go up here and I make the obstacles a bit larger. Every time I refresh browser window, they get positioned randomly somewhere within the canvas area because that's how we define their position on lines 55.56. What if I wanted to make sure that the obstacles never overlap like this and maybe take it even further, since this will be solid obstacles that player can't move through and has to walk around them. I would also like there to be a minimum spacing between them and also between the edges of the game area. Just to make sure all the creatures that will soon be crawling here don't get stuck and can eventually find their way automatically around each obstacle. It's actually easier to implement all of that, then you might think, but we have to take it step-by-step and explain a couple of tricks we can use here to achieve that. 8. Non-overlapping obstacles: Inside init method, we are simply adding five randomly positioned obstacles. Right? Now. I have to delete this. We will need this structure is called a bit differently here. So first, I wanted to make sure the obstacles don't touch, that they don't overlap like this. We could also adjust the number of obstacles to be the maximum number of circles possible can fit into a certain area without any two of them overlapping. Sometimes we call this circle packing. So let's write a very simple circle back in algorithm here. I will use the basic technique where you just try to play circles at random positions many times. And only those that don't collide with already existing circles will actually be turned into obstacle objects and drawn. This is also called a brute force algorithm. It's not very smart, it just tries over and over many, many times. I will create a lead variable called attempts. It will be my safety measure. We will count how many times we tried to draw a circle and we will give up after a certain number of attempts. The assumption being that there must have already been enough opportunities to place the obstacles. I will use a while loop. You have to be careful with this one. If you create an infinite while loop, you will slow down your browser and you will need to restart it. Very old computers might even freeze if you use while loop Rome, new browsers can usually deal with it. My goal here is to randomly place circles over and over. And before we actually turn that circle into obstacle object, we check if it overlaps with existence circles. On if it doesn't overlap, we added into the obstacles array. I want this while loop to run as long as obstacles array length is less than, number of obstacles, less than five. We defined that array here, and number of obstacles was defined here. As a backup, I also set a secondary condition, only continue running this while loop as long as attempts is less than 500. This is important because if I said radius of an obstacle to be a very large number, or I set number of obstacles to be so large that they can't physically fit into the available area, we would get an endless while loop. But when the secondary condition JavaScript, we'll just try 500 times. And if by that time they couldn't find placement for all the obstacles, it will give up. I think 500 attempts is more than enough. Every time the loop runs, we have to increase attempts by one for our safety back-up plan to work. Every time this while loop runs, we create a temporary object I call e.g. test obstacle. It will be equal to the new obstacle and I pass it a game, this keyword as an argument as we did before. Let's console log this test obstacle. Nice. We have 500s test obstacles in console. Now, you can see they have collision, collision y and collision radius properties as they should. My goal now is to take this temporary test obstacle object and compare it against every other obstacle in obstacles array. Of course at first, this array is empty, so the first obstacle should always be placed without issues. The second test obstacle will compare itself with the first one that's already in the array, and so on. So for each obstacle, obstacles array, I will run a circle collision detection formula. Circle collision detection in JavaScript is quite simple. We basically need to calculate the distance between the two center points of those two circles. Then we compare the distance between two center points with the sum of the radii. If the distance is less than radius of circle one plus radius of circle too, they overlap. If it's exactly the same, the circles are touching. The distance is more than the sum of radii. There is no collision. We already did this when measuring the distance between player and mouse. This time, the two points we want to measure the distance in between is the central point of obstacles circle one. And central point of obstacles circle too. So again, we are creating this imaginary right triangle where dx is the difference between two points horizontally. D is the difference between the two points vertically. And the actual distance is the hypotenuse of that triangle. So here we use Pythagoras theorem formula or a built-in math dot hypotenuse method, passing it a DY first and the second. Now we know what is the distance between the two central points. Sum over ADI is the radius of circle one, in this case, radius of test obstacle. And the second one is the radius of whatever obstacle object inside obstacles array, we are currently cycle and over. As we said, if the distance is less than sum of radii, how will I do this? Outside the for each method, I create a flag length variable I call overlap, and initially I set it to false. The distance is less than sum of radii. We set overlap the true because collision was detected outside the for each method. If overlap is still false after we created desk obstacle and after we compare it using Collision Detection formula with every other existing obstacle in the array. If it doesn't collide with any of them. And overlap variable is still false. After all these checks on, then we take obstacles array and we will push this test obstacle that passed our checks into the array. Now, when I refresh the game, five obstacles will be randomly positioned and they will not be overlapping because those that do overlap are discarded. And only non-overlapping circles are used. Because I have my safety measure here on line 10008, and we always stop this while loop when we reach 500 attempts, I can actually go up here and I can set the number of obstacles to a large number that I know will never fit our code. We'll just place as many obstacles as possible and then it will stop trying. We know this is working because if I keep refreshing my project over and over, we never see overlapping circles. I mean, no obstacles overlap with each other. Player can overlap at this point With Obstacles. We don't care about that right now. I said a number of obstacles to ten. 9. Randomized images from a sprite sheet: Now let me show you how we will be attaching images to the circular collision hit boxes and how to position the image in relation to the head box so that it makes visual sense and creates an illusion that this is not flat canvas, but a three-dimensional environment where the player can actually walk around these obstacles. You can download all projects are the assets in the resources section below. In index.HTML, I create another image element with an ID of obstacles and source will be obstacles dot PNG. That image is a sprite sheet. We will randomly out one of these frames for each obstacle object. I don't really want to draw the actual image element, so I hide it with CSS inside obstacle class constructor, I create a new property, I call this dot image. I pointed towards that obstacle spreadsheet using get element by ID like this. Let's set the number of obstacles to one for now. Inside the draw method on obstacle class, I call built-in canvas draw image method. This method needs at least three arguments, the image we want to draw. So this dot image from line 58 and x and y coordinates where to draw it? I will draw it at this dot collision x and this dot collision. Why? At first doing this, we'll simply draw the entire image sprite sheet. And the top-left corner of this spreadsheet will be starting from the center point of obstacle circle, because this is how by default, images and circles are drawn on HTML canvas. If I refresh the project or new obstacle is positioned randomly somewhere on Canvas, I created this spreadsheet for you. So I know that individual frames are 250 pixels wide. I save that value as sprite with variable sprite height will also be 250 pixels. If you are using a different spreadsheet, you can get the width by dividing the width of the entire spreadsheet by the number of columns. And the height is height of the sprite sheet divided by the number of rows in case we want to add scale. And later, I will also create independent width and height properties. For now, there will be equal to Sprite width and Sprite height because I sized the sprite frames to the exactly same size as I want them to be drawn in the game. Draw image can also accept optional fourth and fifth arguments defined in the width and height. The entire image will be squeezed or stretched to the area we defined by these values. It will look like this. What I actually want to do is to crop up one of these 12 obstacles and draw only that one at the size of 250 times 250 pixels. For that, I need to use the longest version of draw image method that expects nine arguments. Those nine arguments are the image we wanted to draw, source x, y, source with source height of the area we want to crop out from the source image. And destination x, destination. Why destination with and destination height to define where on destination us I want to place that cropped out piece of image onto. So if I pass it a zero as a source x and zero as source height. Sprite with sprite height like this as source width and height, I need to spell correctly. So now we are drawing the top left frame in our spreadsheet. As I said before, I will set separate x and y position for the spreadsheet. There are multiple different ways to do this. I can just simply position the image directly on top of collision x, which is the central point of collision circle, minus the width of the image times 0.5. This will center the image horizontally exactly over the collision circle. To actually apply this, I need to use sprite X as destination x property passed to draw image method here, be careful when passing arguments to draw image method. The order in which you pass these arguments is very important. Okay, if I refresh the page, I can see it's been correctly centered horizontally. I do the same thing for Sprite y, and I use it as destination. Why property passed to draw image method. Now the spreadsheet is directly on top of the collision circle. I said collision radius to a smaller value. I want this small collision area to be positioned at the base of the plant where the stone is. Because that will be the solid area that's touching the ground that are game characters will have to walk around. Since our sprites set size of 250 times 250 pixels, I can actually use a hard-coded value here. Plus 40 will move it up. -40, -50 -60 -70. Yes, this seems alright. I said that the number of obstacles to ten. 10. Positioning rules: What if I wanted to make sure that not only the obstacles that don't overlap, but also that there is a additional minimum 100 pixels space in-between. So that's they are more evenly spaced out around the available game area, as well as allowing enough space in-between the obstacles. The game characters can easily walk around them. I create a helper variable I call e.g. distance buffer, and I set it to 100 pixels like this. Then I included distance buffer here in some of radii to apply this buffer in-between obstacles when we are placing them. Nice. To make sure this is working, I increase the distance buffer 250 pixels. That should make it even more apparent. Yeah, so this is how we can easily control obstacle spacing. I also want to make sure that obstacle sprite images are entirely drawn within the game area and not partially hidden behind the edges. I could have done this insight obstacle class constructor when defining these values initially. Or I can also just do it here, since we are not drawing that many obstacles and their positions are calculated only once on the first page load anyway, I make sure the left edge of obstacle spreadsheet is more than zero, so it's not hidden behind the left edge of Canvas. At the same time, I make sure that the right edge is not hidden. So sprite X must be less than the width of the game area minus the width of the obstacle. Nice. When I refresh the page, I can see horizontally, obstacles are always fully visible. For vertical position, I want to check if the image, the central point of collision circle more than zero vertically will not be enough. I want to define an area that is reserved for this background artwork. I don't want to ground obstacles to appear over this area. I create a property called top margin. I guess at this top area is around 260 pixels of height. Let's check here. Yes, 2.6D looks alright, because I wanted to make sure the base of the obstacles doesn't overlap with this top area, but I don't mind if the top of the obstacle spreadsheets overlaps like this because this looks like the obstacle plant is standing in front of the background for us to view. So this is fine. I will also check if the central point of obstacle collusion area circle is less than the height of the game area. I want some margins. I can e.g. create a helper variable that's equal to collision radius of the test obstacle times two. I replace this hard coded value with this dotted top margin property we defined. Plus I want to give it some additional top margin so that characters and especially enemies can squeeze in between obstacles and gain boundaries. Walking across the game field horizontally from right to left. I will also account for the margin from the bottom of the game area to create some space there. We wrote code that automatically places obstacles in our game world. This obstacles never overlap and their correlation areas are placed to allow enough space in-between them. This will make the next step is much easier because we need enemies and friendly NPCs to be able to automatically walk around them using very simple artificial intelligence. We have different images for obstacles, but right now we are drawing only the first top-left frame at coordinate zero-zero. We can crop out to different areas from the obstacle spreadsheet, horizontal crop area. We'll start from the position we pass as source x argument to draw image method here, zero times sprite with is this frame. One. Sprite width will be this frame. Two is this 13, is this one. Back to zero. To select from which row we are cropping, we use source Why argument here? Again, we multiply rule number by the actual height of individuals bright frames, zero times sprite height is this one term sprite height is this. Now we are unrolled two and there is no row three because we start from row zero. Images are drawn and cropped from the top. So instead of hard-coding these values that are currently set to 00, Let's turn them into class properties for clarity. And is a control. This look frame x will determine which column we are on in our obstacle spreadsheet. If I do a random number 0-4, this will not work. There is no column 1.74, e.g. we need integers, numbers without the decimal points. So I wrap it in Math.floor to round random value generated by Math.random to the closest lower integer. This code will give me either zero or one, or two or three. So one of our sprite columns, when we multiply these integers by the width of a single sprite frame and we pass that value as a source argument to draw image method, we are defining horizontal cropping coordinate. That worked perfect. I will do the same for frame y, which will determine sprite row. We have only three roles. This line of code will give me integers, either zero or one or two corresponding to the number of rows we have available in our obstacle spreadsheet. Now we can replace this hard coded zero with this dot frame y. So source Why argument but asked to draw image method will be this dot frame y times this dot sprite height. I'll do that in a second. Random values in frame x and frame why combined will give us a random image out of these 12 available obstacles, each obstacle object will have random frame from this spreadsheet assigned to it. I will finish this a bit later. 11. Reusable collision detection method: On the main beam object, I create a method I call check collision. I want this to be a reusable utility method that takes object a and object B and it will compare them and check if they are colliding or not. We will be able to use this all over the code base wherever collision detection between two circles is needed. The way I'm building my game, all characters and objects will have a circular collision area, which will be a solid base that nothing can walk through and everything will react and walk around everything. Using this, we can also push things around. I will show you check collision between two circles. We have circle a and circle B. Here. We need to check dx first, the distance between the center point of circle a and the central point of circle B on the horizontal x-axis. This reusable methods will work only if all objects involved have properties with the same naming convention. So we will make sure we named x and y positions on each object as collision x and collision why? I'm using this overly descriptive property names so that it's very clear when x and y coordinates relates to collision area circle and when they relate to image sprite sheet positions. This is a tutorial, so I want things to be very clear and easy to understand. We will also need a D, Why the difference between the central point of circle a and the center point of circle B on the vertical y-axis. Then we want to know the distance between these two center points. So hypotenuse, the longest side of this imaginary right triangle, right angle 90 degrees is here. And this is the distance b dagger has theorem formula or alternatively built-in math would hypotenuse method. And we pass it the Dui first and the x as the second argument. To determine whether or not there is a collision, we compare distance between these two center points with radius of circle a plus radius of circle B, I will save this value as a custom variable, I call e.g. some of radii. So if distance is less than sum of radii, we know the circus collide. If the distance is the same as sum over ADI, circles are touching. If the distance is more than the sum of radii, we know there is no collision. This function will simply return true if there is collision and false if there is no collision. Let's use our custom check collision function. Up here inside update method on player class, we check for collision between player and obstacles. We have a one player object and multiple obstacle objects. So to compare all, we will call for each on obstacles array, which holds all currently active obstacle objects. I will call each object in the array with a helper variable name, obstacle, and our console log check collision method we just defined. We know it expects circular object a and object B as arguments to compare the distance of their center points to the sum of the radii. So I pass it this, which means this player object, circle one and obstacle we are currently cycling over with this forEach method as circle B. Keep in mind that this reusable check collision method can only compare objects that have collision x, collision and collision radius property is defined in their class constructor. So I will make sure I keep the same naming conventions for all objects in the game we are building today. As the player moves, we are getting false and true in the console. Seems like this is working. Let's actually only console log the word collision when collision between player and obstacle is happening. Now, it's even easier to see that our code is working. Perfect. 12. Physics: Inside render method, I will draw obstacles first, so behind and player after it, so it will be drawn on top. What if I want to also resolve our collisions? What I mean is if they are collides with an obstacle, I don't want it to be able to walk through it like this. I want the player circle to be pushed one pixel back away from the obstacle circle in the direction that points directly away from the center point of the obstacle. This simple thing, we will make the obstacles solid. The player will actually slide around the obstacles and it will create a nice physics. Let me show you. I'm already calculated everything I need for that insight, our custom check collision method, but this function currently returns only true or false. I need this reusable method to return more values so that we can use them inside player class to calculate collision resolution of vector functions and methods in JavaScript can return one value like this, but they can also return an array that contains multiple values. I want to return true or false collision status as the first element in the array element with an index of zero. We also want to return the distance we are calculating on line 127. We will also need some of radii from line 128. And we will need DX and DY from lines 100.2526. So now our custom check collision method not only checks if collision is happening or not, it also gives us other values from calculations that happened along the way. It's important that we remember the order in which we are returned in these values. Element with an index of zero is collision status true or false? Element with an index of one is the distance. Some of radii is indexed to. Dx is index three, and d y is indexed for. I will just copy that array that gets returned here. And I commented out just so I can see it as a helper reference. Now I want to take each of these values and save them as separate variables so that we can use them to calculate collision resolution here and push two player in the correct direction away from the obstacle it's currently collide and width, I will use something called restructuring assignment. Let's just write it and I will explain it when we see the whole thing. I say let variable is this array. And it is equal to check collision between this player object and the obstacle that for each method is currently cycling over. I have to replace this first expression with a variable name. I wanted to call it, I want to call it a collision. It will be that true or false value depending on the distance between circle's center point. So if this is true, there is collision. If this is false, there is no collision. This structure and assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays or properties from objects into distinct variables. Basically saying here, create five variables for me. The first variable called collision is the array returned when we call check collision method between this player and obstacle index zero. Distance variable is that array index one, and so on. This structure and assignment does this automatically behind the scenes. It creates these five variables and pairs them. The values that sit at these indexes in the array returned by check collision method. This might be a bit strange if you never saw it before JavaScript, this structuring is a good thing to get familiar with. Modern frameworks, use it a lot and basically just taking the array returned by check collision method. And I'm assigning each value to its separate variable names so that I can use them here. So here we are inside update method on player class. We are cycling through obstacles array comparing player with each obstacle object. If there is collision between player and obstacle, if collision variable is true, we console log AAA. This works. I wanted to create a vector, kind of a small line, 0-1 pixels in length. That line will point in the direction in which we want the player to be pushed to resolve the circle collision, to make sure that collide and player and obstacle repel each other, causing the player to slide along the radius of the obstacle rather than going directly through it. Horizontal vector will be the ratio between Dx, distance between player and obstacles central point on the horizontal x-axis, and the actual distance between these two points we calculated before using check collision method. Because dx will always be less than distance, because distance is hypotenuse is always the longest side of the imaginary right triangle. Unit x will always be a value 0-1, because we are dividing smaller value by a larger value. Unit y will be the ratio between Dui, the distance between central points on the vertical y-axis, and the actual distance between the two center points. Again, it will be a value somewhere 0-1. This could also be negative values depending on how our objects sit in relation to each other on horizontal and vertical axis. So actually unit x and unit y will be a value between minus one and plus one. If I console log unit x and unit, why we can see these values, the combination of these two values being added to players horizontal and vertical position for each animation frame will make it move in a certain direction and certain speed away from the center point of the obstacle. I do that by taking player collision exposition, the central point of player's collision circle, to push it outside the radius of the obstacle it is colliding with. I move it horizontally to the position of central point of obstacles circle plus the sum of radii of player circle and the obstacle circle plus one additional pixel outside terms, that unit x ratio to give it the right direction away from the obstacles central point. We do the same thing vertically. Center point of player collision circle will be moved to the position of collision center of obstacle circle plus sum of radii of obstacle and player circle plus one pixel towns unit Y to give it the right direction of the push. I am trying to explain this in a very beginner friendly way, but don't worry if it's still a bit unclear. This is an important technique and every time you use it, you will feel more and more familiar with this coat. Eventually it will click for you how it works. All you have to understand here is that this code is pushing the player one pixel outside the collision radius of the obstacle in the direction away from the central point. And this is how you create very simple but very effective physics simulation in your game. Try to move the player around. This feels very good, doesn't it? Suddenly our obstacle circles turned into solid, impossible objects. Well done if you've followed all the way here, this is the main trick we are using today for our physics game. I adjust the speed modifier to a smaller value. We learned how to make the player move towards a mouse or towards a specified point in a 2D space, and how to make it navigate its way automatically around solid obstacles. This is a powerful technique and you can do with it more than you can imagine. We will explore some of that today. Hope you're having fun. 13. 8 directional sprite animation: I prepared a special aid directional Player's sprite sheet for this class. You can download it in the resource section below. I will include some alternative colors. Probably mine is blue too much to mushrooms in my game art. I will hide it with CSS here. Inside player class constructor. I create a reference to that image using get element by ID, and I save it as this dot image property. Inside our custom draw method, I take contexts and I call built-in canvases draw image method that we already used before. We already said that the draw image method needs at least three arguments. The image we want to draw and x and y were to draw it. This will just draw the entire spreadsheet. We can pass it width and height to squeeze the entire spreadsheet into that specified area. We actually don't have these properties defined. Sprite with the width of a single frame will be 255 pixels. Sprite height is 255 as well. Then we create separate width and height properties to allow the potential if we wanted to introduce it later. Now, we're squeezing the entire spreadsheet into the area of one sprite frame. You probably already know that we will need the longest version of draw image method where we add source x, y, source width, and height. These values will first crop out a portion of the image, in our case, a single sprite frame. After that, we draw that frame, the position defined by the last four arguments. To draw the top-left frame at coordinate zero-zero is simple. We just did it with obstacles spreadsheet, source x, y, z, zero to define the beginning of cropping rectangle. And Sprite with and Sprite height as source width and source height arguments to define its size. Now we see only one frame. I will calculate position of spreadsheet image in relation to collision and collision y-coordinates of player. He'd box in these two separate properties just for clarity. So keep in mind, these properties define the center point of player collisions circle. These two properties, we'll define the top-left corner of spreadsheet frame image we are currently drawing to represent the player. On us. Spherical coordinates r from the center point, rectangle and image coordinates are from its top-left corner. And image and rectangle goes towards right bottom, depending on its width and height from there. We have to consider this when writing the following code. Sprite X will be positioned in relation to collision area. It will be collision x, the central point of collision circle minus half of the width of player frame. Like this. I need to use sprite X inside the draw as destination x argument here. For this to work, we need to recalculate this value every time a collision x updates. So I need to put this inside the update method here. And I also do it for Sprite y, which will be collision y minus the half of player height. I can delete it here. And I use sprite. Why property here as a destination Y argument passed to draw image method. Now it's positioned on top. I actually want this collision circle to match the little shadow on the ground below the player as closely as possible, because that's the contact point we will use when interacting with other objects in our game. Since the player is fixed pixel size, I can offset it by a hard-coded value. If we were scaling our characters in this game, I would use a relative value here. -100 moves the player image up. This is alright for now. 14. Animation angles: Same as we did with obstacles spreadsheet. I wanted to navigate within our spreadsheet by swapping from frame to frame. Horizontal navigation is handled by multiplying sprite with by an integer representing the column in the spreadsheet past as a source argument here. When we cycled through this, we will animate individual directions, individual animation loops to swap between directions in the spreadsheet, the way our specific spreadsheet is organized today, we have to multiply sprite height by an integer representing sprite role, you can see a row, zero is player facing upwards away from us. Rho one is top-right to is the player facing right? Three is bottom-right for is facing down towards the camera. Row five in our spreadsheet is the player face in bottom-left, six is facing left. I think you get the idea. I put these integers into class properties. Frame x for horizontal spread navigation. Frame. Why for vertical, I replace these hard-coded values with my new variables, and now I can change what frame we are currently cropping out from the player sprite sheet by given different values to frame x and frame why? I wanted to change frame, why the row we are currently animating from the sprite sheet, which will determine where the player is facing. I want that to depend on the current angle between mouse and the player on the position where they are currently in relation to each other. For this, we have a built-in method called Math dot eta. And to Martha's, atan2 returns an angle in radians between the positive x-axis and line projected from zero-zero towards a specific point. We will use it to calculate the angle between the player and the mouse cursor. And based on that angle, we will select which row in the spreadsheet we want to animate so that the player is always facing in the direction it is moving. Towards the mouse cursor. We will need DX and DY. So I moved them up here. So these values calculated the distance between the player and mouse cursor horizontally and vertically. Keep in mind that it makes a difference if you use mouse first or the player first. In this calculation, I already wrote this code here before. Without thinking, we would use it for this, so we might have to adjust to it a bit. I will show you exactly what I mean. Martha data to expect dy, dy and dx as the second argument. I will consult angle we are calculating and I can see it is changing. And the values are from a -3.14 minus pi to plus 3.14 plus Pi. This checks out because we know that full circle is two pi, approximately 6.28 rad, which converts to 360 degrees. I will repeat that method. Atan2 returns an angle in radians between the positive x-axis and align projected from zero-zero towards a specific point. Because I'm using mouse first and the player position second, when calculating DX and DY, I'm getting values from a master data and to learn, the current mouse position represents 0.00 and player position is the point we are projecting a line towards. For the purposes of a nice visual, it would work much better if Player was the static zeros, zeros, one important, but I will leave it as is. And from the values I'm getting in the console, I will create this graph with breakpoints in radians. It was actually easy to make because I just needed one value as an anchor. And I knew the whole area is from -3.14, two plus 3.14. And we have eight player directions. So each slice was 6.20 8/8. Anyway, you don't necessarily have to understand all of this right? Now, when we have the full code, you can play with the values which will hopefully bring more clarity. It took me a while using math but atan2 before I fully understood. So if this is your first time seeing it, don't put too much pressure on yourself. If I pause the screen, this is the 0.00, this is the line projected towards another point. And Martha data and two gives us an angle in radians between this positive x-axis and this line. So by using this console log to get an anchor point so that I can see which angle values we are getting. I constructed this helper visual, which I will now use to correctly swap rows in our spreadsheet to make the player always face the mouse. If angle is less than -1.17, set frame y to zero. I will copy this a few times. -0.2, 39 is a frame y one plus 0.39 is a frame. Y to 1.17 radiance is framed. Y3, 1.96 is frame Y4. Let's see. So far this is working great. I think we got it. I can delete the console. Log 2.74 is frame five. This area is a bit weird as the circle ends and starts. I have to say if angle is less than -2.74 or if angle is more than plus 274. I want to use frameworks six. If angle is less than -1.96, frame y is seven. Pay attention to brackets here, minus n plus values and less than operators. If you are getting any unexpected behavior, make sure all of this code is the same as mine. It's easy to make a small mistake here and break your code accidentally. For this to work for all directions, I have to adjust it a bit. I can e.g. take these slides and put them here because with else-if statement, it matters which one is checked first. Sometimes, I reduced the player speed modifier to three so we can clearly see how it turns. While Destin. Now we can turn the player in all eight directions. Perfect. We will learn more about sprite animation later in the class. For now, I'm happy with this. 15. Debug mode: Since this is a physics game where we are placing collision areas at the base of each object. We want to be able to quickly swap between the view where this collision areas are visible and invisible. It will help us to tweak the physics and gameplay elements as we are developing them while giving us an easy way to check how the changes we just made will be visible for the player who will not see these boxes. I want to create a debug mode by pressing letter D on the keyboard, we will toggle all helper collision elements on and off on the main game class, I create a property called this to debug. And initially I set it to true down here where we placed our event listeners, I create another one. We will listen for key down event. Let's just console log event object. When I select Canvas by clicking on it, and then I press any keyboard key, we get this auto-generated keyboard event object. Inside we have a property called key. You can see I press the letter R, So the key that was priced sits inside E dot key property. I say if E dot key is D, set debug property from line 123 to its opposite value. So if it's currently true, set it to false. If it's false, set it to true. This way, present the same key letter D will toggle debug mode on and off. I tested by Console login test or debug. I press the d over and over. And in console I see it switches between true and false. Perfect. I remove the console log, appear inside the draw method on obstacle class. I say if this dog came to debug is true on a diner, draw the collision area circle. Now I can press letter D, the show and hide them. That works well. I want to do the same for the player. If this game to debug is true on a diner, draw the collision circle and also the line between the player and the mouse. In this case, position and size of the head boxes is not perfect yet, but we do have all the logic in place now, great job. I can make collision radius of each obstacle smaller to better match the part where it touches the ground. We have different obstacle types here. The mushroom and this big carnivorous plant should probably have different collision circles which can easily be done. But for now, I'm happy with this. You can see that the collision formula we wrote before is all we need to give the player very simple path finding ability. It will just walk around obstacles automatically. And since we placed obstacles in a way that they are always spaces in-between, it's unlikely that the player will get stuck. I can also see I'm only getting the first four obstacle images, which reminds me to go here to line 10008 and include randomized frame y-value as source. Why argument in obstacle draw image method. Now I'm randomly getting one of all 12th obstacle images. You can play with this and position and size. Your handbook says differently if you want. I'm happy with what we did so far. 16. Player movement boundaries: I wanted to make sure the player can't walk so high that it's above this background artwork area. Let's create some horizontal boundaries. First. If the center point of player collision circle is less than x coordinate zero plus collision radius, set it to zero plus collision radius. So when the left edge of the circle is touching the left edge of canvas area, don't allow it to go any further left. I want to do the same thing for the right edge. Of course, we can delete this zero plus here and here. If the center point of player collision circle is more than the width of the game minus the radius of player collision circle. Make sure it can't go any further, right? Nice. Vertical boundaries. If collision y is less than vertical coordinate zero plus top margin, we defined to be 260 pixels from the top plus collision radius. Make sure that the player can't go anymore up. That works nice. Yes, this is what I wanted. Again, we can delete zero plus here and here. Bottom boundary. That's simple. If collision y is more than the height of the game minus collision radius, make sure it stops there like this. That works if I make player collision radius smaller than obstacle radius because of the margin we defined while positioning obstacles, there will always be a place for a player to squeeze between obstacles. The edges of game area. There is not. So down here, I increase that margin. They should do it. You can compare your code with in-progress source code I will include to download in the project section below in multiple points during this class as we progress with our project. 17. FPS: I can see the bottom of the spreadsheet is being cut off on the lower rows. It's because the height of a single frame is actually 256 pixels. Now it's fixed. In Visual Studio Code editor, I select the View word wrap to make it a code break to another line if it cannot fit. If it's too long. I wanted to set FBS for the entire game because with my previous projects, a lot of you mentioned that games run too fast on your game in high refresh rate screens request animation frame or method we are using here will automatically adjust itself to screen refresh rate. So for normal screens, that will be around 60 frames per second. But on some of the new gaming screens that people use, that speed would be double, or maybe not exactly double, but much faster. We will calculate the delta time, the amount of milliseconds that passed between each goal of request animation frame. And we will only allow the game to serve the next animation frame when a specific number of milliseconds has passed. We can calculate the delta time down here inside our custom animate function. First, I defined last time outside the function like this. Initially, I set it to zero. This variable will always hold a reference of the timestamp from the previous animation loop so that we can compare it with the current timestamp. And the difference between them will be delta time. Request animation frame has two special features. As we said, it will automatically try to adjust itself to the screen refresh rate, in most cases, 60 frames per second. It will also automatically generate a timestamp for us that we can use. And it will pass that timestamp as an argument to the function it calls. In our case, animate. Imagine it's passing that timestamp here, like this. Automatically, it's auto-generated. All we have to do to use it is to assign it a variable name here. I will call it a timestamp, spelled like this, be mindful of lower and uppercase letters when defining your variable names in JavaScript, it matters. Let's do a console log this auto-generated stamps temp variable, that request animation frame has given us just to see what format it is n. You can see it gives us milliseconds since the first animate was called 1 s is 1,000 milliseconds. So here I can literally see that the game started 9101112, 13 s ago. I delete this console log. We know we have access to the current timestamp, so let's use it to calculate delta time. It will be the difference between the timestamp from this animation loop and the timestamp from the previous animation loop. Delta time is the number of milliseconds it took our computer to serve the next animation frame. Once we used last time to calculate the delta time, we assign it to the current timestamp. This way, the current timestamp can be used in the next animation loop as the old timestamp. For the very first animation loop, last time will be zero, but after that, it will always hold the value of the timestamp from the previous animation frame so that we can compare it with the value of timestamp from this currently running animation frame. And the difference between them is delta time. So let's console log delta time to see if it worked. My delta time is around 16.6 milliseconds. Thousand milliseconds divided by 60 is 16.6. So this checks out. I wonder how many of you got the same Delta time and how many of you got a different number. If you have a high refresh screen, your delta time will be a much smaller number. If you have an old computer that is struggling to animate our game, your delta time might be much higher if you have a second right here, delta time in the comments. So we know if most people get the same or very different values than me, it will help me to better optimize my future courses. If I scroll up console to the very first timestamp, you can see that the first two values of delta time are non, not a number. It is because the very first timestamp is undefined because only on the second loop, this timestamp value gets auto-generated by request animation frame. The first loop is not triggered by request animation frame, it's triggered by this line. So in the beginning when we say that delta time is undefined minus zero here we get none, not a number. It automatically fixes itself as the loop runs. But these two initial not a number values could break your code. That depends on delta time unless you account for it with some kind of oral statement, e.g. the easiest way to fix this is to pass zero here as the timestamp for the first animation loop. From the second loop, the value will become the auto-generated tau stamp. Because after that, animate will be called by request animation frame. As you can see, we get numbers here and there are no non values anymore. Perfect. I delete this console log. Let's use delta time to set the frame rate of our game. We will need some helper variables. Fps, frames per second will be e.g. 20. Timer will count over and over from zero. Towards a specific value. When it reaches that value, it will trigger the next animation frame and it will reset back to zero. Interval will be that breakpoint value that when reached, will reset timer. It will be thousand milliseconds, 1 s divided by FBS. This will give us the amount of milliseconds needed to achieve this specific FBS. We will manage this frame handling logic down here inside render method. If timer is more than interval, do something. At the same time, keep increasing timer by the value of delta time over and over. When timer accumulated enough delta time, enough milliseconds that its value is more than interval. We will animate the next frame. We will also reset timer back to zeros so that it can count again for the future frame update. I will take all this code and I put it inside the if statement. Like this. We are using delta time value on line 173. Dot value will be passed as an argument to render method up here. And inside animation loop, we are calculating delta time here and we will pass it to render like this. Okay, so something is happening. The reason everything is blinking is that we are deleting old paint all the time, but only redrawing our game when the timer reaches interval. I got this clear rectangle from here. So now we are not clear in old paint at all. And everything is animating at 20 frames per second. And everything is leaving trails. And I will clear old paint only when we are ready to redraw the next updated game A-frame here. So context, clear rectangle from coordinates zero-zero to this dot width, this dot height to clear the entire game area, one optimization would be to draw our game on multiple cannabis elements and only clear the portions of cannabis that actually update it. That way we wouldn't have to redraw everything all the time. For now, this will work fine. You should be able to see a slow down in game animation speed because we are setting FPS here to 20. To make it even more obvious, maybe I only want to animate five frames per second. 30405060. I am certain FBS to 60 frames per second, but we are not actually animating our game at 60 FPS because every time I reset timer back to zero, there is some leftover delta time I am not accounting for. So even though I say 60, the actual FPS is a bit lower. I can go down and I can account for that leftover delta time. But maybe I want to keep this code based lightweight. Maybe I don't want to make JavaScript to do even more calculations over and over. So while keeping this in mind, I will know that I have to set FBS to a slightly higher value here to actually get something around 60 FPS. If I set this to 70, I think we get smooth enough movement and we're not making JavaScript calculate leftover delta tan, which would slightly increase how performance demand in our game is. I just thought of this now I'm not sure which is a better solution. I will leave my code like this for now, but I guess the right solution here will be up to everyone's personal preference. So three to discuss this in the comments. I will consider your feedback in my future projects now that we know how to control animation speed of our game using delta time, the game will run at a similar speed on every machine, even for those of us who are using high refresh rate screens. 18. Egg class: I wanted to add eggs that can be pushed around to include even more physics in our game, those x will be hatching into creatures after a specific time or has passed. And players job will be to protect the creatures that Hodge. The x can be pushed around by enemies, but they won't be destroyed. The challenge for the player is when they hatch, enemies will eat the hatchlings. So players job in our game will be to position the x, protect them, or to push enemies away from the path of the newly hatched creatures. The larva that comes from each egg will always try to crawl into safety and hide in the bushes inside the mushroom forest at the top. This will introduce a lot of player choice and their options into our game while using physics we implemented, I got an idea for this game mechanic while watching a nature documentary where little baby turtles are hatching on the beach and trying to get to the sea for safety. In our game, we control the blue ball. Its job is to protect the hatchlings by pushing x, lavas and enemies around. This game is all about physics and positioning. I will have a custom class I call e.g. eg. Constructor will expect a reference to the main game object as usual, to make sure Ec class has access to many important properties held on the game object. X will be part of the game physics. So I need to make sure I define separate x and y coordinates for collision circle central point. And for the sprite sheet. Let's start with collision x property. It will be a random value between zero and the width of the game area. Collision y will be between zero and game height, like this, collision radius, e.g. 40 pixels. This load image will be document dot get element by ID, and the ID is in index.HTML. I actually have to create that image element. As always, images can be downloaded in the resources section below. I hide it with CSS here. I'm keeping the same naming conventions across my objects. It's a good practice. So sprite width will be 110 pixels and Sprite height is 135. Width and height will be set to the same values. In our game, every object has collision x and collision. Why properties that represent the central point of collision area circle, even player and obstacles have the properties named like this so that we can use reusable collision detection method to implement our physics to everything. Same goes for Sprite x and Sprite. Why properties? Those represent the top-left corner position from which the object's image will be drawn. Sprite X of image will be collision x plus half of the width of the image. To center the image over collision circle horizontally. Sprite y will be collision y plus half of image height. We might have to adjust this a bit later because vertically, we want the collision area to be at the base of the neck, not in the middle. We'll get to that soon. Draw method will expect context as an argument. As usual, we call draw image, and this time we just need three arguments. The image we want to draw and x and y coordinates where to draw it. If we were scaling, we would also include optional width and height arguments like this. But I'm giving you all the images in the same size. We are drawing them in game. So it's actually not necessary. As with all game objects, we are not only drawing the image representing the object, we are also drawing collision circle if debug mode is active, since we are keeping the same naming conventions for properties all over our code base, we are making our life easier. I can just copy this entire code block and use it here. So we are drawing x MHz and if debug mode is on, we are drawing collision area. Yes, probably it's a good idea to put this code into reusable methods, since we are using the same code to draw collision circles for everything. I might do that later. For now, I wanted to create a method that will periodically add a new egg into our game. On the game class, we will have an array that will hold all currently active egg objects. I will also have another property called number of eggs. Or a max x describes it even better. We will only be adding new to the game until the total is less or equal to max x value. 19. Periodically adding new eggs: Inside render method here we will handle the logic to add x periodically. We already did it. We did periodic event in this codebase where we use the delta time and triggered new game frame only when a certain interval value was reached. We will actually do the same thing here. We will need some helper variables for that. Egg timer will go from zero to x interval value. Then it will add a new egg and it will reset so that it can count. Again. We are operating with delta time, so milliseconds, I want to add a new eggs, Let's say every 500 milliseconds. Down here, I will check if egg timer is more than x interval. We add a new egg by calling this method from line 220. Inside there, I just take the eggs array, I call built-in array push method. I will push one new instance of our customers eg class in there. As usual, we know that the egg glass expect the game as an argument. So I pass it this keyword because we are inside that game object here. So if egg timer is more than x interval, we call add egg. We will also reset timer back to zeros so that it can count again towards the next egg. Else, we keep increasing egg timer by delta time, which we are already passing here to render method from before. I console log this dot x to see if the objects are being added. Sorry, this will just create an endlessly grow in array. I need to create additional condition here, only add new x as long as the length of x array is less than max x, That's better. I inspect one of the objects. I need to make sure all the properties have values. If e.g. I. Have undefined as collision x-coordinate, my x wouldn't be drawn on Canvas because JavaScript wouldn't know where to draw them. I see values on everything. This looks great. Inside render method, I would also like to draw my x. I just copy this line and I adjusted for each element in x ray, we will call it eg. We will call the draw method on it. Perfect. Now we are getting some visuals which will make it even easier for us to tweak the details and polish it. The first thing I notice is that all the eggs are added almost instantly, even though I said, I want one egg every 500 milliseconds. If I increase x interval to 1 s here, I can see that something is wrong with my code. I know the problem must be inside this code block. And it's because egg timer is more than an interval and only then add a new egg, we need to use this comparison operator here. Sorry about that typo. You probably noticed it already before. Now it works. We get one new egg added every 1 s, as long as we have less than ten x. I can also see that the images are positioned outside the collision circles. I change this plus to minus here and also here. Now that's better. I want to adjust the spreadsheet in relation to its collision circle. Plus 35 will move it up -35, we'll move it down -30. I wanted to match the bottom of the image as closely as possible, but also I don't want the collision circle to be too tall because I want the player to be able to walk behind the egg without pushing it, to have this illusion that our game area is in 3D and that it has some depth, even though in reality it's just a flat surface. We will do more to enforce this in a moment. Now I want to create a margin to make sure the x appears certain minimum distance from the edges of the game area so that we can get the player between the egg and the edge to push it anywhere we want. I want the margin to be, let's say collision radius terms to the initial x position of collision circle will be a random value starting from left. From that margin value we just defined and game with minus that margin. Down here I set interval 200 milliseconds. I want 50 x. Just to get a better idea where they can possibly spawn in our game. We have that left margin I wanted, but I can see that the x or too far to the right edge. So here I increase that right margin like this. Yeah, I'm happy with this. Dx are now always fully visible horizontally with some extra space left and right between the ages of the game area. Vertically, I will do something similar. The random position needs to start below the top margin area we defined earlier. I don't want any x in front of this background artwork. The way Math.random works, I just pushed the range from here to here. I also need to narrow the range down by reducing the span of random values we get. So game height minus top margin. Now x can appear from here to here. I will reduce the randomized value by margin to give it some space at the bottom, like this. Perfect. If you are a beginner, Math.random can be unintuitive. It's actually very simple. It can just take some practice. So here I'm saying Set collision. Why property to a random value starting from top margin here? Because we're going from the top and the range of random values is game height minus that margin, minus this other margin. So x can appear anywhere between here and here. Vertically. I set interval to 500 milliseconds and max x to be e.g. ten. For now, this means we will get an egg appear every half second until the total count is ten. This is a physics game, so we wanted the player to be able to push the eggs around to move them out of the way of incoming enemies, or to position them strategically to give the larva that will hatch from it the best chance of survival in this game, I choose that x will be indestructible. Enemies will just push the x out of the way if they collide, but the larva that hatches will be eaten if enemy catches it. So positioning and pushing the x around is very important. Let's give the x some physics. 20. Egg physics: I give each egg and update method inside, we will create a temporary helper array called collision object. This will contain all objects in our game that x will interact with. We will check for collision between each egg and these objects. So we will need player here, this dot game, dot player like this. And of course we need the solid obstacles in here. I want all these elements to be on the same level. In collision object array. We have player object here. And we will spread obstacles array into collision object array using spread operator. Like this. Spread operator allows us to quickly expand elements in an array into another array. I will actually call this collision object with an ice. I will call for each on it, for each of these objects. So in this case, for player and all individual obstacles we have here, I want to use this check collision method we defined on line 225. If you remember, it takes object a and object B as arguments. And it returns an array that gives us true or false for collision distance between two collisions circle center points, some of their radii and horizontal and vertical distance between the two center points. I copy this array. I paste it up here. And again, we will use this structure in to quickly define these five variables using a single line of code, I need a variable name here, so I will call the first one collision true or false, whether the collides with player or any obstacle. We did this before. I want this to be lead variables and they will be equal to this dot game. Don't check collision between this egg because we are inside update method on Ec class and one of the objects in collisions objects array. So as the forEach method runs, we are running check collision method between this egg and each element in this array. And we are getting five variables that tell us more details about position and collision of these two objects we are comparing. If collision is detected, we will actually use all these values to calculate how far and in which direction we want to push the egg. Horizontal direction of the push will be the ratio between the x, the horizontal distance between the two center points, and the distance hypotenuse of that imaginary right triangle. Because dx is a site of that triangle and the distance is hypotenuse, the longest side, we are divided into smaller value by a larger value. Because of that unit, x will be something between minus one and plus one. D x can be positive or negative. Unit y. Vertical push direction will be the ratio between D and distance. Now, we will use this to move the egg. We are inside a code block that will only run if x is colliding with player or any of the obstacles. So when collision happens, we take collision x of the egg and we push it one pixel outside of the radius of the object. It is collide and width. So collision x of the object, the center point, plus one extra pixel to move the egg outside of collision area. So this is how far and the horizontal direction of that move will be defined by multiplying it by unit x, which, as we said, can be positive or negative. We also need to move the collide and egg vertically. Collision center point y of the egg will be collision y of the object. It's colliding with plus radius of egg plus radius of the object plus one extra pixels. So that in the next loop condition is false. Terms vertical direction defined by unit y. Notice that here we are detecting collision and I am moving collision and collision why of the egg based on the position of the obstacle? This is just my choice and doing this will make the egg move and all these elements will be solid in that interaction. When interaction happens, We'll move player and obstacles will remain solid. They will not be pushed by the egg. Down here we call draw method on each egg. We also want to call this new update method we just wrote. Let's test that. We are pushing collision circle of this egg. I need to make sure that collision area and Sprite stick together. The simplest way would be to take this code that position sprite X and Sprite. Why in relation to collision and collision y and I will call it insight update method. I can remove the values here and now we can push dx using player, and they will also collide and slide around our mushrooms and plants, around the solid obstacles. Dx don't interact with each other. This is just my choice. I want the x to overlap so that a skilled player can push multiple eggs, kind of hurt them together, and push all of them at the same time. This choice will also keep our code simpler because we are learning. 21. Draw order: We are drawing everything on a single canvas element. So the draw order of our game objects, what is the drone behind and what is upfront will depend on the order in which we call draw methods on each object from inside the render method here. Right now, I drew obstacles, so mushrooms and plants. Then I draw x. So x are drawn on top of obstacles, as you can see here. And then we draw the player. Player is drawn on top of everything else. If I take the x and draw them first, there will always be drawn behind the obstacles behind the player. And here we can see that it doesn't really make visual sense. I wanted to create an illusion of depth, fake 3D or maybe two-and-a-half d. Objects that are low should be upfront. As we move up, objects drawn on that vertical baseline should be drawn behind, e.g. this egg should be drawn in front of this plant, not behind it. We can't really achieve that. If we draw all x, then all obstacles, and then the player, we need to adjust our code a little bit. I will have to put all these objects into a single array, and I will sort that array based on vertical coordinates. Let me show you what I mean. I create a new property on the main game class. I will call it game objects. At first, this will be an empty array. Inside random method, I will take a game objects and I will use spread operator to expand the entire array inside. I will also expand the entire obstacles array in here. And I will add the player. Now, we are holding all the game objects in a single array. This array will be recreated every time render method takes good optimization tip here would be to only do this operation one vertical coordinate of any element changes. Or when we add or remove an egg, I will repurpose this code block. Instead of calling for each method on array, I will call it on this new game object array. For each element in the array, I will assign it a temporary variable name e.g. object for each object in game objects array call their associated draw and update methods. For this to work, it's important that all objects we add into game objects array on line 217 have draw and update methods defined on their classes. Otherwise the code would break because JavaScript wouldn't be able to find that method. So we are calling draw and update on all game objects, on all x, on all obstacles and on the player. That means I can now delete these lines of code. Typo here, I spelled game objects with an S. Now we draw the first obstacle and then we get an error. We call the draw on the first obstacle. And when we tried to call update on it, we get a type error that says object dot update is not a function. I go to my obstacle class and you can see, as I said, we have draw method here, but there is no update method. We are asking JavaScript to call a method that doesn't exist on this object, I will create an update method here. Inside that method we could e.g. animate spreadsheets of these plants and mushrooms every time the player collides with them or something, maybe I'll add some interactive obstacles later. For now, we will leave this method empty. Now it's working and we are calling draw and update on all x, all obstacles and on the player. Alternatively, I could have also solved the lack of update method on obstacles by some kind of if else statements down here, there are always multiple ways to do something. Feel free to discuss how you would approach this differently. Maybe we will get some better solutions in the comments that I might use in future classes. I appreciate when you give me feedback on my code and when you suggest improvements. Okay, so now we are calling draw and update as we cycle through game objects, which means x are drawn first, obstacles are on top of x and player is drawn on top of everything. If I change the order of these elements here, the player is drawn behind now than x and obstacles are on top of everything. So now we can understand how the layering works. It depends on the order in which we call draw method on each object to draw our game objects in the order that makes visual sense. I can now sort game objects array based on each objects vertical position. I take game objects array and I call built-in array sort method. This method sorts the elements in an array and it returns the same array now sorted. By default, if we call it without passing any arguments, it will just convert array elements into strings. And it will sort them based on their Unicode values. We don't really want that, so we will pass it an argument. This optional argument we can pass to array sort method is a compare function, a custom function that defines some logic. It defines some specific sort order we want. This special function will take two arguments, element a and element be all elements in the array. In our case, in game objects, array will be represented by this a and B used in this logic we define here, I can do return like this, and I want to sort the elements in ascending order based on the value of each object collision. Why property? So we are sorting based on the vertical center point of collision circle area. Alternatively, we could also sort by the bottom of sprite image, which would be sorted by the value of Sprite y plus sprite height. Sort method can be complicated to understand if you are a beginner, all you have to understand here is that I'm putting all my elements into game objects array. Then I'm Colin built-in sort method on that array. And I'm organizing these elements based on their vertical position. It doesn't work now because I'm creating an array I'm drawing and then I'm sorting. I need to sort the elements after I created the array, but before I draw them. So like this. Perfect. Now this is drawn in front of the plant, but if I use the player to push it up, the eggs vertical position becomes less than the vertical position of the plant. Now the egg is drawn behind the plant. This is one simple way how you can draw elements in a 2D game in a way that makes more visual sense. It is a very powerful technique to add to your coding toolkit. Do you have any questions? Leave a comment. You don't have to do the following thing I will do now. I set interval to 20 milliseconds and max x will be 150. Just testing if there are any problems we need to solve. As I move through them, the physics seems very good. It's all working well. Having so many eggs for testing also gives me a pretty good idea where they might potentially spawn. They appear in the area we specified with large top margin and smaller margin from left, bottom and right. We got x, Nice job coders. I said interval 2000 milliseconds, one egg every second, and max x will be 20. Since we have this collision formula in place, if it appears on top of obstacle or the player, it gets automatically pushed outside its collision radius. I remove this console log on line 237. We have our game world. We have randomized solid obstacles. We have mouse controlled player character that can move in a direction. And we have x that spawn in specific interval. On top of that, everything collides and reacts to everything. We can make so many different games with this, Let's add enemies. 22. Enemy class: I create a custom class I call e.g. enemy. As usual, constructor will take a game as an argument and we convert that reference to a class property. We do that to get an easy access to all properties sitting on the main game class from inside enemy class through this dog game reference. We need to keep the same naming conventions here. So collision radius 30 pixels, collision x, center point of collision circle will be the right edge of Canvas. This dot game dot width. Collision y will be a random value between zero and game height value coming from here. Speed X horizontal speed will be a random value between 0.5 and 3.5. You can download enemy image in the video description. At first, we will start with the static single frame. Id will be towed, source will be told the dot PNG. I hide it with CSS because we want to draw it where the JavaScript on Canvas, this dot image property will be get element by ID. And the ID we gave it was towed. Sprite with, in this case 140 pixels and Sprite height is 260. I will also create width and height properties. And we will define sprite X and Sprite y positions of the spreadsheet image which will be positioned in relation to collision circle coordinate. Draw method will take context as an argument built-in draw image method. And because the image file I'm using is already the same resolution as the size. I want it to display it in the game. I only need to pass it three arguments. The image I wanted to draw and x and y were to draw it. I will also copy collision circle visual that will appear only when debug mode property is set to true. Only when debug mode is active. I just copy and paste it here. Since that code is the same for all our objects. Update method. In there, I want enemies to move to the left in the minus direction on horizontal x-axis by speed x, a value we defined on line 179. So we are moving enemies to the left if the right edge of the spreadsheet is hidden behind the left edge of cannabis. We can set its x position back to game width so that it can walk left across the screen again. We will also randomize its vertical y position to get the enemies walking in different lanes. So I will have enemies that walk from right to left and then they reset and walk again. Alternatively, I could have also created new animate objects over and over and destroy them, discard them when they move off screen. The code would be simple but reusing objects by resetting their position rather than creating new ones and discarding them later is a good optimization technique. Let's reuse your objects and reset their positions if you can, rather than creating new ones, using the new keyword to create a new object is more expensive than resetting existing object. On the main game class, I create a custom method I call e.g. at, NME. Up here, we will have an array that will hold all currently active animate objects. Whenever at enemy runs, it will push new animal object into enemies array. Up online 174, I can see that enemy class constructor expects game as an argument. So I pass it this keyword, because here we are inside this game class. Doing this, I'm just passing a reference that points to a space in memory where a game object is stored. I'm not creating a copy of game object. Each time I create a new enemy. Init method will run. Just want to initialize our game and set everything up inside. We are already creating obstacles. We will also create enemies in here FOR loop that will run, let's say three times. And each time it runs, it will call out. And then the method we just defined, I can select this dot enemies. And as expected, it contains three animate objects. I inspect one of them just to make sure nothing is undefined, which could be a problem. All is good here. I can delete the console log. It's a good idea to always check your objects and arrays with console logs as you build your projects step-by-step to catch potential bugs and typos in time. To draw and update enemies, I just have to expand enemies array into game object using the spread operator. We did that before. I see only collision hit boxes, I need to give some values to sprite X and Sprite y so that the JavaScript knows where to draw the images position of the sprite. We'll be moving. As collision circles move. So I put that code inside update method. Let's first centroid, then we offset it. Sprite X is collision x minus half of Sprite with like this sprite. Why is collision y minus half height? I want the collision circles to match the shadow on the ground below are floating enemies as closely as possible. We need to adjust the image positions vertically. -40 -60. What about minus height? Plus 40? I can enable and disable debug mode to show and hide hit boxes by pressing letter d. We have enemies coming from right to left and then resetting. I want them to reset all the way behind the right edge so we don't see them just pop into existence. So we reset them to game dot width plus width of enemy. And on top of that, another game with term 0.5 to give each one a different random delay. Why is this here? I delete that. Just for testing. Let's increase the speed. Resetting them at random offset behind the right edge works well, maybe that's a bit too fast. I need to restrict their vertical positions. Let's say start from the top margin. And from there a random range between zero and game height minus the top margin. I copy this value to be used as the initial collision x position inside the constructor. And I take this new collision, why I use it inside the receptor check in update method. This will not work because up here on line 176, I'm using this dot width, but it's not defined until later here on line 183. The order here matters. I just take these two lines and I put them here. Now we have enemies walking from right to left in a correct corridor and resetting behind the right edge. This way we can reuse the same enemies over and over unless I decide we want to add some other features like allowing player to destroy enemies or something like that. We will see. Again, you don't have to do this part. I'm just testing our code. So I create 30 enemies. Having so many enemies gives me a better idea how they reset and I can spot any potential issues faster. Everything seems to be working well. This would be a very dangerous forest. Luckily for our hatchling creatures, the final game will not have swarms of enemies like this unless you want to create a periodic wave of enemies like this. As one of the game and mechanics the player has to prepare for and avoid. We can do so many things in terms of game design here, I'm just giving you the tools and techniques and showing you some of my ideas. Feel free to expand this game with your creative ideas. When the course is finished, Let's go back to three enemies. Right now. The enemies are just flying through the forest without interacting with anything. First, I want them to react to solid obstacles and the player, we already have code that does that insight update method on EKG class. I can literally use the same code block and put it inside update method on enemy class. This will make enemies, treat obstacles, and player a solid, impossible objects and they will slide around them. We are inside update method on enemy class, and we are passing enemy as object a, player and obstacles as object B. And here we are saying adjust position of a based on position of B. Player and obstacles will be solid and dominant in this interaction, and enemies will be pushed around them. This simple collision check-in will also create very basic artificial intelligence. As you can see, enemies are walking from right to left across the game area. And they are automatically slide in and avoiding obstacles and the player, because they avoided the player in this way, we can also use the player to push enemies around, same as we can push the x around. I adjust enemy speed. If I add x into collision objects array on enemy class, x will also become solid, impossible obstacles for the enemies. And enemies will have to walk around them. It might be a good thing depending on how you're designing your game. By the way, I want my game to be, I actually wanted to remove the x from here. Instead, I go up to class and inside update method, I will add enemies to collision objects. Here. This will make the eggs object a path to check collisions method. And enemies will be solid, impossible object be enemies will push the x around. If I do it this way, we implemented a lot of features. So I will leave the source code from this stage in the resources section below, you can download it and compare it with your files. If you are coding alone. Hope you're having fun. 23. Larva class: Down here between egg and enemy classes. And I create a new class I call e.g. larva. I want x to have a hidden timer and after a certain time interval, each eggs will hatch into smaller larva. That larva will try to hide in the forest. And our job as a player is to protect it by pushing it closer to the safety zone or by pushing enemies away from it. The constructor on the larva class will be a little bit different because I want each larva to appear at the same position as the egg hatched from. So we will pass it a reference to the main game object as usual, but also we pass it x and y coordinates. Now, I convert all these arguments into class properties. I need to name these x and y coordinates, collision and collision, why these variables will be involved in collision detection. So we need to name them the same as we did other objects in our physics game so that we can use our reusable check collision method on this as well and involve these larva hatchlings in the game of physics loop. We will also need collision radius here, let's say 30 pixels for now. You can download larva image in the video description. I added here with an ID of larva and source larva dot PNG. It's a spreadsheet with two frames. On this role, we have a bold larva and this one has some fluff behind the neck, just to give it some visual variety. The fluff makes more sense if you know what these hatchlings turn into when they are adults. I bring the larva image into the project using get element by ID, like this. Width and height of a single frame. Now, sprite with is 150 pixels, sprite height is 150 pixels as well. If you are a beginner, I strongly suggest you follow my code exactly and use the same images. Amusing. When the project is complete, it will be easier to make your own custom changes. Changing the code as you go while following this tutorial is not a good idea unless you are an experienced the JavaScript developer making your own changes before the project is complete, we'll make it harder to debug. We will also need sprite X and Sprite y coordinates of the spreadsheet image. Each larva will need to draw and update methods. As usual. Draw method will take contexts as an argument. In the site we call built in a drawer image and we pass it image we want to draw and x and y coordinates where to draw it. I want each larva to be moving up towards the safety of the mushroom forest. This open area is full of enemies and it's very dangerous. Speed, why vertical speed will be a random value, 1-2, e.g. we defined sprite X and Sprite. Why properties that determine where the sprite sheet will be drawn. But because they will have to move every time larva moves, I need to be updating them over and over from inside update method. Sprite X will be collision x minus half the width. Sprite y will be collision y minus half the height. I hide this image with CSS. We gave it an ID of larva. 24. Egg hatching: So we have a class we can use as a blueprint to create a larva every time an egg hatches, Let's write egg hatch in logic, we will need to help our variables. Hatch timer will go from zero to hatch interval. It will count milliseconds. So let's say I want the egg to hatch after five milliseconds after 5 s. Inside update method, we handle collisions in this area. And down here we will handle hatching. If hatch timer we just defined is more than hatch interval, we do something else. We keep increasing hatch timer by delta time. Counting and accumulate in milliseconds. Delta term will be passed to update method up here on line 159. This update method will receive it here. Inside render. We calculated Delta time value before inside animation loop, delta time contains the number of milliseconds that happened between this animation frame and the previous animation frame. So hatch timer is accumulating this delta time milliseconds between frames. If hatch timer is more than hatch interval, we will delete the egg and we will replace it with a larva. Up here I create a property called marked for deletion. Down here we set marked for deletion to true. I can be check-in and removing these marked for deletion objects for every animation frame about it might be a little bit more efficient to only restructure our erase when something gets actually marked. So here we will call a custom method. I will call e.g. remove a game objects. Down here on the main game class, I will define that method. So far, we are only marking X for deletion. So whenever this method runs, I will take the entire array and I will call built-in array filter method on it. Or a filter method will just create a copy of this array. But that new filtered array will only contain elements that pass the check provided in the callback function. The check in this case will be, I only want X array to contain elements that have marked for deletion property set to false. If anything has marked for deletion set to true, it will be filtered out of the array. This is so-called ES6 arrow function syntax. I'm saying take elements in array one-by-one, assign each one a temporary variable name object. And on each of these objects, check if they're marked for deletion property is false. Exclamation mark means false. If marked for deletion on this egg is true, that egg will be filtered out of this new array. And this new filtered array is assigned to the original x ray and it overrides it. Am I over-explain? And again, let's console log this dot game dot X to see if x are being removed and added. Yes, this is working perfect. When we are in debug mode, I want the Hajj timer to be visible as a number floating above each egg inside the draw method here I call built in filtText method. This method needs at least three arguments, text we want to draw and x and y coordinates where to draw it. The change font size, rather than changing font size every time draw method runs on each egg, I will set it up here on line ten on the first page load. This is a powerful optimization technique. Font is a part of a state and frequent changes to a state can affect performance. Defined Canvas properties such as fillStyle, line width, stroke style, and phoned in a code block that runs as little as possible. Ideally, don't do this in a method that runs 60 times per second on multiple objects at the same time. Although in some cases it might be unavoidable. All I'm saying here, if you can set canvas properties on the first page, load like this, all this code will run only once. I said kind of as fond to 40 pixels. Helvetica. I could have also defined Canvas font here in this draw method. But as I said, that line of code would run 60 times per second on each active egg. That's a lot of operations that can be easily avoided by doing what I just said. Ij dimer is this ridiculous number with so many digits after the decimal point. Let's clean this up. I create a helper variable called display timer. In here, we will format that number a bit before we draw it. I can e.g. take hatch timer and call built-in to fixed method. Javascript to fixed method converts a number to a string and it rounds the string to a specified number of decimals. I actually want the zero decimals. I just want to see the milliseconds. I use that display timer variable here to actually draw it. I can adjust the vertical position of the text, maybe by collision radius like this. Up here, I will set the text line to center. This will align the timers and x horizontally. Nice. I wanted to push the timers even further up above the eggs. Maybe even more. Let's go with 2.5. Instead of milliseconds, I just want to see the seconds. So I close hatch timer in brackets and multiply it times 0.001. Now this is more readable. We can see number of seconds above each egg. Let's make each egg hatch after 3 s. Nice. When the egg hatches, it gets removed by the filter method. On the main game class, I create a property called hatchlings, and at first I set it to an empty array. Whenever an egg hatches, we will push new larva into this array. Up here on line 190, I can see that the larva expects game and x and y coordinates. So when an egg hatches, I take this to the game dot hatchlings array and I push new larva inside. I pass it to distort game. And I pass it x and y coordinates of these eggs that hatched from I remove this console log. Inside render method, I use spread operator or to expand hatchlings into game objects, arrays so that they can be sorted, drawn, and updated. Perfect, we're making progress. Now that we can see what our hatchlings look like, we can go up to larva class and clean this up. First, we will check if the larva moves to safety. They are safe as soon as they reach this mushroom and bushes area where they can hide. So if collision y is less than this dot game dot top margin, if larva moved past this point, we can set marked for deletion on it to true. We will delete that larva because we don't want to draw it anymore. And we will call remove game objects online 350 insight, remove game object's method. I do the same thing we did for x, filter the hatchlings array. And if any larva object in this array has marked for deletion property is set to true, filter it out. Just to check our console log game objects. Every time we remove an egg or a larva, I get an error. And it's because this needs to be this dot game dot remove game objects because that method sits on our main game class. I want you to draw collision circles on hatchlings. I copy this code block from enemy class. And I just pasted here because our classes have the same naming conventions on their properties. It's easy to reuse code like this. Right now, we are drawing the entire spreadsheet for each larva. I wanted to crop out just a single frame from coordinate zero-zero two. This looks bright width and this dot sprite height. And we want to draw that cropped out image at position sprite, sprite y. And we need to give it a width and height like this. Nine arguments. I wanted to position the larva spreadsheet image in relation to its collision circle. I try -50. Yes, that will work. I want the collision circle to align with the bottom of its body. I think that will make the most visual sense when interacting with game environments and characters. I remove this console log on line 362. 25. Larva sprites and collisions: Larva spreadsheet has two frames, but we are drawing just the top one. Let's randomize that frame. Y will be a random value 0-2. And since there is no row 1.5, e.g. we need integers, whole numbers without decimal points. So I wrap this in Math.floor. This line of code will give us either zero or one, because Math.floor will around the value down to the nearest lower integer. Frame X will be always zero until later in the class where I give you advanced spreadsheet. For animation. We will use frame x times sprite with here as source x argument passed to draw image method. And we also need to define a source. Why Source x and y coordinates combined will determine which area of the spreadsheet we are crop in from source Y will be framed y times sprite height. Nice. Since frame why is randomized to be either zero or one. Some hatchlings use sprite image from row zero, and some use the other one from row one. Collision between hatchlings and game objects will be handled here. I go up here inside update method on a class and I copy this code block, we will make some changes to it, but most of it will be the same. So we might as well copy it so we don't have to write all of that. Again. I paste it down here inside update method on larva class. I will remove enemies from collision objects because enemies will have a different type of interaction. So larva will automatically avoid player and obstacles. And we can also use the player to push larva around like this, which will be an important game mechanic. Collision with enemies will be handled down here. I take enemies array and I call for each on it. For each enemy object, I will call them enemy, e.g. for each one of them, call this callback function. Basically I want to say if this larva and this enemy we are currently cycling over with this forEach method collide. One way to easily check if to game objects collide is to use our custom check collision method. Again, I want to check collision between this larva. We are inside larva class and each individual enemy. As this for each method runs, we know that our custom check collision method returns an array of values. It gives us collision distance some of radii, DX and DY. Here I only want the first argument, collagen, which will be true or false depending on whether or not this larva and this enemy collide. Check collision returns an array and I want collision status true or false. I want the first element in the array index zero, like this. So here we are using the structuring to extract all five individual variables from check collision method. Here I am directly accessing just the first value with index zero because I don't need the other ones. The reason I don t need these other values when larva and enemy collide is because there will be no pushing around and no physics. The larva will just get eaten. So I said marked for deletion on this larva. Object to true. I will also call remove game objects to filter that larva out of the hatchlings array. I will also keep track of how many hatchlings we lost in disgust and variable. This dot game that lost hatchlings will be increased by one. And here where we check if Florida move the safety of the mushroom forest, we increase the score by one. So if we protect larva by position and x, Pushing enemies away or by pushing larva towards the forest. If larva successfully heights in the bushes, we get one score point. If larva gets eaten, lost hatchlings variable will increase by one. Down here on our main game class we create these properties. Score will be initially set to zero and lost hatchlings also initially set to zero. 26. Gaining score points: I can use console logs or something like that to check if the code we just wrote works, but we needed that text displayed to the player anyway. So down here, we will draw game status text. Again. We will use built-in cannabis fill text method, which expects the text we want to draw and x and y coordinates where to draw it? I want to draw the word score at coordinates 25 horizontally and vertically. Problem we have right now is that I want this text to be left aligned. And if you remember the text above x, that timer is center aligned, I will have to isolate this filtText called by wrapping it between safe and restore built-in Canvas methods. Then I can set the text-align to left. And I call a restore. Save and restore methods work together and we use them when we want to apply specific settings only to a certain draw call on canvas without affecting the rest of our project. I save canvas state. I set the text-align to left, which will affect only this filtText call where we draw score and then restore method will reset all kinds of settings to what they were. Safe was called. In this case, it will only revert to x line back from left to center out. That makes sense. This is a very useful technique, especially if you want to scale and rotate your canvas drawings. I do that in some other classes, e.g. in my creative coding fractal class, if you want to know more about it. Now, score is left aligned and timers above eggs are center aligned. Perfect. I adjusted the text to draw, I want to say score colon space in quotes plus this dot score variable to make it dynamic. Now, as hatchlings move to safety and hide in the forest, we can see our score increases in debug mode. I also want to be able to see lost hatchlings. So if this game to debug is true, I copy this line of code. Text will say lost plus this dot lost hatchlings variable. Actually we are inside game class here, so I need to say just this dot debug. Yes, I change vertical coordinate here. And now, while in debug mode, we are also keeping track of how many hatchlings were eaten, how many hatchlings collided with enemies. 27. Particle effects: Sometimes the larva hatches quickly and it's eating too fast, or sometimes larva disappears very close to the top edge while enemy is nearby. So it might not be 100% clear if it managed to get to the safety or if it was eaten. I would like to add an additional visual effect that will help us to make our game clear and easy to read. I wanted to add two types of particle effects. When the larva heights in the bushes, it will interrupt a swarm of fireflies that were sitting on the branches and they will fly up in the air. One player sees those fireflies. They know that larva is safe. If Florida gets eaten, I will try to come up with a different, very distinct particle motion. So if there are many game objects in the same area, we can still tell what's going on by seeing what type of particles are flying from there. I will also use this opportunity to talk about subclassing in JavaScript, we will have a parent particle class that will contain all properties and methods shared between all particle types. This is a so-called parent class, also called a superclass class. Firefly extends this particle class. This is a child class, also called a subclass. We will also have a class I call spark that extends particle class like this. We have one parent class and to child classes. Child classes will automatically inherit properties and methods from the parent class, which will save us some cold repetition. Let's write the code and talk about it a bit more as we go along. The parent particle class constructor will expect game X and Y position because fireflies and sparks will always fly out from the position where the larva disappeared. And let's add one more e.g. color here. Maybe I want one particle type to be gold and another one blue, depending on where in our code base was that particle created. I'll show you what I mean. I convert all these arguments into class properties as usual. I'm saying take color that was passed as an argument here and save it as scalar property on this instance of particle class. You know how this works by now, radius will be a random value 5-15. But I wrap it in Math.floor to only allow integers, so no decimal points. If we are creating many particles, you will notice a big difference in performance when we are using randomized values like this, compared to setting the initial radius to a fixed value of, let's say ten pixels for all particles. Randomize an object values when creating many object is very performance expensive. You can improve your game's performance by trying to avoid Math.random as much as possible. If you know, you will be creating many copies of that particular object. I know we will be creating many particles. We only have one player object, so there, it doesn't really matter. It gets created once. But over the course of our game, we will probably create thousands of particles. One way to avoid this would be a technique called object pooling. You create a pool of particle objects and only draw them and use them when needed. When it comes to performance, that will be much better than constantly creating new ones and deleting them. Speed x will be a random value between minus three and plus three. This means some particles will move to the right in the positive direction on the horizontal x-axis, some particles will move to the left if their speed x is a negative value. For vertical speed, it will be a random value between 0.5 and 2.5 pixels per animation frame. I want to use a little bit of trigonometry to make the particles rotate, float, and swirl around. So we will need an angle value initially, I set it to zero. V. Velocity of angle will determine how fast is that angle value increase in. I will show you exactly how to use this in a minute. Don't worry. The a will be a random value between these two very small numbers. We will delete particles that move off screen. Initially, I said they're marked for deletion to false dramas that will be on the parent particle class as well. So it will be shared for all Fireflies and all Sparks. I want to make sure that changes to a state we make here remain isolated to this particular particle. So I wrapped the drawing code between safe and restore built-in Canvas methods. We said fillStyle to this dot color from line of 3/3. I call begin path to start new shape. Built-in arc method will take horizontal, center point, vertical, center point, radius, start angle, end angle. I want you to draw a full circle. So from zero to math.pi times to math.pi times two is a value in radians and it converts to 360 degrees. It's a full circle. We have to use values in radians here when passing them to arc method. Then I call fill to fill the path width color. And I will also stroke it because in our game, everything has this vector art style with black outlines. I want the particles to match it. Plus Firefly will contain only update method. Same for Spark later when we call draw method on Firefly class. Since this class extends particle, JavaScript will automatically look for draw method and for constructor on the parent particle class. Doing this will save us code repetition. I don't have to define constructor and draw method twice if it's shared for fireflies and for sparks, we can only define it once on the parent class and the JavaScript will find it, it will be inherited. Fireflies will have unique motion, I'm thinking floating up and sway and left and right, which is very easy to implement. First, we will be increasing angle by VA, angular velocity for each animation frame. Then we will increase collision x by speed x. Since speed x can be positive or negative, they can start going left or right randomly collision y will be minus equals speed. Why? Because I want them to float up in the negative direction on the vertical y-axis. If a firefly moves all the way up and it's hidden above the top edge of game area. So if it's collision y center point is less than zero minus its radius. We said it's marked for deletion to true, and we will call remove game objects. The main game class I create a property called particles. It will be an array and it will hold all currently active particle objects. I expand particles into game objects so that they can be sorted, drawn, and updated. Inside remove game objects, I add one more line of code to filter out particle objects with marked for deletion property is set to true like this. Let's try to create some particles. I will create them up here on larva class. In this code block that runs when larva heights in the forest, we get a score point. I want a swarm of fireflies to fly out of the bushes. I take this top game look particles array, and I push one new Firefly inside. I remember that particle class constructor expect for arguments, a reference to the main game object as usual. So I just pass it to this dot game along from larva constructor. Initial starting x and y of this particle will be the last X and Y position of the larva we just deleted and color will be red, e.g. just to test it. Nice, we have red particles with white outlines. If I want more than one, I just created a for-loop. Let's say I want three fireflies each time. I will change color to yellow. Let's see what that looks like. Nice particles need black stroke. I can set it inside the draw method on each particle. But in this project, I'm not using a stroke on many other things. I can just set the stroke to black globally here on line nine, this will be more performance efficient. It will also give black strokes for collision circles while we are in debug mode. But I don't really think it's a problem. It might look even better like this. 28. Particle motion: Fireflies have a very basic left and right upwards motion. We are not using that angle. We are increasing endlessly on line 327. Easy way to make something cycle back and forth is to pass every increase in angle value to Masdar sine or cosine method. When your code is like this, va, by how much angle increases for each animation frame will determine the speed of swaying. And this dot speed x will determine the curve, the radius, how far, left and right, the motion goes. Perfect. Whenever larva successfully heights in the forest, we get a score point and we get confirmation by seeing this Firefly effect. I want sparks to look different so that in case that larva and enemy are obscured behind obstacles or something, you can still see that the larva was eaten based on the particle effect that happens there. In here, I will define a different update method with different code inside. So firefly and Spark are both child classes of the parent particle plus they both inherit code in particle class constructor, and they both share its draw method, but each one will have a unique update method where we handle motion. I will increase angle by angular velocity VA again, but I will slow it down. So times 0.5, horizontal position will be minus equals mastered cosine. We pass it this ever-increasing angle value to map it along a cosine curve. And we define the radius of that curve using speed x. Collision y will be minus equals method sign and I pass it the same angle value and radius of the curve is speed y value. We go back up to larva class. And here, if Florida collides with an enemy, we delete it. And I wanted to create a swirl of particles. I will just copy this code block we used to create a three fireflies and I copy it here. In this case, we want to create three sparks and color will be blue. How do I do this? Now I need to push the larva in front of an MA, see what happens when it gets eaten. Nice, we get blue sparks and some kind of circular motion. Just for testing purposes, I will create Sparks even when larva heights in safety so that the animation happens automatically more often without me having to chase them around. I need to see it so that I can adjust the movement. What can we do with this olive particles? You can do so many different movement patterns so easily. E.g. let's make them shrink. If you try to draw a circle using arc method that has radius less than zero, you will get an error. So we have to be very careful here. I say, if radius is more than 0.1, keep reducing radius by a small value. That value needs to be less than 0.1 to make sure we can't get below zero. Also, if you remember, we are only removing old particles if they move past the top edge of Canvas and the swirling particles never do. So, I need another condition here. If radius is less than 0.2, just to be safe, said, it's marked for deletion to true and call remove game objects method. Nice, this looks interesting. I want them to kinda explored to both sides. I haven't mentioned it before because it's not necessary to fully understand trigonometry for this course. Sine and cosine and work together to map a circular path. If we give them the same values, look what happens if I swap sine and cosine. All you have to understand about sine and cosine for animation purposes is that if you pass them, ever increase in angle value. And when you attach these values to vertical and horizontal positions of your object, you will get a circular movement. The best way to get some clarity is to play with the values tried to break it, adjusts the code and see what happens. Don't worry about fully understanding trigonometry today, it can be complicated for beginners and it takes a while to master. I'm drawing a 30 particles here to give me a better idea about the motion that happens. And if we get any edge cases appear that needs to be accounted for. You don t have to do this. I recommend using only three particles each term for performance reasons, you can see the sparks are kind of swirly explosions. I like it. The motion is very different from fireflies. I give them yellow color here, and I will go back to using fireflies. Let's see what that looks like. So we know how to extend JavaScript class to avoid code repetition, we created a parent particle class and to child classes, Firefly, that indicates to the player that larva managed to hide in the forest by disturbing swarm of growing bugs that float away upwards. And when larva is eaten by an enemy, it will turn into a swirl of magical sparks that slowly shrink and disappear. I will go back to a three fireflies here. And down here. Let's create three sparks, or maybe five, because they shrink so fast and often they are obscured by obstacles and other game objects. We want to make sure they get noticed when they appear. I would also like to allow the player to move the xs to the forest to get score point immediately, I want X to instantly hatch when we push them high enough into the safe area, that egg will automatically turn into larva and into fireflies instantly. And we will get a score point. I can do that up here on line 179 where we check if Hodge timer is more than hutch interval to turn back into a larva, I want this code block to also run if the egg was pushed to safety zone. If a vertical position collision y is less than this dot game dotted top margin. To test it, maybe I should increase hatch interval. Otherwise these eggs hatch too fast. I see an egg here, no here, and I push it the medulla. Okay, Now here we go. It hatched instantly while hatch timer was only 7 s. I try again with this egg, and yes, this works and we're also getting score points for that. Perfect. 29. Randomised enemy skins: I peptide many different enemies for you. You know how we have a single image file with multiple obstacle types. I also prepared many different toads gains for you that will play the role of enemies in our game. I had a lot of fun making different variations and imagine and what types of special abilities and special moves they could have. Let's say for performance reasons, we want to use just a set of static images for enemies. We will also animate these later if that's what you want in the final version of the game, everything will be animated. All the project images can be downloaded from the resources section below. As usual, I'm giving you all this premium game art for free. This course is designed to give you the maximum value possible. Feel free to use these art assets for your own projects if you want. So I bring this spreadsheet with four frames for enemy types into the project. Id is toads and source is towards the dot PNG. I hide it with CSS as usual. In script.js inside enemy class constructor, we create two helper variables that will help us navigate around the spreadsheet and crop out one random frame for each enemy object, frame x. We'll navigate around the spreadsheet horizontally. And it will be initially set to zero for MY will navigate vertically and it will also start at zero. I will need the longest version of draw image method to define what image I wanted to draw, source x, y, source width and height to specify which rectangular area I wanted to crop out from the source image and Destination. Destination. Why destination with and destination height to define why we put that cropped out piece of image on destination Canvas. Nine arguments in total. Image to draw cropping area. And where to put that cropped image. Let's start by cropping just the top-left frame. So we crop from coordinate zero-zero, two coordinates, sprite with sprite hide. This spreadsheet has only one column, so frame x will stay at zero. I want to crop out one vertical frame at random. So source why of the cropping area will be sprite height pushing the start of the cropping area here, given us this frame, to actually see it, I need to use the new image with an ID of toads. So to be clear, zero times sprite height will give us this frame. Two times sprite height will crop out this frame. The value we pass a source. Why to draw image method will determine where do we start cropping from a vertically. Instead of this hard-coded value, we can use frame. Why? Now, when I give frame, why a different value? It gives us different enemy types. I want each enemy object to be randomly assigned to one of these images when it's created. So we have four rows, Math.random times four. And if I wrap it in Math.floor frame y will be either zero or one, or two or three. I will also replace source X with a disk dot frame x times sprite with this will become relevant a bit later when I give you the next spreadsheet. For now, let's leave frame x at zero. It would also be nice to randomly reassign the image every time and then it moves off screen and reset. So we make use of all available images. I just randomize frame y here, like this to achieve that. To quickly test this or increased enemy speed to a random value, 5-8 pixels per animation frame. Enemies are resetting and images are randomly changing every time they reset. Perfect. Let's go back to a lower speed. I set x to five, since we are using static images for enemies at this stage, drawing them is very cheap in terms of performance, maybe I could increase the number of enemies to five as well. This is starting to look really good. 30. Win and lose condition: I wanted to display a winning and losing message on the main game class, I created a property I call e.g. winning score. For testing purposes, I set it to five. We will draw winning and losing message down here. If score is more or equal to winning score, I will wrap it in a safe and restore to restrict some drawing settings we will use now only two that win or lose message. I want to draw a semi-transparent layer to indicate the game is over, and also to make the message more contrasting against the background. So I said fillStyle to block zeros, zeros, 0.0, 0.5 opacity. Then we will draw that black semi-transparent rectangle over the entire canvas from coordinate 00 to the width and height of the game area. Let's run this code to test it. When we reach score three, we should get the Dutch semi-transparent layer. Yes. After that rectangle is drawn, I will change fillStyle to white to make sure the text is contrasting against the dark background. I set the text-align to center. We will have a main message in large letters and a secondary message in smaller font. I will just define them like this as lead variables. And the values of these messages get will depend on how well we played. In any case, this message will only display after score is more or equal to winning score. But let's say if we played well and we lost only five or less hatchlings, we will get a winning message. If we lost more than five, we will get a losing message. The goal of the game is pushing eggs, hatch links, and enemies around to make sure we protect as many as possible. So if we play well, message one will say, let's play with words a bit. You can write anything you want as a winning and losing message here. So if we win the main message in large letters across the screen, we'll say bulls-eye and some exclamation marks. The secondary smaller message will say, you bullet the bullies. If we lose, the main message will say, Borlaug's secondary smaller message will say you lost. Plus, we will display dynamic variable value to show how many hatchlings got eaten. Plus hatchlings coma. Don't be a pushover. This is a physics game about pushing things around. We need to learn to push better. I'm using a good old string concatenation to construct this dynamic message, even better would be to use a template literals here, if you are familiar with modern JavaScript syntax. Now we actually want to draw these messages. The large message one will be e.g. 130 pixels. Helvetica. Filttext method will take the text we want to draw message one and x and y coordinates will be the middle of canvas horizontally and vertically, like this. The second message will be smaller for the pixels. Helvetica. Filttext will draw message two in the middle of cannabis as well. One more filtText goal that we'll say final scores space plus we will display the final score value there, plus full stop to end the sentence. And another sentence will say, press R to butt heads again. I want to show you how to implement a very simple restart functionality. Whenever we press the letter R on the keyboard, I will also draw it in the middle of kind of as vertically and horizontally. Now I have to space those messages out so they are not drawn on top of each other. I adjust the vertical position of message one by -20 pixels, moving it up in the negative direction on the vertical y-axis. Message two will be plus 30, pushing it down. Message three will be plus 80. Let's see what that looks like. Yes, this space and is much better. We have our winning message. When score is more than winning score, we said game over to true. On the main game object, I define the game over property and initially I set it to false. The simplest thing we could do here is to freeze animation when Game Over happens, I can do it e.g. down here, I say only serve the next animation frame. If game over is false, when game over becomes true, the game will freeze. I said winning score to one just for testing. And it will display winning or losing message. And it will freeze like this. I go down to line 519 and I delete this bit. I would like the game to keep running, but we will make new X stop appearing and I will prevent enemies from reset. And so they just float off screen and stay there. So whenever game over happens, the objects that are already in the game area, we'll just finish the action they are doing, but new objects will no longer appear the game we'll just finish playing out behind the winning or losing message, but new x will no longer appear and enemies will stop, come in. Player will still be interactive and we can still move it around in the empty game world. How do we implement this? It's simple. First of all, let's say winning or losing message appears and we still have some eggs hatching larva class, we will make sure that we get score points only if game over is false. When Game Over happens, hatchlings will still appear from the remaining x, but whatever happens will no longer affect our score points. On the enemy class. I only want the enemies to reset if game over is false like this, when GameOver happens, and then this will finish their movement across the game area, but they will no longer reset to the right. So new enemies will stop coming. Down here, we only want to add new x into the game if game over is false, winning or losing message appears, the existing x, we'll still finish hatching, but new x will stop appearing. Let's test it. I have a winning message. I have some leftover eggs, but these hatchlings no longer increase our score. We have some remaining enemies, but they just slowly move off screen and don't come back again. Player remains interactive and we can still move it around. Perfect. I wanted to test the loosen message, rather than intentionally pushing hatchlings in front of enemies to get eaten, I will just manually set lost hatchlings, the ten here on line 380. Yes, we get are losing message. This is great. I said plus touch links back to zero. Adding a custom font is easy. You can choose any font you want. I will go to Google fonts. They have thousands of fonts available there. I want to use this comic book inspired font called bankers. I click here to select the font, and I click up here, which will generate some code I can use to include this font in my project. I copy these three link tags and I paste them up here in the headstock in my index HTML file, delay before my custom style sheets, so the font is available from there. Then I copy the CSS rule. I use it here. In the case of this project, I can just apply that font-family to all elements. You might want to be more specific and only applied to the canvas element e.g. now, the font is available in our project. So up here on line ten, I said canvas fond to 40 pixels bankers. This will affect the text that displays score and timers above hatching eggs. We also want to set bankers here and here, if we want to use it for game over messages, Let's quickly when the game yes. This looks better, doesn't it? Because we use safe and restore. Hear everything I do in this area will remain restricted to game over message is Canvas. Shadows are performance expensive and some browsers don't deal with it well, but if I limit them to this piece of text, we will be okay. Let's try it. We need to define horizontal distance between shape and the shadow. It can be a positive or a negative value depending on if you want the shadow to be to the left or to the right. Shadow offset y can also be positive or negative. It will determine vertical position of the shadow in relation to its parent shape. Shadow color will be black. We can also define shadow blur if we want. That one is optional, so I will leave it on default zero, which means nobler. Keep in mind that kinda shadows will only be drawn if shadow color is set to a nontransparent value. And if at least one of the properties shadow blur, shadow offset X or shadow offset y is set to a non-zero value. Shadows give the text nice highlight and make it stand out from the background a bit more. I said lost hatchlings to ten again, just to see the loosen message. What it looks like with new font and shadows. Nice, this looks great. I said flossed hatchlings back to zero. 31. Restart game: We have this message here that says press R to butt heads again, which means press R to restart the game. What I'm about to show you is the simplest way you can implement restart game functionality on the player class. I create a custom method I call e.g. restart. Inside, I want to set player properties to what they are when a new game starts. Let's have a quick look what we have here. I want the player to move to the initial position. We will reset collision x and collision why? We will also make sure that sprite image moves along with the collision circle. So I will need these two lines of code. So play restart method will move player collision area and player sprite sheet back to its starting position. We go down here to the main game class and here inside key down event listener, I say if key that was pressed is our call restart method on game class like this. I define that method down here. And in here, we will set all properties to their initial state. This will be different from project to project. We just wrote this code base so we are familiar with it and we understand what needs to be changed to restart the game back to its initial state. First, we will call restart method we just defined on the player class. Let's test it. I move the player and when I press letter R on the keyboard, player will move back to its starting position. So far so good. We can use a similar technique to give the player and ability to rewind time. E.g. we just set state and position on x and n is n hatchlings to what it was, let's say 5 s ago. That might give us some interesting gameplay. Anyway, we wanted to restart the game. So up here in the constructor, I check what needs to change. I know I will have to reset the contents of my arrays. I take obstacles, x, enemies, hatchlings, and particles. And I said all these back to empty arrays like this. I test it. Okay, so when I press R, Now this happens and needs to run init method again to recreate enemies and obstacles since we deleted them. Yes, now, when I restart, obstacles get regenerated at random positions and we also generate new enemies. I can see I also need to reset the current mouse position. I take this dot mouse and I set it to these starting values actually, so I can just copy this. I also reset the score back to zero and also lost hatchlings. I also need to set game over to false to make sure x keep appearing and enemies keep resetting. Let's test it. I play. I win the game. I press artery side. I play. I when I resize it, I play, I win, seems to be working. Alright. I said winning score to 30. Okay, I spend some time testing the gameplay and there are a couple of more things we can adjust. As you know, we can enable and disable debug mode by pressing letter D. I'm here on our custom larva class. I would like our larva hatch links to interact with x inside update method on larva class I used spread operator to expand x into collisions objects array. Doing this will make the X solid, impossible obstacles and hatchlings will have to crawl around them. This will make the game a bit more difficult and player will have to get more involved to get the x out of the way to make sure the hatchlings reach safe area as fast as possible. Sometimes hatchlings can even get stuck between multiple eggs and obstacles. And if we don't freedom in time, they will get eaten by enemies. Alternatively, I can remove X from here. I go up to the egg class and insight update method. On a class, I will expand hatchlings into collision objects array. This, on the other hand, will make the game easier because not only will the hatchlings be able to push the x out of the way. They will also sometimes put the x in front of them closer to the safety zone. You can choose what you want to do here yourself, depending on if you want your game to be easy or more challenging at this point, you know this code-based well enough. So if you want, you can take some freedom and adjust the gameplay however you want. I also want the collision circles on hatchlings to better match the sprite sheet -40 here will work well, I think to better align the bottom of collision circles where the bottom of bodies of the hatchlings. I want this collision areas to match the artwork as closely as possible. We are in debug mode now, but keep in mind that the game is meant to be played with collision circles hidden. When debug mode is switched off. You can use the same technique to better align collision circles on enemies with the little shadow on the ground below each enemy. I will do that in a minute because the next lesson we will focus on adding new enemy types. I will also give you all the characters spreadsheets and we will add a lot of animations to this project. I had so much fun designing these creatures and making them move. I hope you like it. I noticed one small edge case buck, when we get game over message and leftover enemies eat some leftover hatchlings. Lost hatchlings variables still increases. We need to make sure that lost hatchlings value stays the same after game over message is displayed. So I will only run this code block if game over is false. This will also make the hatchlings in vulnerable under the game over screen. If you don't want that, you can apply this if statement only to one line of code that increases lost hatchlings. If game over is false, lost hatchlings plus, plus. 32. Extending enemy class: Okay, multiple enemy types. I want to create two child classes that extend. Parent enemy class. Told skin will be this slimy green one, bark scan will be the hollow wooden want with antlers, spikes, and leaves. We are doing magical forest theme. So I was having fun with creature design on this one. So again, we are extending JavaScript class here. We do it to avoid cold repetition. Any properties and methods shared between all enemy types will be on the parent endemic class. Only the properties that are specific for individual enemy types will be on child classes. You can download all these premium or the assets in the project section below. We will start by adding eight different bark scans. What do you think about my designs too much? I wanted this one to be made of wood and to be hollow inside, but light coming from eyes and mouth, kinda like a Halloween pumpkin. I hide the image with CSS. I have also replaced toads image. We had four characters on it at first. Now it has eight different versions. Lots of words, slime, eyes, and tentacles. Up here on the main enemy class, I can see that the constructor expects game as an argument. I want to run the constructor on the parent enemy class and add a little bit to it from inside TO skin class. Mainly the properties that will be specific only to toad's skin enemy type. So in the child class constructor, we will expect the game as an argument. And then first we have to run constructor on the parent enemy class, also called a superclass. We call superclass constructor. And we pass the reference, the main game object along because we know the expected up here on line 264. All these properties will be specific only to tote skin NMAI because image will be different. Sprites size as well, and width and height will depend on that sprite size. And collision x uses width and its formula. So I cut out all these, base them on the child class here. So these properties will have a different value for each child class. They won't be shared. I will copy this code block and I put it on bark skin. Here we will have to adjust the values. Sprite width here is 183 pixels. Sprite height will be 280, width and height of a single frame. This enemy will be larger. This dot image will be Id of barack. Did we gave it an index HTML? So these are the properties shared for all enemy classes. They will also share this drawer and this update method. Properties on the child classes will be unique for each enemy type, we have two enemy types. I would like to randomly add one or the other. I handle adding enemies down here inside add enema method on domain game class. In here I can say if Math.random is less than 0.5, Math.random called on its own like this will return a random number that is greater or equal to zero and less than one. So we can say that it will be less than 0.5 and around 50 per cent of the cases. If it is less than 0.5, we will push new toad's skin into our enemies array. Else, in the other 50 per cent of cases, we will push new buckskin. Nice. Now we are randomly add in both enemy types. Frame x is set to zero, so we are only getting the frames from the first column. I want it to be zero or one. So Math.random times two wrapped in Math.floor like this. Now we are getting all frames. I will also show you how to animate these spreadsheets, but that will make the game more performance expensive as the character art I chose to use for this project is very detailed and images are quite large. There are optimization techniques that can be used for sprite animation, but that's beyond the scope of this beginner friendly class. We will talk about this a bit more soon. When enemies reset, we are randomized and frame y, but not frame x. Let's do it by copying line 270 and we put it here inside this if statement block. Now we are fully randomized in the image when enemies reset position, I can put these lines that randomized frame x and frame y into shared update method. Because both of my enemy types have the same amount of frames for rows and two columns. If each enemy sprite sheet had a different number of frames, I would have to extend this update method. On each NMS subclass, we are adding and deleting objects like particles, hatchlings, and x. It's always good to check our objects to make sure the old objects are being correctly removed and we don't have an endlessly grow in array. I could console log it in my update method, e.g. but running a console log like that, 60 times per second is very performance expensive. We could just console log r objects on demand whenever we press a button inside our key down event listener, I say if we press C on the keyboard, only then console log this dot game objects. Now I can play the game and occasionally I press C to check if game objects array only contains the correct objects that are currently active in the game. If you e.g. notice that it's endlessly increasing and it contains more and more particles. We know that we are not removing the old particle objects correctly. All seems good in this case. 33. Simple fullscreen mode: So in our game, we can press letter D to enable and disable debug mode letter R to restart the game, C to run a custom console log. And I'll also show you how to toggle a very simple full-screen mode on and off by pressing letter F. We will call discuss the method e.g. toggle full-screen. We will define it down here on the main game class. Javascript has a native full-screen functionality. This built-in API contains a set of methods that allow us to present a specific element and all its descendants in a full-screen mode, removing all browser user interface elements and other applications from the screen. When I call document dot full-screen element like this, it returns the element that is currently being presented in full-screen mode. If it returns null, it means that full-screen mode is currently not in use. So here I'm saying, if we are currently not used in full-screen mode on this page, I want to enter full screen mode. Request full-screen method will display the element it is called on in a full-screen mode. In this case, I wanted to display the entire webpage. So document, which represents the webpage DOD document element, which represents the root element of the document, in this case the HTML tag. I want it to full screen the entire web page from its root element code to exit full screen. This simple, so we just say else if document dot exit full screen, Run, document that exit full screen method. It's a bit weird, but it will work. During this will turn the entire web page. Fullscreen Canvas will not take up the entire screen width. We are moving the player using mouse, so we have to be careful how we re-size Canvas in this project as the mouse coordinates are calculated in a certain way. If I give Canvas dynamic width with CSS, it will start giving us wrong coordinates. In Google Chrome browser. If I go full screen like this and I zoom in to make the game cover the full screen, mouse coordinates will still be calculated correctly and the gain will be playable. You can test it for yourself by pressing F to enter full screen and then hold down Control key and tap plus or minus keys to zoom in and zoom out. On Mac, we use Command key instead. We are about to animate the spreadsheets. These images are large and it will put some strain on computer performance when we start swapping through these images very fast on each active animated object, you might want to save the code base as it is right now and continue in a copy of this folder so that you can keep static and fully animated codebases and compare them side-by-side in terms of performance on your machine. It's up to you. I will also leave the full source code from this stage of the project available for download in the resources section below, the folder with full source code from this stage is called source code version five. 34. Player sprite sheet full animation: Time to fully animate the player sprite sheet. We are already using the sprite sheet, but we're cropping only the first frame on each row to turn player in different directions. We have helper variables here, where a frame x will cycle on the same row from left to right over and over loop in that particular animation. And frame y will determine which row we are animating. In the case of player sprite sheet, different rows have the same player character facing in different directions. We are using draw method to draw this spreadsheet on Canvas. We are using the longest version with a nine arguments image we want to draw. Then we define the cropping area by the following four arguments. Source x, y, source width, and source height. And the last four arguments and define where on destination cannabis, we place that cropped out image onto destination x, destination. Why destination width and destination height? I explained this a few times in this course because it's really important to understand if you want to use the draw image for a sprite animation. We already have a functionality that swaps frame y to a different row based on where we want the player to be facing. All I have to do now to fully animated is to make frame X cycle between frame zero and max frame over and over. We will handle sprite animation down here inside update method. And we will reuse this code for other objects as well. We will need one more helper property called max frame. Sprite sheet has 58 frames per row. It's a massive spreadsheet image. We will be flying through it, cropping out different frames to create an illusion of movement and animation. Let me show you. It's easy. If frame x is less than max frame, I want to frame x to increase by one as the update method runs over and over. This will travel over the animation row from left to right. When it reaches the end frame, x is no longer less than max frame. So else statement will run. It will reset frame x back to zeros so that it can cycle again. That's it. We are animating the player. I try to walk around, turn the player in all possible directions to see if everything is okay. Now, our player is properly alive. When you prepare your spreadsheet and you'll game art correctly, like I prepared it for you. Animating it with code is very easy. All you need is this simple code block. 35. Larva sprite sheet full animation: I copy this code block. I will reuse it on larva class. I go down to larva class. Here. We will also need max frame helper property. In this case, max frame is 38. Larva spreadsheet has 38 frames per row. As usual, you can download all spreadsheets in the resources section. I put it into my Project folder and I bring it into the project here. Id will be larva underscores sprite and source will be the same larva sprite dot PNG. In script.js, I point this dot image property towards this new ID. It has 38 frames per row. And again, I want to cycle between frame zero and max frame. I copied that sprite animation called blog from update method on player class, and I paste it here. It's very simple, so there's no need to make any changes. If frame x is less than max frame, keep increasing frame x by one. Else, reset frame x back to zero so that it can cycle again. All the spreadsheets are set up so that the last frame and the first frame connect in a continuous animation loop. So looping over them over and over like this will create a seamless animation sequence. Now you can see our hatchlings are crawling with their Antonio, wobbling up and down and they're squishy bodies moving as they crawl to safety of a mushroom forest. Perfect. 36. Enemies sprite sheet full animation: I also prepared animation spreadsheets for the enemies. I give it an ID of bark skin and ID will be bark skin dot PNG. The green slime. One will be Id of adult skin and source told skin PNG. I Hyde Park skin with CSS. Also told skin. And the larva sprite. We will again copy this code block. It's important to notice how are these enemies spreadsheets organized. We need to consider that when writing our code, I can see we have four types of toads and four types for dark skin, each type on a separate row. In that case, we know that frame y will control which enemy type is displayed. Frame x will again cycle through that animation row, bring in that creature to life. It's also important to notice that I have the same structure for both tote and dark-skinned sprites. Both have four rows, 38 frames per row. So I can handle the animation on the parent enemy class as the logic will be shared for both animus subclasses. I said frame x to zero here. Frame why we'll randomly choose one of the four available enemies to animate. Max frame will be 38. In update method, I handled sprite animation up here, I paste the code block I copied. First of all, I wanted to use toad's skin spreadsheet here and bark skin here like this. When you see the animation glitch like this, it usually means that the frame size we defined is wrong. So the frames are kinda slide in. Dark skins are animating correctly. I check frame size untold skins, and I can see that the single frame in the spreadsheet is 154 pixels wide and 238 pixels tall. You get the width of a single frame by dividing the width of the entire spreadsheet by the number of columns, by the number of frames per row. And you'll get the height of a single frame by dividing the height of the entire spreadsheet by the number of rows. Perfect, we are animating the player hatchlings and eight different enemy types. We are seeing collagen circle areas, but the game is meant to be played with the debug mode disabled. We need to make sure that the collision areas match the little shadows under our float and enemies, since I want them to be pixel perfect here. And toads, canes, and buck skins have different sprites sizes. I can't offset sprite X and Sprite. Why here in the shared update method by a certain value and align both of them from the same place. In a situation like this, I want to comment this line out and I want to extend this update method on each subclass to give it slightly different values for each element type. To do it as simple. On torts can subclass that extends NME superclass parent class, we call update. If I just define update like this, this method would take priority and it would completely override the method with the same name on the parent class. I don't really want that. I want the code inside update method on enemy class to run. And I wanted to add some custom code that is specific only for toad's skin class down here inside this update method on a child class. I do it by using the super keyword representing the parent. And then my class. Here I'm saying run all the code inside update method on the parent and then the class on the superclass. Then I want to take this line of code, and this line will only run four toed scans. I try plus 50. My goal is to align collision circle with the little shadow on the ground below the floated enemies as closely as possible, we broke bark skins because they're sprite y-value is not updated now, We will fix that in a minute. First, I want to align towards, I will do height -100. Okay, how about height of the enemy divided by two -100? This is getting closer to what I want. Maybe -90. Yes. When I press the d to enable and disable debug mode, I can see that little ground shadow undertone skins aligns very closely with collision circle area. Perfect. I copy this code block and I put it here on our bark skins. Here I will do -100. So this is how you extend a method that exists on a parent class like this update method we have here. And on each subclass, we first call the code inside update method on the parent class from line 302. And then we can add some additional code to it that will be unique only to this particular sub-class. Using this technique can give each enemy type of different movement pattern, different behavior, different attacks, different animations and so on. You can download the final source code folder I called source code version six in the resources section below and compare it with your own code if you are experiencing any issues. Now it's time for you to add some additional features. Maybe try to check my other game development classes where we apply sounds or state management and use it for this game. Checkout bonus art asset collection available in the resources section below, I will leave a lot of art in multiple formats with separate pieces so you can mix and match and have fun with it if you want. Thank you for spending your time with me. I hope you've got a ton of value today. Well done for completing the project. I'll see you later. 37. Bonus project (optional): Create an animated game environments for directional keyboard controlled characters, randomly positioned obstacles, and environmental art assets. Let's make games using HTML CSS and plain vanilla Javascript with no frameworks and no libraries. As usual, if I draw all my interactive elements on a single canvas element layering can be a challenge. We can use built in array sort method to reorganize game objects based on their vertical y coordinate and draw them in that order. With that simple trick in place, we can have a player character that walks around obstacles in a way that makes visual sense. Let's build a game from scratch and learn about Front and Y development and object oriented programming. 38. Bonus project setup: We will work with three files in index HTML. I create a generic simple web page and 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 GS file. I create a dip with an ID of a wrapper and I put canvas inside. I create an image tag with Source overlay, Alt overlay, and ID overlay. You can download all art assets in the video description in the project files section. I'm also giving you all separate pieces in high resolution so you can compose your own unique background images. If you want optimization tip number one, use plain CSS. For large background images, I can draw and animate everything on cannavas. I usually do that today. I want to show you how you can combine CSS and canvas draw image method to maximize performance. This will negate the need to draw these large images on canvas over and over for every tick of animation. And it will improve performance of our games. Css transforms use GPU. They are faster and they have simpler markup because CSS has a lot of built in keywords which makes animated transitions much easier. Maybe for your game, you need everything to be drawn on canvas. But today I will combine it with some CSS to take full advantage of the tools and techniques front end web development environment offers. 39. Enhancing game worlds: Intalsiass. I give Canvas a background image, you can download it in the video description or you can put together your own background from the individual pieces I'm providing as well As you can see we created two layers. Background art, our character will be drawn on top of, and some overlay images, leaves and grass that will be in front of our forest scene. Player character will be able to hide behind them. Unless we set canvas width and height, it will always default to 300 times 150 pixels. We will make it the right size with the Java script in a minute to reveal the full background artwork. I could have also put this background image on the wrapper element. I give the main wrapper element some border. My browser is a zoomed out so I can fit everything on screen. The images I'm giving you today are optimized for 1,280 times 720 pixel resolution. The game we are building is pretty large. You can adjust the sizes if you want. If you are a beginner, it might be a good idea to follow my code exactly, use the same sizing and the same images, and only make changes once we got the entire project working. I want to center the container, so I give it position absolute. You can see that the wrapper doesn't start from the top left corner. There are some default margins and paddings to make sure our page looks the same across all different browsers. I will do a global reset target all elements on the page and I set margin to zero, padding to zero, and box size into border box. To make sure that elements padding and border are included in its total width and height, I want to center the rapidive in the middle of the page vertically and horizontally. I already gave it position absolute. Now I can give it top 50% left 50% And transform translate -50% -50% I also need to align the overlay this image. I give it position absolute top 50% left 50% transform translate -50% -50% This will align it exactly on top of the wrapper. There are many more things we can do here. For example, let's bring another two images into the project. I create an image called leaves underscore left. I give it the same old attribute and ID. You can download all these images in the video description, I create another image called leaves underscore, right? Like this. These could have been just a part of the main overlay image, but I want them to be animated and interactive. As we said, CSS transforms are processed by GPU. Let's take advantage of that to make our game world feel a bit more alive and interactive. Css do some work for us. Not everything needs to be drawn on canvas. It will all blend together really well and our game will look great. I target leaves left at top position to 50 pixels left position to -100 leaves right will be positioned -150 pixels behind the right edge up here on the main wrapper. Set overflow to hidden, to clip and hide everything that's outside the main game container. We can do so many things with it now. For example, we can have the leaves move out of the way. When we hover over canvas, we are just a silent observer hiding in the bushes. Let's push the leaves out of the way a little bit so that we can see. When I hover over canvas, I want to apply some CSS to leaves left. I will change their left position, and I will rotate them by plus 15 degrees. This CSS declaration will not work. It would work if leaves left was a child of canvas element, but it's not. If we look here, we can see that they are siblings. They are on the same level in element three and they both share wrapper as a parent. To apply something to leaves left, when canvas is hovered over, we need to use something called the general sibling selector. General sibling selector selects all elements that are next siblings of a specified element. If I look at our element structure, we have canvas element overlay image is directly on top of it. It's actually blocking the hover event on canvas from triggering. I want overlay image to be on top, but I want it to be invisible for all mouse interactions. So that I can interact with canvas that is underneath it. I can do it by setting pointer events property on overlay to non like this. Right now canvas is only in this small area, but soon we will resize it to fill the entire container to test the hover event. For now, I have to move my mouse over the small canvas area. Here it works on hover, I set left position to -150 pixels. I will give leaves some transition time so that it actually animates. Let's try 0.3 seconds. Nice. I do the same thing for leaves, right? I also give it some transition, maybe just a 0.2 seconds. So they are not completely synchronized. We can do so many things. For example, apply key frames animation to make it look like the leaves are moving from the wind. I'll call it wobble At 0% it will start at top 50 pixels. We will have 50% breakpoint at 55 pixels. And at 100% it will go back to 50. We can apply it by giving leaves left animation property. We call it wobble. Timing will be easing out. Time of animation loop will be 1.5 seconds. Like this, like this, it will run just once, but I want an infinite loop, I don't see any movement. Let's set this to 65 pixels, right? I need to make sure I have the right syntax for key frames. This semicolon has to be here we have leaves moving in the wind. Let's try 56 pixels. I copy this line and apply it also to leaves, right? I want to desynchronize them. Loop on this one will be 1.6 seconds, same as we did with overlay. I need to set pointer events to none on both leaves to make sure they don't block mouse events on canvas that's underneath it. This is how we can draw and enhance part of your game world scene with CSS. It's a good practice when it comes to performance. If your project allows it, feel free to use it more often. 40. JavaScript setup: We will also draw some images with Javascript, mainly our animated keyboard controlled Alber character. When we work with images in Javascript, we always need to make sure that the image is fully loaded and available before the code that depends on that image is executed. Otherwise, we will get an error. There are many ways to do this. We can use promises or a very simple way is to wrap all Javascript code inside load event listener. Load event is fired when the whole page has loaded, including all dependent resources such as style sheets and images. This way I can just put my spreadsheet as a regular IMG element in index HTML, and Javascript will wait for that image to load inside the anonymous callback function. Here I set up my canvas. We need a reference to the canvas element, a constant variable I call canvas and I want to point Javascript towards this canvas element we created on line 12 in index HGML, we gave it an ID of canvas one. We don't really need to use get element by ID here, because all browsers automatically create Javascript variables for all elements with an ID. This automatic variable name is always the same as ID. It's good for the bug in, but because browsers put all these variables into the global namespace, these variables are easy to accidentally override. It's better if we use get element by ID, like this. Ctx context is canvas dot get context two D to generate an instance of built in canvas two D API that holds canvas state and all two drawing methods. The parent wrapper element was set to 1,280 times 720 pixels. Let's make sure that canvas element is the same size. This will reveal the full background artwork. What do you think about it? As I said, I will also share individual pieces with you in high resolution. You can mix and match them and create your own unique game environments if you want. All art assets I'm sharing in this video are copyright free. They were designed and drawn by me or by artists I hired. You can modify them and use them however you want. I will comment out CSS animations on lines 39.31 I think it will be less distracting. We have some Java script coding to do now to bring our animated character to life. Let's follow the principles of object oriented programming today and split our code into individual classes. Each class will have different responsibilities and we will make them communicate and work together to create the final product. Custom class I call for example, input handler will handle keyboard inputs. When a key is pressed on a keyboard, this class will process that and it will transform and store that value so that it can be used by other classes. Class Owl Bear will be our main animated character. Player will be able to control it using keyboard. Class object will be used as a blueprint to create randomly generated trees, bushes and grass. Once we place them into the game world, we will learn how to organize them in a way that they are drawn in front and behind the player, depending on where the player is currently standing. This is very important because without it in game like this drawing player on top of everything wouldn't make visual sense. We need some logic so that the player can walk around these two D obstacles and I will show you an easy way to do it. Finally, we will need a class I call game. This is where all the logic from all the classes comes together. This will be the main brain of our code base. Class constructor will create an instance of a class for us based on a blueprint we define inside. Let's define a blueprint for our main game class. I want these classes to be self contained and modular. We will pass it with and height of the game area as arguments like this. We convert them into class properties. We take width and height past as argument to the class constructor and we convert them into width and height properties on this instance of game class. To create an instance of game class, I create a constant variable. I call for example game, and I use the new keyword. The new keyword in Java script is used to create an instance of an object that has a constructor function. New keyword will look for a class with that name and it will trigger its constructor. Constructor will create one new blank Java script object and it will automatically set its prototype behind the scenes. It will bind this keyword to point to this newly created object and it will assign the object all the properties and values as we define them in the blueprint here. So far, our game object will only have width and height properties. In this case, I can see that these properties are expected as values that are being passed from the outside. We do this to keep our classes self contained and modular. I pass it canvas width from line four. As with canvas height from line five as height. Because I want the game to be the same size as canvas, I want the game area to use up the entire canvas element. This is how you create a class in Java script and how you create an instance of that class. How you use that class to create one object based on the class blueprint. Let's consolok game variable from line 26 to check if everything went well in console. I can see that game variable stores a reference pointing towards a game object with height and width properties set to the right values perfect. If you get any errors when writing your object oriented code base, you can always consolo your objects like this and check if all these properties have values. If you see undefined here, you know there is a problem in your code and you can track that value back through your code base to find the issue. 41. Keyboard controls: Input handler class is here to keep track of keyboard keys as they are being pressed and released by the user. And it will convert them to values that can be used by other objects in our code base and it will store them. I give it a constructor as well. This is how we will make our objects communicate with each other. Input handler will expect a reference pointing to the main game object as an argument. This entire object inside we convert that reference into a class property like this game that was passed as an argument is converted to game property. On this instance of input handler, class objects in Java script are reference data types. I'm not creating a copy of game object here, I'm just creating a variable that points to a space in memory where the main game object is stored. This is great because when values of game object update, those changes are immediately visible from this dot game reference. Here on the main game class, I create a property called this dot last key input handle class will be updating this value on game class as keys are being pressed and released. Initially I said it to undefined. Today we will learn about keyboard controls and we will only hold the last key that was pressed or released in memory. It's all we need to control, four direction onto the character. If I wanted to keep track of multiple key presses, I would create an array here instead. And I would add and remove keys from there. I've done it before and I might do it later in this series. Depending on how complex and precise keyboard controls we will need. I also want to automatically create an instance of input handler when I create the game object. Let's put a consolo here that says input handler created inside game class constructor. I create a property called this input. I set it equal to new input handler like this. On line eight, I can see that input handler class constructor expects a reference to the main game object. Here I'm creating input handler instance inside that game class. I pass it this keyword. This keyword used inside game class points to the entire game class itself. It represents the object inside which it was defined. Nice because I put this code inside game class constructor when I create an instance of game class on line 31, it will also automatically create an instance of input handler class for me. It will save it as a dot input property on the main game class itself. I can confirm that input handler was created because I see this consologe here. Perfect. This is a simple way how you can connect your classes and make them work together to create a full game. It's also very modular, so you can later add more features and more classes to your game if you want. As we see with this consolo, all the code inside class constructor is automatically executed when an instance of that class is created. That code doesn't always have to be just defined in class properties. We can put any code in here. In this case I want to apply event listeners automatically. When an instance of input handle class is created, I will just put them in here. We will listen for the key down event in the callback function. I will run a consolo callback function on event listener in Javascript has access to autogenerated event object that contains all details about the event that just fired. I can assign it a variable name here, convention is usually a letter like this. I've done this before, so I know that this autogenerated event object has a property called key that gives us the name of the key that was pressed. I consolo key, I need to click on Canvas to make sure it's selected. And when I press anything on keyboard, the names of the keys are being printed in the console. Today we will focus on directional arrow keys. So arrow left, arrow right, arrow down, and arrow up. I want to save these key values inside last key property from line 28 on the main game object. We have a reference to the main game object here on line nine. But when I consolog this game from inside the event listener, we notice that the reference returns undefined. It's because this callback function forgets that it was initially defined here inside constructor method on input handler class. I want the function to remember, I want to bind its scope so that a reference to this keyword in this case representing this input handler object as well as access to this game property will be available from inside this callback function on key down event listener whenever that event listener runs Later on. I want to make sure this function never forgets that it was initially defined sitting inside an object. I can use Javascript bind method to do that, or I can simply use ES six arrow function. Es six arrow functions don't bind their own this, but they inherit the one from the parent scope. We call this lexical scoping. The scope of arrow function will always depend on where in our code base it was originally defined on its original lexical scope. In our case, it was defined here inside this constructor method. So it will always have access to this dot game property and any other properties we might define inside this constructor. Later on when I refactor this callback function to a narrow function, we are able to consolo did game. And we see that it points towards the main game object. And all its properties are visible there, Including last key, if I consolo last key value from line 28, initially it is set to undefined. We take the key property from event object and I assign it to it like this. Now, last key property on the main game class always keeps track of the last key that was pressed. I also need to know when the last key was released. I create another event listener, this time for key up event. Now we are storing the name of the last key that was pressed or released. The problem is that it just registers the key's name. I need to know if that key was pressed or released. I will concatenate capital letter P inside key down event to specify that the key of that name was pressed. I will then add capital R in front of the name of the key inside keyup event so that we know that key was released. Now we are getting these values in console, you can see the value of this dot gamet. Last key property is changing. We press arrow right here and we release arrow right here. I can remove the consol. Ok. Now that we know it's working on the main game object, we defined last key property and we created an instance of input handler class. As input handler class gets initialized, we apply a key down and key up event listeners. This will dynamically update that last key property so that our game object and all objects connected to it are always aware which key was pressed or released. We will use those values to control the player character, the Owl bear. Let's define it here. 42. Player character: First, we need to connect it to the main game object. We make sure it expects a reference to the game object as an argument insight, we convert it into a class property as usual. Let's start by giving it width and height of 100 pixels. Its initial position will be 200 pixels from the left edge and 200 pixels from the top. I give it a draw method to draw it on canvas. It will expect context as an argument to specify which canvas element we want to draw on. Take that context variable and I call built in Phil rectangle method on it. Phil rectangle expects x, y width and height. So I pass it properties from owl bear constructor. We want to draw a black rectangle representing the owl bear at first, same as we did with input handler class. I want to create an instance of Owl bear object automatically. When I create an instance of the main game class, I instantiated here inside class constructor and I assign it to a class property. I call this owl bear up on line 20, I can see that it expects game as an argument. I pass it this keyword because we are inside this game class. Game class will have a special method I call render to update and draw all game objects on canvas. I take oil bear from line 42 and I call its associated draw method from line 27. That method expects context as an argument, which is this CTX from line three. I need to pass it along. I will still call it context. It will be expected as an argument by the main render method, we pass it along to draw method on Owl Bear. I take a game, I call its render method from line 44, and I pass it CTX from line three as an argument that will get assigned a variable name context and passed along where needed. Perfect. We are drawing our Owl bear. It looks like a simple black square because that's what we defined here inside draw method on owl bear class. Let's make it move. I give it a custom update method for every animation frame. I want X to increase by one, making it walk to the right. We have to actually call that method from inside render on game class. Here I delete this consologe to actually see the movement. We need to be calling this update method over and over. Calling it from render just once on the first page load like we are doing here, won't animate anything. We will need animation loop. I create a custom function. I call for example animate inside. I put this render call. To make it loop, I call built in request animation frame method. This method will update our web page before the next repaint by running a code in a function, we pass it as an argument. If I pass it animate the name of its parent function, it will create an endless animation loop. Animate gets called. It calls render to draw and update our owl bear request. Animation frame will trigger animate again, so the cycle will repeat itself. Request animation frame sits on the window object representing the browser window. But it can also be called directly like this. Without putting window.in front of it. It's better to use request animation frame for animation than using set interval request. Animation frame adjusts frames per second to your screen refresh rate and it also auto generates a timestamp for us. We might need it later to trigger the animation. I just call animate Like this nice player is moving to the right, it's leaving trails. We need to make sure we delete all canvas drawings between each animation loop. I do that by calling clear rectangle built in method. I want to clear the entire canvas from coordinate 002, canvas width and canvas height. Now we have a moving black square representing the player character. Perfect. It's moving to the right because here inside update method on Alber class, which is our player, we are increasing horizontal x position by one for each animation frame. I give it a property I call speed X. Initially, I set it to zero. We will also need speed Y, vertical speed for up and down movement. Remember that we are building a keyboard controlled character that can walk in four directions. I will increase this dot x by the current value of speed x. Like this vertical y coordinate of the owl bear will be increasing by the value of speed Y. This is great because I can give it a positive value to move to the right, a negative value to move to the left. I can make it move faster by giving it a larger value per animation frame. Here this number means pixels per animation frame. Positive value in speed Y will make player move down. Negative value will make it move up. Positive value in both X and Y will make it move down, right? We could easily use this for eight directional movement. As you can see up here on line seven, we have Input handle class that captures keyboard input. It transforms the default key names to indicate whether the key was pressed or released. By pre pending or R in front of the actual name of the key. It saves the value of the last key that was pressed or released here on line 46. Inside this dot last key property on the main game class. Because I'm passing a reference to this entire game class when I create Alber on line 48. Alber object has access to last key value through this dot game reference here on line 21. I can say if this game do, last key is arrow left. If arrow left was pressed, set speed x to minus one to make the character move to the left in the negative direction on horizontal x axis. If I click canvas and I press left arrow key, we are moving perfect. When I release the key, the player doesn't stop up here. I can see we are capturing the value for press and release. I can say L, set speed x to zero, Now we can move left and we can stop. I could also create a set speed method that whenever it's called, it will set speed x and speed Y. These will be passed to it as arguments. We take those arguments and we update class properties from line 26.27 Now I can replace this line with this set speed. And I pass it minus one as speed x and zero as speed y. In the L statement, I set both horizontal and vertical speed to zero. It's better to have a global max speed variable rather than hard coding one and minus one here. In case that speed needs to be dynamic, player can have some temporary speed boost. Or maybe player is moving slower while crawling and prowling. To do that, we define max speed property. We set it to three pixels per animation frame, and we replace it here. Let's expand this statement. I will also check L if this dot dot last key is pressed R right, like this. In that case we set speed x to plus max speed speed y to zero. Now we can move left and right and we stop moving when the RO key is released. Perfect another L if block. Be careful about the syntax and the brackets. It's very easy to miss one bracket and break the entire code base while doing this. When we press R key, we call set speed. We set speed x to zero and speed Y to minus max speed because we want to be moving up in the negative direction on vertical Y axis. We do one more L if block if last key is press arrow down like this. We set speed x to zero and speed y to plus max speed. Also we can move left, right, up and down. I want to make sure that the player can't leave canvas. I need to set some horizontal boundaries. If players horizontal x position is less than zero, set it back to zero, that's the left boundary. Else if players horizontal position is more than this game with width of the game area, this game is coming from here. From there we are navigating to this property. On line 64, the player's current position is more than the width of the game minus the width of the player which we defined on line 22. Meaning that the right edge of player rectangle is touching the right edge of canvas. Make sure that player can't move further to the right anymore. Like this, I will increase player speed to ten pixels per animation frame. You can now move left and right to test the horizontal boundaries. Vertical boundaries will be slightly different because in our game world, the ground ends here. I don't want player to walk over this area unless it's a flying creature. I guess this owl bear is definitely too heavy to fly. I wonder if there are any rare flying owl bear species, We might look for them later in the series. We have this area on top where I don't want the player to be able to walk. I create a class property called top margin. Initially, I set it to 200 pixels. Let's put it here. Up here, we will define vertical boundaries. Say if this dot y is less than zero, y is equal to zero. This will create a boundary here. The player cannot go up past the top edge of canvas. I actually want the boundary to be lower because all of this environment art, I say zero plus this game doop margin like this. I can delete zero plus here. Of course now the top boundary is here, 200 pixels from the top edge. We can walk around, but we can't walk up here anymore. Perfect, it will make more visual sense when the player is an actual animated character, not just a black square, we are getting there fast. Bottom boundary is simple if players vertical Y position is more than height of the game minus height of the player. Meaning that the bottom of player rectangle is touching the bottom edge of canavas. Don't allow it to go any further down like this. Let's test it. Yes, we have all four boundaries. Perfect. Let's turn this simple black rectangle into animated four directional character spreadsheet. 43. 4 directional sprite sheets: I start by adding spreadsheet image into index HTML like this. We do it this way because all our Javascript is inside load event listener. If I place my spreadsheet here, Javascript will wait for these images to be fully loaded and available before it starts animating them. You can download all project art assets in the project resource section below. I gave it an idea of, let's bring it outside the wrapper like this. You can see we have eight animation rows in the spreadsheet, Four directions, and each direction has idle and walking loop. We will look into that further in a minute, will hide the image itself with CSS. We want to draw it with the Java script on canvas. You can see that all the code is inside load event listener. All this code inside will run only when Owl bear and all other images have been fully loaded down here inside constructor on Alber class which is our player control character. We will add a reference pointing to that spreadsheet image as a class property. I call it this image, and I set it equal to a variable called al bear. That variable was not declared by us, but all browsers automatically create references, autogenerated global variables to all elements with an ID. This element has an ID. So we know that our browser automatically generated a global variable for it. Normally, we would use get element by ID here on line 29, but we don't have to. The only problem is that this is a global variable. So that we are pulling global variables into our classes right now, that variable is in constant danger of being accidentally overwritten. Let's just test if it works. Anyway, I take context referring to CTX variable from line three. I call built in Canvas draw image method. Draw image expects at least three arguments. I pass it this auto generated global variable that was created from elements ID as the image we want to draw. And I pass it this dot x from line 24 and this dot y from line 25 to tell Java script where on canvas we want to draw the image. Now we are drawing the entire spread sheet at these x and y coordinates. We can move around using arrow keys. Because of the logic we wrote earlier, it's safer to use get element by ID here. So let's do it. I use this dot image here. Okay, that still works. Nice to animate any spread sheet, we need to know dimensions of a single animation frame within that spread sheet. I will put these into separate variables. I call the first one sprite width, and I set it to 200 pixels. Sprite height will also be 200 pixels. If you are using a different sprite sheet, you can calculate sprite width by taking the width of the entire sprite sheet and divided by the number of columns. Sprite height is the height of the entire sprite sheet image divided by the number of rows. In this case, width and height properties will be the same as sprite width and sprite height. But keeping them separate might be a good practice because we can then use scaling or randomize the sizes here without affecting these values that always need to stay the same. To correctly crop out individual frames from the sprite sheet draw image has three versions. The first version expects three arguments, we just did that here on line 35. The second version takes five arguments, optional fourth and fifth arguments defined width and height of the image and the image will be stretched or squeezed to fit these dimensions. Now I'm squeezing the entire massive spreadsheet into an area of 200 times 200 pixels. The third version of draw image method expects nine arguments to give us the most control over the image we want to draw. That's the version we need to use to animate our spreadsheet. These nine arguments are the image we want to draw. Source x, source Y, source width, and source height, the area we want to crop out from the source image. The last four arguments we call destination X, destination Y, destination width, and destination height. This will define where on canvas we want to draw that cropped out piece of image onto. Let's say I just want to crop out the top left corner frame. I'll be cropping from coordinate 00 to sprite width. And sprite height values we set to be exactly the same size as a single frame in our spreadsheet, in this case 200 times 200 pixels. Nice, we are using draw image method to crop out a single frame. I can multiply sprite width here by a number and sprite height here as well. Now I have a way to jump around the sprite sheet from frame to frame 00. Is this 1100? Is this 1200? Is this frame? This number navigates horizontally. This other number will determine which row in the sprite sheet we are on. You can see we can jump to a different animation row every time I change this number. I will put these values into Class Properties Frame X will handle horizontal sprite navigation. Frame Y will be for vertical sprite navigation. Again, when Frame X and Frame Y are 00, we are showing the top left frame. I can change these values to jump around the spreadsheet. Now that we understand how these arguments passed to draw image method crop out individual frames, we can actually animate our spread sheet and really bring this mighty owl bear to life. Let's start by just animating a single row for each animation frame. If frame X is less than max frame, in this case, max frame will be the number of frames per row, 30. If frame X is less than 30, keep increasing frame X by one L, meaning it is equal or more than 30, Reset frame X back to zero so that it can cycle again. Good, we are animating this row, because here we set frame Y to three. If I set it to zero, we are animating this row. Is I change this number, we are animating different rows. We want to swap these animation rows depending on two things. Which direction is the player walk in and is the player walking or just standing? If we had a complex character with multiple attack moves and so on, I would suggest to do a state design pattern here like I did in the endless runner class. In this case, the movement and animation logic is simple enough to be handled here inside the update method. We can always expand it to a state design pattern later if we decide to add more player moves. Let me show you, here we are setting player speed based on which of four arrow keys were pressed left, right, up or down. Let's copy this code block. Be very careful about brackets here, it's easy to miss one and break your code. If you remember up here we are keeping track of keys that were pressed and released. Pressed keys start with capital P, Released keys start with capital R. How do we do this? I think this should work. When we press left arrow key, we want to animate this row. This dot frame y is equal to three walking left animation row. When we release arrow left like this, we set frame y22. We want just standing idle to the left. Let's test it. I need to set speed to 00 when we release here. That's better when we press arrow, right? I want to animate walking, right, This row, this dot frame is five. I copy this LF, careful about brackets. We change to R here when we release arrow, right key. We set speed to 00. And we set frame Y24, Idle, right. Animation. Perfect. We have a character that can walk left and right, and the logic we just wrote correctly navigates around the spreadsheet. We are walking and we are standing. Player is animated and it is correctly reacting to keyboard inputs. Nice work. Let's also do it for vertical, up and down motion. When we press up arrow key, we want the player to walk away from the camera frame y seven. I copy this code block. When we release up arrow, we animate frame y six, and we set speed to 00. We can walk left, right up here. When we press arrow down, we want to animate frame Y one. I copy this code block. When we release arrow down, we animate frame Y zero and we set speed to zero. We are walking and animating in four directions. We are correctly swapping between standing and walking animation for each of these directions. Amazing work to create an idea of depth to make it feel like the player is walking away and towards the camera. When walking up and down, I will make it move a bit slower on that axis. Look how much difference it makes. It feels like there is more depth, like the background is further from the camera than the foreground. We walk at a normal speed, left, right? But up and down we walk a bit slower. Let's change max speed to five. This is a big, heavy creature. It should move slower. I comment out the black rectangle, we don't need it right now. I really like this. We have a base for so many different games. All you need now is your creative ideas. We can do so many different things with this. As you learn more about Java Script Canvas and game development, it will become easier and easier to actually turn those ideas into a working code base. Let me show you more. I hope you are getting some value today. Let me know in the comments if you learn something new because we are using only the last key that was pressed or released to control the player character. There is a common problem that when we walk in one direction, let's say I'm walking right, I press left arrow key. Player turns left and only then I release right arrow key. The last key is release right, Which will make the player stop briefly before continuous holding of the left key makes it walk left again. You can try and you find that we will have this problem in any direction, walk somewhere. And when you press a different directional key before releasing the previous one, it will make the player stop for a bit before it continues moving in that new direction. To fix this is easy. When we release arrow left. We want this code only to run if players speed is less than zero. Only stop the player and make it animate idle to the left if the current players speed is less than zero, if the player is currently moving to the left. That way we can enter idle left only from walking left state. When we release right arrow key, we only want to stop movement speed and animate idle, right? If player is currently moving right, if its speed x is more than zero. I also have to remove this L statement here. And now we fix the issue for left and right motion. Let's do the same thing for up and down motion. Only run this code when we release up arrow and at the same time players movement speed y is less than zero when we release arrow down. Only run this code if at the same time speed Y is more than zero. Only when the player is walking down towards the camera. Now we are moving around and the glitch is gone. Well done. 44. How to control FPS: If I set max speed to two player moves slowly, but the sprite animation serves frames so fast that the player is moon walking. The feet animate in a way that doesn't match movement speed and it looks very bad. One way to solve this is to manually control how fast the sprite sheet animates. Right now, we are just serving one new animation frame per loop. Every time request animation frame is called. Let's create a functionality where we can manually set FPS frames per second for the animation speed of our sprite sheet. It can be done globally and we can set FPS for the entire game. Or as I will show you now, you can set FPS individually for the player object. Maybe we will have some enemies later that will have different sprite sheets. And we might want those sprite sheets to be animated at different speed. By default request animation frame will adjust itself to screen refresh. Rate. Our game will run faster for someone with high refresh rate screens, like those new gaming screens, we can control that if we want to request animation frame has a special feature where it generates a time stamp every time it calls animate function and it passes that time stamp as an argument to that animate function it calls. Let's use it to count milliseconds between frames so that we can set our own FBS frames per second. I create a variable I call last time, it will sit outside animation loop like this. Initially I set it to zero. It will hold the value of timestamp from the previous animation loop. So that we can compare current and old time stamps and determine how many milliseconds passed in between. The value is called delta time. Delta time is the number of milliseconds that passed between the time stamp from this animation loop and the time stamp from the previous animation loop. To calculate delta time, we know we need to compare those timestamps. Timestamp from the previous loop will be held in last time variable here. Initially we set it to zero before we start generating timestamps. As I said, request animation frame passes autogenerated timestamp argument to the function it calls. If you are a beginner, imagine that it's being generated and passed here like this. At the point when request animation frame triggers that function, we assign that autogenerated timestamp a variable name. Here, I will just call it timestamp spelled with a capital S. Let's comment this out and consoloc timestamp. Just so that I can see what format we are getting, You can see that it's milliseconds. The first value is literally the number of seconds since the loop started, 45678. This is the time stamp I delete. The consolo delta time is the time stamp from this animation loop minus last time from line 113, which will always hold a value for time stamp from the previous animation loop. Once we calculated delta time, we set last time to time stamp. So that this new time stamp from this loop can be used as old timestamp value in the next following animation loop. Now we have delta time. It tells us how many milliseconds it takes for our computer to serve one animation frame. My screen refreshes at around 60 frames per second. My delta time is around 16.6 milliseconds. This is perfect. Are you getting the same delta time or are you getting a completely different value? Let me know in a comment. It will depend on the refresh rate of your screen and partially also on the power of your machine. Weaker machines will have higher delta time. You can see that here the first delta time values are none, not a number. Because we first run animate here in the first loop, this time stamp is undefined. There was no previous request animation frame call to auto generated. For us to fix this, I need to make sure I pass it that first time stamp here just to avoid non, not a number value in the initial loop. Otherwise it might give us problems later depending on how you want to use your delta time values. Initial time stamp will be zero. You can see the values are all over the place at first, but then they quickly settle at around 16.6 as our animation loop runs over and over. This is ideal. I delete the consol, I pass this delta time value to render method on game class. I make sure that value is expected here and I can pass it along anywhere around our game. Now wherever we need it. I pass it to update method on Alber class because we want to use delta time to control FPS frames per second of sprite animation. There I'm passing delta time to update method and I need to make sure it's expected. Here on line 44 we are inside Alber class now and we can use delta time value here for so many different things. To control FPS of sprite animation, I will create three helper variables, class properties, FPS will be 30. Let's try to animate 30 frames per second and see what that looks like. Frame interval will be 1,000 milliseconds divided by 30. This will determine how many milliseconds should pass before we swap to the next frame in the sprite sheet. Frame timer will be the counter. It will be accumulating delta time over and over as our animation loop runs. When it reaches the value and frame interval, when enough milliseconds have accumulated, we trigger certain periodic action. In this case, we will serve the next animation frame. Same technique can also be used to add a new enemy to the game or some other event that you want to be happening in a specific interval. This is an important technique to understand. Let's write the logic and explain it when we see the code. It's just a few short lines. I only want to run this code that swaps between sprite frames when enough milliseconds passed. If frame timer is more than frame interval, only then animate the sprite sheet. Else keep increasing frame timer by delta time. This code will animate spreadsheet from here. When this triggers, we also reset frame timer back to zero so that it can count again towards the next periodic event inside animation loop, we are calculating delta time, the difference between time stamp from the current and the previous animation loop. Delta time is the amount of milliseconds it takes our computer to serve one animation frame. Frame timer starts at zero and it adds more and more delta time as animation loop runs until it is more than frame interval. Frame interval is the breakpoint that when reached, it triggers our periodic event. When we reach it, we handle sprite animation and we reset frame timer back to zero so that it can count again towards the next periodically served animation frame. I know this was a lot, but this technique is very important. It will become easy to understand when you use it more often. Trust me now, the character is animating slower, just the sprite swapping and not the actual movement speed over canvas. You can really see that when I set FPS to two frames per second, it still slides over canvas smoothly at 60 FPS. But we are throttling how fast the next frames in sprite sheets are served. Hope this makes the difference clear. I can try other values as FPS. I have to experiment a bit here and find the right value that will make the lex move at the speed that feels natural as the player moves over the grass terrain. 50 is still some sliding. 60, we are actually not accounting for leftover values of delta time every time we trigger our periodic event. Even though I said FPS 60, the real FPS would be less than that. For the purposes of a project like this, it's perfectly fine. We have a value we can increase and decrease to control sprite animation. It serves its purpose well. I can simplify this line of code and use ternary operator to write all of this on a single line. Let me show you it's easy. Ternary operator is the only Java Script operator with three operands. We will use it as a simple one line if L statement we have condition to evaluate. We check if frame X is less than max frame. If it is question mark, increase frame X by one, L reset frame X back to zero. Now this single line of code does the same thing as this multi line L if statement. You can use either syntax. I just wanted to show you. 45. Randomly positioned game objects: Let's create some objects and spread them randomly around the game world. I create a class, I call object. As usual, it will expect a reference to the main game object from line 111 as an argument that we have access to all important properties. From there we convert that reference to a class property. Same as we did before. Draw method, we'll expect context as an argument. Inside we call built in draw image method. I want to show you how to extend classes and take advantage of inheritance, which is one of the main principles of object oriented programming. How we can use it to reduce code repetition. I create a class called Busch that extends object class from line 102. It will have a constructor as well. I create another class. I call plant one more, I call grass. We have the main object class. We have three classes, Bush, plant and Grass that extend that object class. Object is so called parent class, also called a superclass. Bush, Plant and Grass are child classes, also called sub classes. If I use a property or a method inside one of these child classes, that property is not defined on that subclass. Java script will go look for it automatically on its parent class, on object. That way, I can only define this draw method at once. And all child classes that extend this parent class will automatically have access to it, they inherit that method. We can do something similar with properties inside constructor using super keyword I will show you in a minute. Object class will hold all properties and methods shared between all child classes. Busch, Plant, and Grass will contain properties that are specific only for that particular subclass. For example, each subclass will have a different image, but all will pass that different image to the same draw method from 907. Let's do it. Before I can use this keyword inside child class constructor need to trigger constructor on its parent class. When I say super like this here, it means I want to run a constructor of this class's parent. Parent class is also called a superclass. On line hundred three, I can see that object class constructor expects game as an argument. I pass this reference along at the same time I convert it to a class property on Bush class as well. Like this inside the shared draw image method I pass it did image didot x and dis.yi can also give it dist width and distot height. If I want to scale the images as you can see, none of these are present on this class. I want each subclass to have a different image, and we need to know size of that image to calculate its randomized position. I will have to put all these properties on each subclass separately. Let's start with Bush. This dot image will be document dot get element by ID. Here in index HTML, I need to create that image element as usual, you can download the images in the project resources section below. I put it here, ID will be Bush, another one with an ID of plant like this. The last one will be grass in style CSS. I use their IDs to hide these images. We want to draw them on canvas, not as actual image elements on the web page. The ID is bush. I duplicate this code ID. Here will be planned and here grass. I'm trying to keep the naming simple and clean. I don't really want to scale the images, but if we want to leave the option for scaling open, maybe it's better if I define image width and image hide properties separately. Even though at this point they will have the same value. I already size the images to be the same size as we will draw them on Canvas, which is a good practice. Bush image is 216 100 pixels. I could also define these properties on one line like this. It's up to you. Horizontal position will be a random value between zero and the width of the game area minus the width of the image itself. This will probably need some adjustments. Let's see, Vertical y position will not start from zero, it will start from top margin. And from there a random value between zero and game area height minus the height of the image minus top margin. I think when we start drawing them, we will see if I need to make any adjustments here. Let's test it. On the main game class, I create a property called Number of Plants. Let's create ten randomly positioned plant objects. I create initialized method that will run only once on the first page load and it will randomly position the objects inside. I create a four loop. It will run ten times. Every time it runs, we create one plant. I create an empty array here that will hold all the plant objects. Every time the four loop runs, I take this plants array, I, new Bush object inside on line 111, I can see that Bush class constructor expects game as an argument. I pass it this keyword because we are inside that game class here. After I create an instance of game class 160, I can call this init method. It will run and it will fill plants array with ten randomized instances of Bush class. If I want to display them on canvas, I need to call their draw method. I will do it from inside render. I take plants and for each plant object inside the array, I call their associated draw method from line 106. That method expects context. I pass it along this context reference. Nice, I'm drawing ten randomly positioned bushes. I go up here, I will copy all these properties that are specific for Bush class, and I copy them here inside plant class. I check the image width is 212 pixels, height is 118. I copy it again, and grass width will be 103 and height will be 183 pixels. Nice, We defined a parent object class where we can place all shared properties and methods, and three subclasses called Bush Plant and Grass that extend the parent class. To quickly check if these classes work, I can just swap the class name here on line 168. Grass is working, Plant is working. How do we randomize them and control which portion of these ten randomly generated plants will be bush, grass or plant objects. One simple way to do it is to create a variable. Here I call for example, randomize. It will be equal to mathodtrandom. We know that methot random code like this on its own return a random value 0-1 Let's say I want roughly 30% of these objects to be instances of plant class. I say if random Ize is less than 0.3 L, if randomize is less than 0.6 when math at random rolls between 0.3 and 0.6 we create an instance of Bush class L, meaning when Maat random rolls between 0.6 and one, we create grass. It doesn't work because this has to be inside the four loop because we want to roll each time we create a new object, not just roll once for all ten objects. 46. Layering and draw order in 2D games: Perfect. We are extending a class to create three different randomly positioned game objects. Nice work. As you can see, the way these objects are being positioned and the way the game is layering doesn't really make much visual sense. Owl bear is drawn first on line 162 and then all plants are drawn after plants will always be on top of a bear. If I swap this around, then plants are always behind the bear. Since we are drawing everything on the same canvas element, whatever gets drawn first is behind, and whatever was drawn after is on top in front of it. I want to draw objects in a specific order based on their vertical positions. More specifically, based on the vertical position of their bottom edge. Because each object has a different height to make sure they are aligned in a way that makes logical and visual sense. And so that our character can walk around them and be in front and behind the objects. When appropriate, we are trying to simulate a virtual world where plants grow from the ground. And where this owl bear is walking on solid ground at all times, even when it walks up and down. The layering has to match that visually. It's actually very easy to achieve this. I just need to make sure that all these objects, so al bear and all plant objects, are in the same array. So that I can sort them based on their vertical position. I create another array called this game objects. Every time render method runs, I put Alber object inside. I spread all objects from the tot plants into this array spread operator. Used like this allows us to expand one array into another one. In this case, it doesn't make much sense to do this every time render method ticks for every animation frame. Since we have just Alber and ten static plants, we could have done this inside init method. It would just make sense to do this periodically to construct this array over and over. If we have more objects that are being added and removed over and over, for example enemies or power ups that come and go. Now we have alber, all ten plants on the same level inside the same array. I can take this array for each object in game object array. I call their draw method. When we do this and we combine different object types into a single array, we need to make sure all these objects actually have draw methods defined in their classes. Be careful about brackets Here I can delete this code. I will have to call update method and pass it delta time. Otherwise, I will bear, will not move or animate. When I call update like this, we draw and update all bear. When I try to draw and update the first out of ten plants, it gets drawn, but there's no update method to run, so we get an error. I need to add update method on object class for this code to run. We are not really updating the objects, but here we can have some animations. For example, bushes and grass can move when the player touches them, that code would be handled inside this update method. I will leave it blank for now. Now we have the same thing we had before, but all elements that need to be layered dynamically are being drawn and updated from inside game object array. All bear is first in the array. That's why it gets drawn before plants. Plants are drawn on top of it. If I swap them around, plants are behind and aulber is drawn last on top. Because that's the order in which for each method cycles through game object array. To call their draw methods, we want to sort Alber and all ten plants in this array based on their vertical y coordinate, but not based on their top but on their bottom boundary. Because we have objects with different heights, we can do this using built in array sort method. The sort method sorts the elements of an array in place and returns the reference to the same array. Now sorted, it takes an optional argument. We call a compare function, where we can define logic that describes the sort order. If we don't define sort condition, by default all array elements are just converted to strings and sorted based on characters, Unicode values. A is the first element for comparison, B represents the second element For comparison, sort method will automatically compare every element in the array against every other element. To sort them based on our requirements. We want the sort condition to compare the bottom boundary of each element drawn on canvas. So it's vertical y position plus its height. Like this. I'm saying sort all elements in ascending order based on their vertical position plus their height. Once the array gets sorted, we draw plants and owl bear in that order on canvas. And now everything makes visual sense. We can walk around obstacles and we can see that the player character and plants are now always correctly drawn in front or behind. You can expand this game in many different ways, create mushrooms that grow in playable area to make the owl bear grow as it eats them. Or you can make it avoid dangerous enemies or walk around spiky obstacles. I suggest you create a copy of this code base and you can use it as a base for different gameplay experiments.