Introduction To Javascript Game Development: Part 1 | Chris Dixon | Skillshare

Playback Speed


1.0x


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

Introduction To Javascript Game Development: Part 1

teacher avatar Chris Dixon, Web Developer & Online Teacher

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.

      1 Introduction

      2:12

    • 2.

      Share Your Work On Skillshare!

      1:09

    • 3.

      Setting Up The HTML Canvas

      6:37

    • 4.

      Grids & Co-Ordinates

      1:27

    • 5.

      Drawing On The Canvas

      10:48

    • 6.

      Text, Lines & Paths

      8:32

    • 7.

      Looping

      8:21

    • 8.

      Moving Objects With The Keyboard

      5:32

    • 9.

      Detecting Collisions & Bouncing

      10:24

    • 10.

      Paddle Contact

      9:05

    • 11.

      Tracking Scores

      3:33

    • 12.

      Ending The Game

      7:38

    • 13.

      Starting & Re-Starting The Game

      8:41

    • 14.

      Random Direction

      6:17

    • 15.

      Computer Movement

      3:54

    • 16.

      Random Bouncing

      6:26

    • 17.

      Keeping The Paddle On The Canvas

      2:52

    • 18.

      Final Thoughts

      0:31

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

384

Students

4

Projects

About This Class

Free canvas reference sheet to download:

https://github.com/chrisdixon161/HTML5-Canvas-Quick-Reference

Project stages for comparison:

https://github.com/chrisdixon161/Introduction-To-Javascript-Game-Development-Course-Part-1

If you have ever wondered how to build simple 2d games which work in the browser, then this class is going to be exactly what you are looking for!


Since Javascript is built into all major browsers, it is perfect for building browser-based games, and during this class, we will build a simple pong-style game to learn what you need to know.

Beginning with the HTML5 Canvas. This element is used to draw inside the browser, including images, shapes, text, and animations. Making it perfect for 2d games. If you have not used it before, we look at everything you need to know to draw, including how the grid system works.

Along with this, we also look at:

  • Text, Lines & Paths
  • Co-ordinates
  • Math calculations
  • Looping
  • Moving objects with the keyboard
  • Detecting collisions and bouncing off the walls and paddles
  • Keeping track. of scores
  • Starting and ending the game
  • Adding randomness to the bouncing to make the game less predictable
  • Computer movement
  • Restricting movement on the canvas

All of this combines into a 2d game covering all of the essentials you need to build more games on your own.

The class is beginner-friendly and I try to explain everything as we go, however a little Javascript experience will really help your understanding and experience. I also have classes on this subject if required.

Looking forward to seeing you in the first lesson!

Meet Your Teacher

Teacher Profile Image

Chris Dixon

Web Developer & Online Teacher

Teacher

Hello, My name is Chris and I am a Web Developer from the UK. I am an experienced trainer leading web development bootcamps and also teaching online courses.

My main areas of interest are Vue.js, Nuxt.js, Shopify, JavaScript, eCommerce, and business. I am passionate about what I do and about teaching others.

Whatever your reason for learning to build websites you have made an excellent career choice.

My personal motivation was to become my own boss and have more freedom and flexibility in my life. I also enjoy the technical challenge it provides and the way it constantly evolves. I built my first website back in 1999 and I have watched the web evolve into what it is today.

I try to make my courses enjoyable and try to remember what it was like when I was lea... 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. 1 Introduction: You've ever wondered how to build simple 2D games that work inside the browser, then this class is designed for you. Since JavaScript is built into all major browsers, it's perfect for building browser-based games. This class will teach you all the concepts which you need to know while building a Pong-style game, put everything into practice. This class isn't designed to go too deep or if you do have some existing JavaScript knowledge, it will really help you as you progress. We'll try to cover all of the main concepts which you need to build basic 2D games work inside the browser, and for this, we begin by setting up the HTML Canvas. The Canvas is an ideal way to draw inside the browser. It's perfect for drawing our game area, things like the ball, the puddles. We can also use JavaScript to move these on the Canvas too. But working with a Canvas though, we do need a little bit of background knowledge on the grid system. That's all covered in this class too. But don't worry, it's really easy to pick up. We'll take a look at all of the basic drawing functions such as how to draw text, how to lines, how to draw squares and rectangles, circles, and how we can also apply looping so we can repeat processes that make a really smooth game. We'll take a look at also how we can interact with our game and move objects by using the keyboard. Of course, what kind of game of Pong would be complete? We didn't handle the ball bouncing off various items. The ball needs to bounce off all the sides of our game. We need to crack a score if it hits one particular side. We need bounce off the moving paddles. All of this is covered inside this class. You don't need any additional tools or to make any purchases for this class. All we need is a web browser and a free text editor. If this sounds like something which excites you and you want to learn about, jump into the class and I'll see you in the first lesson where we'll begin by setting up the HTML Canvas. 2. Share Your Work On Skillshare!: When taking any course, it's really important to not get in the habit of following along just for the sake of ticking off another lecture. Take the time to process each lesson, review the code which you write, and think about how you might approach these solutions yourself. With this in mind, this class is project-based, and this gives you the opportunity to really make something personal and unique. You don't need to get too lost and diverted away from the class, and you can even take a step back after you've finished the class and come back and make some project changes afterwards. This will really give you a good chance to practice what you've learned away from the class. Also, remember to share your project too here on Skillshare and only will I check it out, but it will also inspire fellow students too. For more information on the class project, head into the Project and Resources tab where you can not only upload your project, but you can also see other class projects too. With this in mind, I look forward to seeing what you create and upload here on Skillshare. 3. Setting Up The HTML Canvas: Since we are creating a 2D game, we need a way to create various shapes and various elements and place these onto the screen. To do this, we'll be making heavy use of the HTML5 canvas. Canvas is just an HTML element just like a div or even an image. It has an opening and closing tag, and on its own it doesn't actually do anything. But once we have this in place, we can make use of the canvas API to draw graphics. We can also do much more to for overuse cases such as photo manipulation by changing the pixels and animations, to name a few. This course will be more focused on a 2D graphics. A lot of other APIs and libraries are also available to handle 3D features. To access these 2D features, the canvas API has an interface available called canvasRenderingContext2D. This is not something you need to memorize. But just know this is why we have access to the 2D drawing features on the canvas using JavaScript. Here, you can see a selection of some of the properties and methods we have access to which will allow us to draw on the canvas. You'll see some more of these during the course. Let's now go into the text editor and set things up with a new project. First things first, we need a new project folder to store all of our files inside of. Let me call this game, anything you want to but I want to call this one game and hit, "Enter." Open up Visual Studio Code. If you prefer, you can use a different editor if you want to. Drag this over. Then we need two new files to get started. The first one you can either click on the New File icon just here, this will create a new file. I'm going to call this the index.html. The second file we need is going to be for our script, the script.js. This is going to handle all of our drawing functions in our game code. Let's start over in our index.html. Inside here, Visual Studio Code has a handy shortcut called html:5, which will give us all of our basic HTML structure. The title are the same. We don't need much content inside of the body section but the first thing we need is the canvas. As mentioned before, the canvas has the opening and the closing tags. If we save this and open this up inside the browser, you won't see any content just yet on the screen. If we copy the path index page, paste this in, you don't see any content inside the browser. To actually see the canvas, we need to draw things inside of our JavaScript file or we can also add some styling inside of here to make our canvas more visible. On the style, then all we want to do inside here is to grab our canvas, set a background color to make this more visible. You can make this any color you want to but I'm going to go for an rgb value. The red of 61 and 59 for the green and the blue. This will give us this darker background color. We can now see the canvas inside the browser. You can see by default that it's a pretty small canvas. By default, the canvas will be rendered as 300 pixels wide and 150 pixels tall. We can override this inside of our script. To make this in the center, we can do this just like we would do with other regular HTML elements. First, set the display type to be the value of block. Then we can set the margin to be zero on the top and bottom and then auto on the left and right. Save and Refresh, and this will now appear inside the center because I've automatically divided up the space on the left and right. The final thing to do inside of our index page, just below the canvas is the link our script file. Placing the source which points to our script.js. Then we can move into this file to add some content. The first thing we need to do inside of here is to actually grab our canvas element. We do this just like we would do with any other HTML element. We have access to our elements using things like querySelector, getElementByID, getElementByClassName, and we can store this inside of a constant called canvas. For this access, the full document, I'm going to use querySelector passing in our canvas element. Now this stores our reference to our elements inside of this variable or constant. We can now access this just below. Starting by overriding this default, 150 by 300 pixels size. Grab our canvas. We can set the width of this element to be any value which you want. Let's say 800. Next, the height of 400. This should now update inside the browser. The last thing we need to do inside of this file is to access the canvases 2D drawing functions with getContext. We can store this inside of a constant called ctx, grab our canvas elements, and then call a method called getContext. Passing in a string of 2D to give us access to the 2D drawing features. The constant name of ctx is up to us but this is a common naming convention to access the rendering context, and this constant can now be used to draw to the canvas when we need to. We will use this plenty throughout this course. This canvas is now ready for us to draw too. But just before we do this, in the upcoming video we're going to take a look at how we can work with grids and coordinates, which will really help us understand the placements of our objects onto the canvas. 4. Grids & Co-Ordinates: We're not going to get too far withdrawn to the Canvas, if we first don't understand some basic coordinates. You may already understand some of these, and we don't need to go too deep, but if not, we're now going to take a quick recap. When we draw it to the Canvas, or in fact, most 2D grid systems, we have two directions we need to know. This is the x and the y-axis, x is horizontal from left to right, and y is vertical from top to bottom. Meaning if you wanted to locate the top left corner of this grid, x and y, will both be zero, but what about something like this square of many shapes like this? Although, it takes up multiple grid spaces, the starting location is the top-left. This is where we have this red dot. Again from the starting top-left of this grid, we'll go across three spaces on the x-axis and down two spaces on the y-axis, which gives us our starting position. After this, once we have our starting position in the corner, we can then set the height and the width of any shape which you want to. This is all you really need to know to get started. We can then set the size of the graphics and do other things when we create them too. This is what we're going to have coming up next. 5. Drawing On The Canvas: To help with drawing to the canvas, I've created a download for you to use during this course and also in the future. All you need to do is go to this link which you can see on the screen, download the PDF, and keep this in a safe place. Now let's jump into our script and take a look at how we can use some of these. In the coordinates video previously, we looked at an example of drawing a square. Let's begin with this. Also note, the squares and rectangles use the same drawing method. We just changed the width or the height values To draw a rectangle or a square using the canvas, what we need to do is to first access our context variable, so ctx, and this has a method available called fillRect. This will fill a rectangle with a solid color or even something like a gradient. We're going to parse into year 4 different values. Just like we looked at with the coordinates video previously, the first two values is the location where we want to place this rectangle. Since this is based on the top left of the rectangle or square, I want to begin this example by showing this up in the top left. The top left will be x, 0 and y, 0. Then we parse in the width and the height which we want the shape to be. To make this a square, we can parse in some even values like 100. This will place a 100 by 100 pixels square in the top left of our canvas. We can also push this across the x-axis or the y-axis, any value which we want to. If we change the y-axis to be 50, this will push this further down the canvas. As well as the fillRect method, we can also change this to be stroke, so strokeRect. Rather than filling a solid color just like we're seeing, stroke will place an outline around the shape. This will give us a outline of a rectangle or a square. For most things we draw to the canvas, will have a stroke or a fill alternative. I'm just going to change this back to be fill. We can also create a rectangle by changing either the height or the width. If we change this to be 200, for example, this will give us a rectangle. By default, we'll have this solid black color. We can change this by accessing a property on this context called fillStyle, just above fillRect, again, access our context like we'll do with all of these drawing features. We can access the property called fillStyle. FillStyle is going to be equal to a string and set this equal to a color such as red. If we refresh the browser, this will now update the background color. If we were using the strokeRect instead of fill just like we've seen before, to do the outline, we'd also need to update this to be strokeStyle to match. This will change the outline color to be red. Let's just undo these two changes and leave as the fill. As you would expect, these rectangles will be useful inside of our game. We could use them to draw the player and also the computer's paddle, which is going to be used to hit the ball. Let's give this a go starting with the players paddle over on the left. To begin, since we have a 400 pixels height canvas, we can start by placing this in the center by changing the y-value to be 200. The width of the canvas, let's set this to be a value of eight and the height of 80. Refresh. You would expect the paddle to be in the middle since we've set this y-value to be 200, which is half of the height. But as we've already learned, the starting position of the x and the y coordinates is in the top left position of our shape, meaning that the top of the shape is in the center of the canvas rather than the center of our rectangle. This is where we need to start thinking about things more carefully. For the paddle to be correctly in the center of the canvas, we need to now deduct a half of the height of the paddle. Since we know the height of the paddle is 80 pixels, we could deduct 40 from the starting position. This works, but a better option would be to change these values to make use of variables. The variables would then be used to perform this calculation for us, and it would also be useful in the future if we were to change any of these values. Just both, we can create some variables. The first one is the paddle width using the same values, so the width of eight pixels. Then the second one is for the paddle height. The paddle height is 80 pixels, just like we already have. Then we can make use of these in our fillRect method. The paddle width, also the height, and this should still work exactly the same. But now instead of hard-coding this value of 160, what we're now going to do is to calculate this using JavaScript. We can grab the canvas height, which is currently 400 pixels, divide this by two to get the center which currently gives us the value of 200. But as we know, 200 will not place this into the center of the canvas. We also need to deduct half of the paddle height, so canvas.height divided by 2. I will also take away the paddle height divided by two. What we have here is exactly the same as before. We have the value of 200, takeaway 40. This is just the same as before but using variables. Save and refresh. Now, for the computer's paddle, which is going to be over on the right, and this should all look pretty similar, all we need to do is to change the x position to be over on the right. We can change the fillStyle to be a different color too. Moving down, all the code from now will have a different color by changing the fillStyle. Let's go for blue. Then we use ctx.fillRect. As mentioned, the only difference between the players paddle and the computer's paddle is we want to push this over to the right-hand side. The players paddle has the x starting location of zero, which is over on the left. What we want to do for the computer's version is to place this over on the right by accessing the canvas.width, which is currently equal to 800. But since this starting position is based off the top left of the rectangle, this would actually push this off the edge of the canvas. What we need to do is to bring this back on by deducting the paddle width. The last three values are exactly the same as above. This is going to start in the center. We can use this, and the width and the height of the paddle has also been set too. Grab all three of these, add these in just after the comma, leaving us with two paddles now in place on the screen. The next thing we need to draw is a ball. You may be expecting a method called fillCircle or something along those lines. But for circles, we use a method called arc. Again, on the context, call the arc method. This is used for creating an arc or a curve. We can form a circle by rotating this curve all the way around back to the starting position. Unlike a rectangle, since an arc is curved, the shape doesn't have a top corner to locate it. Instead, we locate it by the center. To place it in the middle of the canvas, we could do something like this. We could access the canvas.width divide by 2. This is placing this in the center of the x-axis. Then also the same for the height. We're not finished yet though. Next comes the circle radius, which is the dimension from the center of the circle to the very outer edge. Basically, half the width of the circle. Let's place it in as 50, separated by a comma. The next value in a clockwise direction is the start and the end angle. To effectively start this vertically at 12:00 o'clock, we start with the position of zero. For the end position to rotate this all the way around and create a circle, we need to rotate this by 360 degrees. But when using the arc method, this rotation is in radians, not degrees. The equivalent of 360 degrees in radians is 2 times math.Pi. This is how we can do this using JavaScript. Now, if we save this and refresh the browser, we're currently don't see any circle on the canvas. We don't see our circle on the Canvas just yet, because first we need to declare if we want this circle to be a fill or a stroke. We can do this with ctx.fill. This is a method, so we need the brackets just afterwards. Refresh. This will now fill our circle with a solid background color. As you'd expect, we could also use the stroke method to give us the outline of our circle. I'm going to keep this as fill. Also change the fill color just above using fillStyle and set this equal to gray. Since 2 times math.Pi is a full circle, you can probably guess that half of this value is a half circle, so rather than timesing it by two, we can just say math.Pi. This will be a half circle. Again, if you want this to be a line, you could change this to be stroke. You could also reduce or increase the value of math.Pi. If we divided the value of math.Pi by 2, this will then give us a quarter of a circle. As you can imagine, this arc is a pretty versatile method. But since we need a ball, I'm going to reinstate this to be 2 times math.Pi, just like we had before. We can also change this to be a fill color, and also a smaller ball radius of 10 pixels. This is just a first basic look at drawing to the canvas. As you would expect, there is a lot more to learn, and many more things you can do. We'll begin to look at some of these in the upcoming video. 6. Text, Lines & Paths: Continuing on from the previous video, we're now going to discover some more techniques we can use to draw to the Canvas, to draw some lines and also some text. This is going to be really handy for our game. I will begin with drawing texts to the Canvas which is going to be used to draw the user's score and to also prompt the user to begin the game. The draw texts on the Canvas we have both a stroke texts, but an outline, and the fillText, or a solid color. Let's start at the very bottom of our script. Access the context and we'll begin with fillText. For fillText, the first thing we need to add is a string, which is the text which we want to display, so hey, followed by the x and the y positions where we want to place this. Let's go for 150. Save and refresh. We can just about see this small text on the Canvas but it's really hard to see because the default size is 10 pixels with a sans serif font. But we can of course change this in our JavaScript. First of all, let's change the fillStyle to be equal to any color such as red and also to change the size and also the font family. We can access ctx or font. Set this equal to a string. This takes in the exact same syntax as we would do with the CSS on property so we can pass in a string of the pixel size. Let's go for 30 and then the font family of Helvetica. Refresh and this takes effect. What would be nice to have is the player's score displaying on both sides of the Canvas. If we had the player's score in the middle of the left half and the computer score on the middle of the right half. To simulate this for the player's score, we effectively need to push us in a quarter of the width of the Canvas. To simulate a score we can just place in any value inside of here, such as three, and then pushes over a quarter of the width. We can first grab the Canvas, that width and divide this by 4. The computer score, this needs to be three-quarters of the way across the Canvas and we can duplicate this. Change the score for now. But rather than dividing the Canvas by 4, we're going to multiply this by 0.75, pushing our text three-quarters of the way across the Canvas. Finally, we can also store these two values into variables so we can access them and use them later in the course. Back to the top, using LET so we can update these as the game is progressing. The first variable is the player's score. We have an initial value of 0, followed by our computer score. These variables can now be used inside of our fillText method. Remove the hard-coded value, and this is the player's score. The second one is the computer score. Something else that Canvas gives us is the ability to draw using lines. We have two useful methods available called move tool and line tool. Let's take a look at these. Ctx.moveTo and ctx.lineTo. The first one of move to is used to move to the starting position and then line to is what actually draw a line on the Canvas to the end position which we set. Move to is like lifting the pen off some paper and moving it to a certain position. Line to is used to actually draw the line. What I'm going to use this for is to draw a center line vertically on the Canvas and also the center circle too. First, let's start with this vertical line and we need to first move the position of the pen to be in the center of the Canvas and at the top. The values for this, first of all, for x is half of the width of the Canvas and the y position is 0, since we want to keep this at the very top. Move dependent to be in this position just here. Now, we need to use the line to method. Actually draw a line to the end location, which is at the bottom, passing in the end location so this is still in the center of the Canvas so we can grab Canvas width divided by 2 and the final y position is down at the bottom. This is the Canvas.height. This will then set where we want to draw our line to but actually places on the Canvas, we need to use the stroke method, so ctx.stroke and there's a line from the top to the bottom. This is really good, but if we look closely, we also have an additional unwanted line around this ball. This happens because at the moment we don't have any separation between all of these Canvas paths and the graphics which we've created. For example, just above, we've drawn a circle using the film method. We've drawn this, as you'd expect with this gray color, but then the code keeps running all the way down and it also draws the same circle using the stroke method too. This is why the ball has a fill and also an outline from the stroke to. When this happens, we can separate each one of these sections by using a method called begin path. We'll call this just above our line section with ctx.beginpath. Begin path will effectively clear out all of the existing paths above and start a fresh from this line. Save and refresh and now our line has been removed from the circle, leaving only the vertical line which we intended as well as this solid line. We can also change this to be a dashed line too. We can do this just before we draw our line with ctx.setlinedash. Set line dash is a method which takes in an array inside of this JavaScript array, we set the size so both the dashes and also the gaps between each one of them. If we did something like this, 10, 10, 20, 20, and 30, this will set all the values for our dashes and spaces so we have the size of the first dash, the size of the first space, the size of the second dash, the size of the second space, and then the size of the third dash and then it will repeat until the end of the line. Ten pixels for the first line and then 10 pixels for the first gap and then we move on to 20 and then 30. To keep this simple, I'm just going to pass in one single value of 6 and this will make sure that each one of our spaces and also our dashes is in equal value. The last thing to draw is going to be a center circle. We know how to draw a circle using the arc method. But this time we'll also set a dashed line right down to the very bottom and we'll begin a new section with ctx.beginpath. For our circle, ctx.arc. Just like our starting ball position, we need to place this into the middle of the Canvas with Canvas.width divided by 2 and also the same for the height to. Grab this, paste these in. The third value is the radius and since we have a ball of 10, let's make this a value of 20. For the circle, the starting position is 0 and a full circle is 2 times math.pi. Actually draw the circle you need to call the stroke method leaving our center circle now in place on the canvas. This is most of what we need for our games at drawing functions and the great part about using variables like this is in the future we can update these values to move our objects on the Canvas. 7. Looping: Looping is going to be a really important part of moving things inside of our game. If you think about it at present, we are currently drawn things like a ball and also the pedals onto the screen. But what we need to do is to update these values to move these into a different direction, and then we need to continuously redraw and repeat this using a loop. This is what we're going to take a look at now. Down at the bottom of our script, the first thing to do is to create a function which you want to repeatedly call loop. You can give this any name of your choice, I'm going to stick with loop this one. The purpose of this function is to repeatedly draw autographics such as the ball and paddles after they move position. To call it, we can use a JavaScript method called setInterval. SetInterval will repeat our loop function after a number of milliseconds. We call this at the very bottom, this is going to take in two things, the first thing is the thing which we want to repeat, and in our case it's our loop function. We'll pass this in, followed by a time delay in milliseconds. Let's set this currently to 15, and you can increase this for the slower game and reduce this for a faster game. This loop function will eventually repeat many parts of our code which we have above, but for now let's place in a simple console log so we can check this is working. So any text inside of here, give this a save, and now we can go into the console and check our setInterval is calling our function, inspect, jump into the console, and now if we refresh, we can see this is called every 15 milliseconds. Let's start off by replacing this console log with our ball. To draw our ball we could cut and paste the code which we use to draw our ball which is the ctx.arc method. Or instead, we could wrap this in a function and call this directly. Just above this will create a new function called drawBall. This is going to wrap all of our code just below. Open up the curly brackets just like this, and then we can cut and paste and move this directly inside of our function. Now, we can call our drawBall function from inside of our loop, replace the console log, pass in our drawBall function, and we'll call this every 15 milliseconds and refresh the browser. A couple of things to note here, the first thing you'll notice is our ball is now too big. We seem to have a conflict between the paths which we are drawing again, which can be fixed with ctx.beginPath. I'm going to add this inside of our drawBall function, refresh and this now fixes our first issue. The next issue is the ball actually isn't moving yet. This can be expected because although we've repeatedly drawn this ball every 15 milliseconds, we always drawn it in the same location. In the drawBall function, we always drawn this into the center, and we can change these two values with some variables which we can update. For the width, which is the exposition, we replace this with ballX, and ballY for the Y position. We still do want both of these variables to initially be in the center of the canvas. First of all, ballX, it'll be equal to the canvas width divided by 2. Place this initially into the center, and then for ballY just below, we'll divide the canvas height by 2. As we would expect if we save and refresh, we don't see any updates still just yet because we actually need to update the values of ballX and ballY each time the frame has been repeated. We can do this again in our drawBall function after this has been drawn. As soon as we move on to the next loop, we'll update the value of both of these variables , plus equals 2. Plus equals, we'll add the value of two to our ballX variable and then update the variable, ballY is equals. We'll keep this short since we don't have as much trouble on the y-axis, so the value of one is fine. Refresh this. We'll now see the ball traveling on the canvas. This is now updating, but we still have this solid trail on the canvas since the previous ball position needs to be removed. We can fix this with a canvas method called clearRect, which will clear all existing drawings from the canvas before we redraw our ball down to our loop, place this in at the beginning, just before we repeated to call our function, passing clearRect, which is available on the context. If we want to do have the option of only clearing small parts or a particular section of the canvas, on our case we'll clear the full canvas. First, we pass in at the starting location which is in the top-left, which is the coordinate of 0, 0, and then we clear the full width and the full height. First of all, by passing in canvas.width, separated by a comma, canvas.height, and again replace this with small values. If you only want to remove a small part of the canvas over to the browser, the ball now moves as expected without leaving this solid trail. Go to the ball, now moves as we expect, and we don't see anything else now on the canvas since we cleared it with clearRect. We're clearing the canvas each time, we call this loop function. What we need to do is to grab our drawing functions from above and also move these into our loop. Also, the additional benefits of all these drawing functions being in the loop is that very soon we're going to update the paddle position with a keyboard, and this will also update the position on the canvas on each loop. But for now, we'll go up to where we draw our shapes, and we'll do the same as we did with the ball, which is to wrap all of the relevant code into a standalone function. So it can be called from inside of our loop. First, drawing function was the player paddle, which is here just underneath our variables. Cut this out and create a new function called drawPlayerPaddle, paste this back into our function. Second one is draw a computer paddle, and this is for all blue section. Cut this out, and create our new function called drawComputerPaddle. Again, paste in our code, drawBall function is still in place. The next one was filtText, and this is to draw the score onto the canvas. So cut this out, create a new function called drawScore, and then paste this back into the body. The next two sections are for drawing our lines to the canvas. This one was for the center line and also the circle in the middle. We'll place both of these into a single function called drawCanvas. Paste this in. Now we can call all of these new functions from our loop: drawPlayerPaddle which was the first one, followed by drawComputerPaddle, drawScore, and finally drawCanvas. Let's try this out, let us see the browser. Now after we clear our rectangle along with the ball, all of the rest of the drawing functions are now working. As you would expect, this is a really important part of our game and a big step in the right direction. Coming up next in the upcoming lesson, we'll take a look at how we can use the keyboard to move the players paddle up and also down to the ball. 8. Moving Objects With The Keyboard: We now get to the fun part where we can actually make things move on the Canvas using controls such as the mouse or the keyboard. The aim of this video is to listen out for when the user presses the up or the down button on the keyboard, then we're going to move the users paddle. We can do all of this with regular JavaScript. At the moment, we have this player paddle over on the left. If we go to the draw player paddle function, which controls this, just here, we can see with the x and the y coordinates location. Though this is over on the left because we have the x value to be 0 and the y-value is set to be in the center. To update our paddle with the keyboard, we need to replace this y-value with a variable. To keep it positioned in the center rather than the top-left, we can still keep this peddle height divided by 2. But the Canvas height divided by 2 can be replaced with a variable called player position. A position will need to be created up at the top with the rest of our variables. We use let since this needs to be updated. Play position and set this equal to Canvas height divided by 2. To begin, this will leave our player in the center of the Canvas, just like before. But now we have a variable which we can update. This will also be checked on each loop since we call our function from our loop. With this variable now setup, we can begin to listen out for a keyboard events, move our player position. Just below this, what we need to do is to listen out for a keyboard event with addEventListener. This is just regular JavaScript document.addEventListener. We're going to listen out for a user's event. The event we want to listen out for is a key being pressed down, which will then trigger a function which I'm going to call movePaddle. Function movePaddle. Since this isn't event, we need to access the event information to find out exactly which key the user has pressed, we need to pass in the event information into our function. Begin, we'll start with a console log passing in the value of e. We can see exactly what event information we have for our key down event. Jump into the console, refresh. This won't do anything to begin with until the user has pressed the key. Let's start with the key up, which will then print all the information from our keyboard events. There's lots of information inside here which we don't need. But the main thing which you do need for this project is this code property. You can see this is a string of Arrow Up. If we now close this down and press the Arrow Down, the code which you need for this one is Arrow Down. We can access e.code and check if each one of these is equal to the arrow up or the arrow down, then we can set the value of player position. Let's remove the console log since we know what we're looking for now and replace this with a JavaScript switch statement. The value which we want to check against, as we've just seen, is e.code. Since we're only current list now for the arrow up being pressed or the Arrow Down, it could replace this with an if else statements if you prefer. But I want to use a switch statement so we can extend this later on to use the keyboard to start the game. To begin, the first case which we need to listen out for is Arrow Up. Make sure this matches the string exactly like we see inside the console. Each word begins with a capital. If the arrow up has been pressed with a need to update the player position by deducting a value. Because remember, the value of y at the very top is 0. This updates as the player position moves down passing our variable of player position. For this, we'll make use of the subtraction assignment operator, which will subtract our particular values such as 15 from our current value and then re-update this variable. Each one of our cases needs to be followed with a break clause. Break out of our switch statement if this case is being matched. We also just need to place in a colon inside of here. Our second case is just below. This one is going to be for the case of Arrow Down : This time we'll update the player position with the addition assignment operator, which will add 15, and then reassign our new variable with the updated value. We'll break out of this if this one is true. Since our player position is used inside of our function when we draw the paddle, we should now be able to update this when we press the up and down keys. We can also move anything else on the canvas using the same technique. In a future video, we'll look at how to move the computer's paddle up or down, but this one needs to be done automatically. Next, we'll cover how to handle the ball bouncing off our objects. 9. Detecting Collisions & Bouncing: What kind of game we would have if the ball didn't bounce off the sides or also the paddles too? Well, this is a tricky one because it involves some working out because all of our current coordinates are based off the center lines of things like the ball and also the paddle. But we'll do our best to figure things out and we'll move on to this now. If we locate this draw ball function, we know these two lines of code at the very end are responsible for moving our ball. Each time the ball is drawn to the canvas, we're going to move the value of ball X and also the value of ball Y. Also, we know how to change the direction. If we now refresh this, this will go across in a positive direction. We can also switch the direction by changing any of these values to be a negative number. This is going to be the basis of bouncing off our walls and also the paddle. To do this, rather than having our hard-coded values just like this, let's update this function to make use of variables instead. Move x to the x location and move y to the y direction. This will make updating these values dynamically much more easier so we can reverse the direction when there is a collision. At the top, let's set these up as variables. First of all, move x, and for now let's keep in the same hard-coded values which we had before. Move y this was equal to one. But you can update these to be different values if you want to. Also one more variable for the ball radius, which is a initial value of 10. We will need this a lot when we're calculating the collisions. This is because the ball is positioned from the center point of the circle, but when it gets up to the top for example, we also need to take into account the radius of the ball. We can also update our functions to make use of the ball radius just below. Back down to draw ball. Here we're setting the ball radius to be also some pixels, or we can update this to use our variable. Now, on to the function to check if there is a collision. Let's set up a function at the very bottom just above our loop. I'm going to call my function collide. Then this function is going to be responsible for checking four different things. The first thing is to bounce off the top and bottom. We also want to check if there's contact on either the left or the right of our game, so we need to check for the score on the x-axis. This applies to both sides. We also want to check if there is contact with the players paddle. Also, the same for the computer's paddle too. Good. We now know what we want to do inside of this function, and we can call this just below inside of our loop. This means that we'll check all of the collision points at any given frame of our loop. We'll check for contact each time anything moves. Now we do have a bit of working out to do inside of this collide function. Just before we start to work out our four points of contact, I'm going to draw a temporary ball onto the canvas. We can move this around, and make sure we have the correct contact points. First of all, we'll begin a new path. It doesn't interfere with any other drawings. The fill style. You can make this any color you want just so it stands out, I'm going to go for purple. Then ctx.arc to draw our ball on the canvas. Any location for now, any random location is fine, 10 pixels on the x and y as in the ball radius. To make our circle the start angle can be zero, and then 2 times math.PI. Do draw this, the final thing we need to do is ctx.fill, save, and there's a ball in the top corner of our screen. Okay. The first points of contact we want to check is the top and bottom of the canvas. Starting with the bottom. Let's move our temporary ball down to the bottom of the canvas and make sure we have the correct collision point. The x-axis doesn't matter for now, but we do need to change the y-direction. But first of all, we'll pass in the canvas.height, save this. As you can see, this will push this off the edge of the canvas, so we need to pull this back half of the ball radius. We already have this stored as a variable, so we can deduct this from our canvas height. There we go. This is the point of collision on the bottom of the canvas we want to watch out for. Now, we can make use of this in an if statement. We want to check if something is true. The check which you want to do is if the ball y, which is the location on the center point of the ball, is greater than the ball location which we've just drawn; if the ball has gone further down than this current point, it's then considered to be off the canvas, and we then need to rotate the direction. Just before we do this, we'll test this is working okay with the console log of hit bottom. Jump into the console and refresh the browser. As soon as the contact point gets to the bottom of the canvas or goes off, we want to get our console log run inside of here. Bouncing this ball is pretty simple. Currently when the game starts, the ball goes in a positive or a downward direction, but we can reverse this by changing this to be a negative number, just like we've seen at the start of this video. Now, in this and since we are working on the y-direction, we can replace our console log by updating the variable. Move y, which is the current location, is equal to a negative version of move y. Which will effectively reverse the positive to a negative and a negative to a positive. Let's save this and try this out. Refresh, and we should see a bounce off the very bottom. Of course it still goes off the corner of the right-hand side of the canvas, but this is fine. We can now see our bounce is all working. Good. Now we need to account for the collision on the top of the canvas too. Inside the if statement we'll add an or condition. This time we want to check if the ball y location is just touching the top of the canvas. We don't want to check if this is equal to zero because then if it was, because of the ball radius, this would be half off and half on the canvas. We also want to deduct the ball radius. We check if this is less than or equal zero. If it is, it should bounce off the top of the canvas. Currently, when we reload the browser, the ball moves in a downward direction. But for testing, we can move the move y-direction to be a negative number, and this will cause the ball to move in an upward direction. This is the basics of how we can bounce a ball. It really is mostly a case of just checking our contact points are correct, and also making sure we account for the ball radius too. We'll now move on to adding a condition to check if the ball hits the left or the right-hand side of our canvas, and later on, this will increase the scores. This one will all be based off the ball x location for the left and the right-hand side of our game. Go back down to our function, which is collide. Then just under our comments, we also want to place in an if statement. First of all, to check if the ball is collided over on the left-hand side. Currently, our temporary ball is exactly where we want the point of contact to be, which is set to be a value of 10. This all works out fine because our ball radius is set to 10. We want to check if the location stored inside the variable of ball x is less than or equal to the ball radius. Effectively, if the ball is on the left where it is now, we want to then pass a score to the computer. We'll provide a way to do this later, but for now, just paste in a console log of computer score. Then below this, an else-if section. This is going to be for our check to see if the player has scored by moving the ball over to the right-hand side. For this one, we pass in the location of ball x. We want to make sure that the ball is touching the right-hand side of the canvas. Again, the x position vertically is in the center of the ball. We also want to check if the ball x plus the ball radius is greater than equal to the full width of our canvas. We can grab this with the canvas width. Then placing a console log for the player score, test this out into the console. It's a little bit bigger. You've got a typo on line 85. This just wants to be together, no space in between. Let's try this out now. If the ball moves over to the right, we see there's a player score. If we go up to our x location at the very top, it can just to be a negative number. We can then test out the computer score. Here we go. This now all works as expected. Things are really beginning to take shape now with our game. Next, we'll take a look at another important section, which is to bounce the ball off the moving paddles. 10. Paddle Contact: In a similar way to bounce off the sides of our canvas, we now also need to account for the ball hitting our moving paddles too. This involves a little bit more work because we need to account for not only the ball hitting the front of the paddle, but we also need to check the ball location is between the top and the bottom of the paddle too. Starting off with our player's paddle, to check we are working things out correctly, we can use this temporary ball, place this on the front of the paddle and check we have the correct contact point. Jump into the collide function and at the top, we have this arc which is creating this temporary ball. Remove this value and place this on the face of the paddle, we need to move this across on the x-axis, the ball radius, plus the width of the paddle which is stored in the paddle width variable. Refresh and first of all, we can see this move across, and just to confirm this we can move this into the center by adjusting the y-axis equal to the canvas height divided by 2. There we go. Now we have the correct contact point for our paddle. We can use this contact point now to check if the ball is less than or equal to this X value. Again, we set up an if statement just like this. Move down to our comment, which is check the player paddle contact. The if statement is going to check if the ball X position is less than or equal to the X position which we just set, which is the ball radius plus the paddle width at this end. Basically checking if this ball position is where it is now or less than. Using our move X variable, we can then reverse this by setting this equal to the negative equivalent. Remember here though all we're doing is checking the X location, so the ball should bounce off anywhere vertically from the top to the bottom as long as it is in-line with the face of the paddle. Let's refresh this and test this out. We should now see a bounce before it hits the back of the canvas. Good, so this all now works fine. Next, we want to restrict this bounce to only happen when the ball is between the top and the bottom of the paddle. We already have a variable in our game called player position, which is set to be initially in the center of the canvas which for us now would be 200. When the up and down keys are pressed, the center point to the paddle will update the player position variable so we always know where this is. For example, let's say it's currently at 100, next we need to check where the ball is in relation to the paddle. Now we can use 70 as the ball position. Take this value away from the paddle and we can see the difference is 30 pixels, and this is a positive number. In another example, here we can see the ball position is a 125. Again, take this off the player position, but this time the result is a negative number of 25. But why does this calculation matter? Well, it matters because if this number is within the paddle height, there should be a contact. We would have half the Paddle height since we're working from the center line and we also need to account for the ball radius too. This is where things can get a little bit more complex. Here we've add the radius or deducted, depending on which side of the ball is on, positive and negative values. In the previous slide, we also had the same positive and negative numbers to account for too. This means we could write some complex code to account for this or we could make our lives a lot easier by changing every comparison to be positive or we can do this with a math method called absolute. To see how math. absolute works, let's jump into the console and test this out. Placing a console log with the value of math, delta abs passing in a positive number such as two. Now if we refresh and go into the console, we can see we have the value of two so just as expected in the console. However though, if we change this to be a negative value, I'll just move this out of the loop so it doesn't keep repeating. Refresh, we can also see the value is still a positive number of two. Regardless of if we pass in a positive number or a negative number, we always get the positive equivalent shown. The point here is we can use this absolute methods to make sure the calculation between the ball and paddle is always positive, meaning we can always compare this value to a positive action of adding the ball radius rather than having to work out if we want to add or deduct this. Over to the code and let's see how this looks. We can remove our console log, and then jump into our if statement at the top. We currently only checking the exposition, but we now also need to check the Y position with the "AND" operator. Now we're going to check if the ball is between the top and the very bottom. Passing in math to abs. We always get a positive number. What we want to do is to check if the Ball Y position, take away the player position. Remember this is going to give us this value between the ball and the paddle, but it's always going to be a positive number unlike in the slides. Then we check if this value is less than or equal to the height of the paddle, divided by 2 plus the ball radius. The reason why we can add the ball radius, and we don't need to worry about taking away depending on which side it's on is because we are always converting this to be a plus number, therefore, we're always adding the ball radius. Let's give this a save and try this out inside the browser. First of all, the ball can go auto play, and if we now move the paddle in place, they should now cause a contact point between the ball and the paddle. I know this may seem difficult, but without this positive conversion, we wouldn't need to duplicate this for the ball being either above or below the paddle center line. Now with this working, the next thing to do is to check the contact point for the computer's paddle. This one's going to be pretty similar, so we can copy the full if statement in the player section and paste this just below the computer comment. First, the exposition needs to be over to the right. We now need to check if the ball position is now greater, add the ball radius to account for this. On the right of the greater or equals, we need to check if the ball is past the face of the computer's paddle. We can do this by checking the canvas, width, takeaway the width of the paddle. This should be the X position taken care of and for the y position, this is going to be pretty similar. We want to also check if this is between the top and the bottom of the paddle rather than checking it against the player position, we want to check this against the computer position. Of course this one hasn't been created yet so let's go up to the very top where we created our variables and we can duplicate our player position and change this to be the computer position. Again, setting this to be in the center of the canvas is completely fine for the beginning of our game. The computer position will also be updated in a future video. To clean this up, we can now go back down to the collide function and remove our temporary ball, we no longer need this. It's going to be pretty difficult to test if the computer's paddle is working since we can't move this towards the ball. But one thing we can do just to check things out and check we have a bounce, is to change the move Y position to be a value of zero. This will move the ball horizontally across our game, off the players paddle. Excellent, so the bounce is now working off both of our paddles. Now it changes back, Negative 1 since we know this is working. We've made it through one of the more difficult parts of our game. It may be a little bit hard to take in, but this really is an essential part to make our game function correctly. It's not perfect. We have not accounted for certain edge cases, such as if the ball hits the very top or the very bottom of the paddle, but we don't want to go too deep in this course. Next, in the upcoming video, we'll take a look at how to track the scores, both for the player and also the computer too. 11. Tracking Scores: We already use the filtText method to draw our score onto the Canvas and our scores are also stored in variables. We also know when the player or the computer scores by hitting the ball off the left or the right-hand side of our Canvas. The logical next step would be to update these variables when this happens, to then update the score on the screen, these variables where player score and also computer score down into the Cloud Function, let's locate this inside of our script. Just here. We currently logged to the console when a player or the computer has scored. Inside of our if else if statement, we could directly update our score variables inside here, but instead I'm going to call a function. This function will also check other things like if the game is over and also place the ball back into the center. We'll replace these two console logs with a function which we're going to create soon called score. The score function will also need to be made aware of which one of our players has scored. For our first one, we'll pass in the computer as a string, and for our second one, if the player has scored, we'll pass in the player to this function. Of course, we need to create this and just blow our Cloud Function, create our function called score. Inside here, we're going to take in the player. Remember this player variable is going to be equal to either our computer or our player. We can check which one of these has been passed with an if statement. If the player variable is equal to the computer, we'll do something inside of here, which is to update our variables. Remember at the start, we looked at the player score and the computer score, and Here we'll update both of these variables by the value of one. This one is for the computer score. Increases with plus-plus. Else we update in the player score. Over to the browser and let's test this one out. We'll let the ball pass out and the paddle. We can see that the computer score is going up really fast. The reason this happens is because each time the ball moves or each time we have a new frame inside of our loop, we are checking if the ball is behind the player or the computer's paddle. Since we are continuously behind the paddle, the score will keep on increasing. To fix this, we can put the ball back into the center of our game so we can start again. The way we can do this inside of our score function is to reset ball location with ballX is equal to the canvas.width divided by 2, place this into the center. We'll also do the same for the location of ballY. This time this is based off the canvas height, also divided by 2. Let's test this out. Refresh, let the ball pass behind the paddle, this is set to one, then the ball is placed back into the center for our game to continue. This is a simple way to track the scores of our game. In the upcoming section, we're going to take a look at how we can add a maximum score so we know when the game has ended and also will display the winner onto the Canvas. 12. Ending The Game: The first step towards ending our game is to set how many points we want to be the maximum. For this, we need a variable at the top called winning total. Const winningTotal and my value is going to be equal to three so the first player to get to three is going to be the winner and we can update this inside of our score function. Let's head back into our function. Here we need to check if our computer score or player score is equal to this winning total. Placing an if statement to begin, check if the computer score is equal to our new variable which is winning total. If it is, we're going to do something, if not, we'll pass in an else-if clause and this time we'll check if the player score is also equal to our winning total. What we want to do inside of here, we're going to end the game by creating an endGame function. Obviously, we haven't created this yet, but it's called endGame. Just like when we created our score function, which took in the player, we're going to also do the same for the endGame function. This is the left, this function know which one was the winner. This one, this was the computer then we'll also pass in the return keyword to break out of the statements. In a similar way, the else-if statement will also call our endGame function but passing in the player. Also return out of this if this is true and the reason why the endGame function needs to know which one of these players was the winner is because we're going to change the colors depending on which one was the winner. As you can see, we've got the red color for the player and the blue color for the computer. This will be reflected inside of our endgame text. Let's create this function just below. Remember this is being passed either the computer or the player, which will store inside a winner and then pass in an if else statement. The if section we can check if the winner is equal to the computer. Just need to remove these brackets we don't have these in the else section. If the winner is equal to the computer, which is the color of blue, we're going to then change the text color to display the results to be a blue color. ctx.fillStyle is equal to blue and then in the else section, we changes fillStyle to be equal to the red color to match our player. Now the reason we're changing this text color is because we're going to display some text onto the canvas when the game has ended. This is simply just going to let the player know if they've won or if the computer has won. Just before the text, we'll set the text line to be equal to the center. Place this into the middle of the canvas and then we create our texts with a function called fillText. Open up the backtick so we can insert a variable because we also need to insert the variable of the winner depending if the computer or the player has won. Say the winner is, a colon, then using the dollar symbol and the curly braces in JavaScript, we can insert the variable of winner. This will be the winner is player or the winner is computer. After the backticks, add a comma then we can place this in the center of the canvas. First of all, the exposition, which is the canvas.width divided by two. On the Y position is canvas.height divided by two. Auto-browser and we can try this out. Refresh and let's move this out of the way to get to the value of three. That's one, two, and three. You can see straightaway that we do initially see our text, but it quickly disappears and the game continues on. The reason this happens is because our loop is still running. We haven't done anything to stop our set interval. Once the player or the computer gets to the score of three, we're still drawing the text very briefly to the canvas but on the next iteration of our loop, we're running this clear text method, which is clearing all of the texts off the screen and then redrawn all of our game functions. How do we stop this loop from running? Well, set interval can be stopped by a method called clear interval. This involves storing a reference to this interval when we create it and then using this reference to stop it later with clear interval. This reference can be stored inside of a variable and like all the rest of the variables, this will be at the very top. Call this gameLoop and then at the bottom, set this variable to be equal to our interval so gameLoop is equal to our setInterval. Here, we're still calling setInterval just like before but this is going to return a unique ID which is stored inside of this variable. We can see this if we log this to the console, jump into the browser and refresh into the console and we can see the value of one. If we had multiple intervals running, each one of these returned IDs will be unique. Back to our endGame function, this variable can now be pass to clearInterval to stop the loop from running. We'll do this right at the very start of our function. Pass any method which is clearInterval, which takes in our ID, our reference store interval called gameLoop. Now we can test this out, refresh, wait for this to get to a value of three. Good. We can see straight away to the game freezes and we still have the text on the screen. To improve on this, it would be better to clear the ball, to clear the paddles, and also these dotted lines in the background. Even only the score on the winner on the canvas. This is something we already know how to do from our loop where we clear our canvas, we clearRect. Let's copy this and place this inside of our endGame function. This will only clearInterval method, it'll clear all the rest of the Canvas. Since it happens before we draw our text, we should still see the text on the screen but it would be useful if we could also see the score at the very top. Well, this is pretty simple. We also know how to draw the score with this function just here. After we clear our Canvas, refresh and we'll try this one more time. Great, the canvas has been cleared we still see the text. We still see the final score at the very top too. With this all now working, next, we'll move on to starting and restarting our game. 13. Starting & Re-Starting The Game: Instead of our game starting immediately as soon as the browser loads, it would instead be nice to trigger this action with the keyboard by using something like the space bar. We'll now take a look at how to do this and also how to restart our game once it is finished. I will use the space bar to start the game, but you can change to a different key if you prefer. Look inside our switch statements. we will listen out for the arrow up and the arrow down. We can create a new case to listen out for our chosen key to begin the game. So case, this time as a string. The key I'm going to listen out for is the space bar, put a colon, and then we're going to call a function to start the game called game start. At the break clause, if this is true, and just before we create this function, it would also make more sense now to rename this new part of function to be something else, since it does other things rather than just move our player up or down. I want to go for a handled key pressed. Remember we also need to change this in our key down listener just above. Of course, we need to create this game start function. Set this up just below. If we think about this, what do you want this game to do? Well, since we are currently unable to refresh the game and it currently starts without doing anything, we want to now move this loop, which we call it right down at the bottom into our function. Rather than this game starting straight away, we can cut this out and place this into our game start function, so this will only happen when the space bar is pressed. Let's try this. If we refresh, we don't see any game start just yet. Hit the "Space bar" or your chosen key and there we go. Instead of this empty screen, there should also be some instructions at the beginning. Let the user know they need to press the space bar to begin. This doesn't need to go into a function or anything else, we can just add this at the top of our script. But this is just going to be some texts and we use fillText, but first we'll set the color with fillStyle equal to red. You can change this up if you prefer. Ctx.font will set this to be a string or 30 pixels for the font size with a style of Helvetica. Place this into the center with text line, then draw our text with the method called filtText and pass in a string. We don't need to insert any variables, so the regular quotations is fine then the text of press space to play. For x and y positions, this is canvas width divided by two, and also divide the height by two. Let's try this out. There is our text. Press "Space" and our text is also cleared because if you remember down at the very bottom, the canvas is cleared before each one of our loops. Back to our game start function, there's also a few other things which needs to go inside of here too. The first step at the very top is to reset any scores. The player score equal to 0 and the computer score also 0. Using clear interval will also clear out any existing timers which is stored inside of our game loop variable. Let's try this out. Refresh, press "Space" to begin, and everything looks fine. All scores updated, but there is a small problem if we keep pressing the space bar during the game. You can see up at the top, if we press the space bar now, the score is reset each time we begin the game. This isn't a problem if we actually want to begin the game, but if the player accidentally presses this during the game, it's going to restart. We can help this by keeping track of this with a variable. Let game running to initially be a value of false, so we'll switch this around to be true as the game is running, which will then prevent the space bar from restarting our game. We need to paste this into a few different places. First of all, we look for our function, which is endgame. As you would imagine, since this is the end of the game, we can also set this game running variable to be equal to false into the game start function. Now at the very top, we want to perform a check to see if this game running variable is equal to true. Pass this inside of an if statements, if game running. We don't need to say equal to true or anything like this. If the value of game running is equal to true, the code inside of these braces will run. Or we can also place this onto a single line and remove the curly braces and then return out of this function. Basically if game running is equal to true, we'll then jump out to this function without running the rest of the code below. This will prevent the game from restarting. If it's not, if it's equal to false, we then want to go ahead and run the code below. Also we'd say in our game running variable to be now equal to true. Therefore, this will stop this function from running a second time, if the space bar is pressed during the game. We can try this out, refresh, press "Space", let the ball go behind for the score and if we now try to press the space, the game isn't reset. But we do have another issue to address and to see this, if we restart the game and wait to get to the score of three, let us pass behind three times. All is good, we have the text of the winner is computer, the score of 3-0. But now if we restart the game with the space bar, the game restarts, but we still have an initial score of one. But you would expect this to be zero since we set this inside of our function. Why do you think this is happening? Well, to find out more, let's go into our score function. The score function is the only place where we update either one of these variables. The score function is being called just above inside of our collide function. Jump into the collide function and we calling this with our if else section. This is the only function or the only piece of code which is called in our game, which is responsible for updating these variables. We know this is a cause of our score being set to one initially. Why do you think this score function is being called at the beginning of a new game? Well, the reason this happens is because as soon as the game has ended, our ball is either over on the left-hand side for a score, or over on the right-hand side. We have this controlled by the variable called ballX. Yes, in our game start function, we do initially reset both of these scores, but as soon as a new game starts, the ballX location is still touching one of the sides, causing the score function to run again. Fixing this is pretty simple, all we need to do is to reset the location of ballX to back into the center when the game starts. Game starts just after a game running and before we reset our scores, we can also reset the value of ballX to be in the center of the screen. Let's test this out. We get to the end of our game, which is a score of three. Game over, both of our scores are now reset as expected. When building games like this, you will often find edge cases like this to work on and it's usually just a case of trying out different things and seeing which one works. Next, we're going to take a look at how we can apply some random movement to the ball when it bounces. 14. Random Direction: Having both of these moveX and moveY variables preset makes the game start much more predictable. We know because our negative 2 and our negative 1 values which direction the ball would go. We can improve on this by making this much more random inside of a function. Let's create a function just below our texts, called random movement. The purpose of this function is to set both of these variables with some random values, meaning we can now remove these initial values. To set these variables, we need to call this randomMovement function inside of gameStart. Locate this function, call our new function, which will reset our two variables with a new value each time our game starts. Go back to our randomMovement function that generate our two x and y-values, as well as setting the ball off in unpredictable directions. This will also slow down and speed up the game a little because of the random values and movements, i.e, the x movement could be higher or lower, causing it to move slower or faster. Again, create two variables or two constants. This is random x, which will be a random number between two and four. Basically, we're going to set our x value to be equal to 2 or 4 and also either a positive or a negative direction. We can do this by accessing a JavaScript math function called random. Math.random will generate a random number between 0 and 1. But we're going to multiply this value by 3. Doing this will allow us to generate a number from one onwards. We can also round this up by cutting this value out. In the math.ceil method, paste this in. Now since we're rounding up our value, this will either give us a value of 1, 2 or 3. Since we want the value of 2-4, we can add one more to this value to give us our random number. Let's test this out. Placing a console log of randomX, save and refresh the browser, jump into the console. To see this, we'll also need to call our GameStart function. Press Space, the value of 2, the value of 4, 2, 3, 2. These all seems to work correctly. For our randomY location, we can duplicate this line, change the variable name to be randomY. RandomY is going to be a number between 0 and 2. This one we don't need to add plus 1. We can use math.round to round this number down, leaving us with a value from zero up to two. We also now need to create two more variables. This is going to decide if we have a positive or a negative direction. Currently, we just have a positive x and y-value, but this is going to also add to the unpredictability. Const plusOrMinusX. Again, we'll access the random JavaScript function, which one's more is going to give us a number between 0 and 1. Using the JavaScript conditional operator, we can check if this value is less than 0.5, which should roughly be a 50/50 chance. If it is, we'll return back or store inside of this variable a string of negative. If not, it will be positive. Since this is a number between 0 and 1, there's a half or a 50/50 chance roughly that this is going to be either a negative or a positive value. We'll also add this to our numbers soon. Duplicate this and the only difference this time is the variable name of y. Then we can use these variables to merge together and create our new values of moveX and moveY variables. First the variable of moveX. Since we're also returning a string value for the positive or the negative, we'll wrap this inside of a number function to make sure we always get a number rather than a string. Starting with x, plusOrMinusX, add this to our random number. For example, this could be negative and then a value of two or positive one, or any number between this range. Duplicate. We'll do this for moveY. Also changes to be a plus or minus y and the value of random y. This is a random positive or a negative number in both directions, but I'm going to add one more little piece of randomness. Create constant to store this in called random number. Just set this equal to simply math.random. The reason we do this is to add a small random value to both of these variables. Add this to our first number, then to our second number, it should be all we now need. Refresh the browser. Each time we start the game, we should see the ball traveling in a slightly different direction. We have it going left, we have it going right, we have it going up, we have it going down. You can also see we have various different speeds depending on the actual values for these two variables. This is not all over for our randomness. A little bit later on, we'll look at how to add some random movement to the ball direction when it bounces off the walls and also the paddle too. Speaking of paddles, this is what we're going to cover in the upcoming video, where we'll look at how to automatically move the computer's paddle. 15. Computer Movement: At the top of our scripts, we have the player and also the computer positions inside of these variables. Both of these values set the paddle positions at the start of our games, be in the center vertically. The player position we already took care of with the movements inside of our handle Key pressed function. Now we can also add some movement to the computer to make the game a little bit more playable. Let's do this in a draw computer paddle function, which is this one just here. All we are doing currently is setting the canvas.height divided by 2, places into the center. Obviously, we don't want to do this just like above. We also want to replace this with a variable. We take away the canvas height and replace this with the computer position. This means just like the player position above, each time this variable is updated and we then call the loop, the new position of the computer paddle will also be reflected. The ext stage is to update this. But how do we decide on how to move this? Well, we could go really complex and include things like some artificial intelligence, but we don't want this course to be too complex, Instead, we're going to replace this with some simple motion tracking. For this down at the bottom just above our loop, I'm going to create a new function which is called on each interval. Function's name is move computer. This also needs to be called on each interval, so we can grab our function name and add this into our loop. The most basic tracking can be done something like this. We can update our variable of computer position to be equal to the location of ball Y. This will effectively track the location vertically of our ball, move the Computer paddle to track this, we can see this? If we go back to our browser, refresh and you can now see the computer paddle moving up and also down depending on the location of the ball. Great, this all works fine, but as you can see, this creates a game which is impossible for the player to win. Again, we could go as complex as we want to with a computer movement. But to keep it simple, I'm going to just add an if-else statement. This if-else statement will gradually update the computer position depending on if the ball is above or below the paddle. We can remove this, add an if statement. Where we check if the computer position currently is below the current location of ball Y. Remember for the y-axis is begins at 0 at the top and goes down in a positive direction. The ball is below the paddle. We can then update the computer position variable to move towards the ball. This can be done by adding plus, plus, else if is the opposite direction, we want to move the computer's paddle in the reverse direction. We can do this inside of here. Let's try this. Refresh and test this out. Bounce the ball back. You can see that the computer is now moving. It's now a winnable game. You can also if you wanted to speed up or slow down the steps which the computer paddle takes to go towards the ball. But this is completely optional, and this may also need to be fine-tuned too depending on how fast the loop is running. Great. This is a very basic computer movement and next will improve the game even further by adding some additional randomness to the ball movement. 16. Random Bouncing: The ball currently bouncing off all of the walls and the paddles is a little bit predictable. Currently every bounce is at 90 degrees, which often leaves us with a situation where the ball can sometimes go round in a square, and it bounces off the paddles without even needing to move them. To improve on this, we'll add some randomness to our paddle bounce to make our game a little bit better. For this, we need a function. Let's create a function anywhere in our code with the name of generate random bounce. Add some randomness. We don't need to do anything too crazy or complex. If we first go up to our collide function, the last two if statements check the paddle contact for both the player and also the computer's paddle. Currently, when there is any contact between the ball and the paddle, all we're doing with these two lines of code here is reversing the direction. We do this by setting a positive direction to a negative and also the other way round too. To add a little randomness, all we need to do is add a small positive or negative value to either one of these lines, which we can return back from our new function. Inside of this function, we're going to first generate a number between zero and one. Zero and one gives us two options, which we can then use to decide if we're going to create a positive or a negative number. Again, we use Math.floor to round our number down. The number which you want to round down is going to be generated with Math.random to give us a number between zero and one. Remember all of Math.random generate a random number between zero and one. It doesn't actually include one. For example, it will go all the way up to 0.999. Randomness number down will always give us a value of zero. To get a value between zero and one, we can multiply this by two, install this inside of a constant called number zero to one. These two options can now be used to create a positive or a negative symbol, just like we looked at earlier. Store this inside of a constant, positive or negative. Then we'll grab our variable from above, which is either zero or one. We'll, say if this is equal to one of the options which is zero, using the JavaScript conditional statements, the first option will return back a negative value. If not separated by a colon, will return back a positive symbol. If this returns back a zero, we'll get a negative symbol. If it returns back a one, we'll get a positive symbol. Remember, since we are returning back a string, we also need to wrap the results inside the number function. Make sure we always get back a number rather than a string. We return back the symbol which is positive or negative, and add this equal to a small value. Again, we use Math.random to give us a number between zero and one and also to make it a little bit more of a smaller value, we'll divide this by two. If we then return this value back from our function, this will return back a number which is a positive number or a negative between the value of zero and 0.5. With this being such a small value which we are now returning back, how do we tell if this is being added to our bounce or not? Well, we can first see this with a console log. If we take a look for our Cloud Function and into our last two sections that we looked at before, we can add this to the player paddle contact just above where we do the direction change at a console log with the value of mu of x. Copy this and do exactly the same just afterwards. Each time the ball bounces off the players paddle, we should see two console logs with the value of mu of x. Remember we haven't added different random value to any one of our direction changes just yet. These two values should be exactly the same or the opposite in terms of positive or negative. Let's try this out. Refresh and jump into the console. Start our game, and now make some contact between the puddle, and we can see we have negative 2.49 and also the positive equivalent too. Since these numbers are exactly the same, this proves all we're doing is reversing the direction by 90 degrees. But if we now go ahead and add our small random value, we should see two different values inside the console. Now, we'll add our small volume which is returned back from our function called generate random bounds. Also the same with the computer's paddle too. Now, if we test this out, we should see the small value being returned back and added from our function, and this should be slightly different values to give us a different direction change with our ball. Refresh. Now, if we make some contacts, there we go. Great. Now, there's a lot going on here but if we take a look at these in pairs. The first two pairs, there's negative 3.55, which then reverses to be a positive value of 3.22. With these two values being slightly different, this means our bounce value has now taken effect. If we look at the second pair, again, we're now not only changing the value from a positive to a negative, we'll also slightly change any bounds value too. This is true for all of the pairs which follow too. Small change can make a big difference and make our game a lot less predictable. Also stop the ball going around in a square on the Canvas too. Next up we'll take a look at how we can restrict our paddle so it doesn't go off the Canvas. 17. Keeping The Paddle On The Canvas: As we approach the end of our game, one of the finishing touches which you want to add is to restrict the players paddles so it doesn't go off the top or the bottom of the canvas, when we press the up and down keys. For this, we'll head into the handleKeyPressed function to add our code which is needed to restrict this. This handleKeyPressed function is the area in our code which detects if we press the arrow up or the arrow down. The switch statement is responsible for then moving the players paddled in an upward direction or in a downward direction. Inside here, starting with the arrow up case, we're going to add some code to restrict the players petals from going off the top of the canvas. To do this, before we move our player position by any particular value, we'll add an if statement to check this. If something is true, we then want to return out of this section without moving the player's position. There's something which we want to check is the player position. Remember when we're talking about the player position variable, this is the center line of the paddle. To find the very top of the paddle, we need to deduct half the paddle height and to find the bottom of the paddle to make sure it's not going off the bottom of the canvas. We also need to add half the height of the paddle too. We can use this inside of our if statement. Going off the top location inside of our if statement. First of all, we'll grab the current player position. Just as we've seen in the slides, we'll deduct the paddle height divided by 2. This will give us the very top point of our paddle. We need to check if this is less than or equal to 0, which is the very top of our canvas. If it does, we'll then return out to this without moving the player position. Then in the arrow down section, we'll do a similar if statement where we check if the player position, this time we're going to add half the paddle height, since we're dealing with the bottom of the paddle. Here, we're checking if the bottom of the pedal is equal or greater than the bottom of the canvas, which we can find with canvas.height. Greater or equal, on the canvas.height, if this is true, again will return out of this without moving the player position, so it won't go any further than the bottom of the canvas. Test this out, press the space bar and we'll go right to the very top. The place paddle doesn't go any further than the very top. Move this down to the bottom. It's now restricted the players paddle to stay within the canvas area. 18. Final Thoughts: [MUSIC] This is it now for the end of our game and congratulations for reaching this stage. We've now learned some core concepts and even though our game is not perfect, it's playable, we've learned all of the concepts which we need to begin JavaScript game development. I hope you've enjoyed it. I hope you picked up some new skills and eager to dive into building more JavaScript-based games. Thank you for taking this class, and I will see you in the next one.