Module 6: Begin making a block dodger game in JS Canvas
Objective: use variables, operators, and functions to create a simple animation.
Getting started
Welcome back! Now that we've had a small taste of JavaScript and are getting comfortable with our development environment, it's time to dive right into game development. We'll introduce the remaining basics of programming in the context of a graphical game.
We're going to use JS's built-in graphics library, Canvas, to render the graphics. Canvas is an ideal game framework to use because it's simple and no-frills, forcing us to write all of the game mechanics from scratch. Later, we'll (optionally) be able to use a more complex game framework that will handle some of the work for us.
A good way to start is to plan out the result on paper. The primary game mechanic works like this: Using the mouse, a player will move a block left and right along the bottom of the screen, dodging falling blocks of different sizes and speeds. Every block that the player avoids colliding with increases the player's score by 1. The goal of the game is to survive as long as possible.
Hello, Canvas!
All graphics programs take a little bit of code to set up and show something on screen.
Don't worry too much about the specifics
of the code--it'll make more sense later on, but I'll offer a provisional explanation below.
Don't forget to copy the HTML and CSS portions. You're welcome to follow along with the code in
Codepen or in your local environment. Don't forget to
reference your .js
script and .css
stylesheet from your
.html
file if you're working locally.
See the Pen block dodger (part 1) by ggorlen (@ggorlen) on CodePen.
There's a lot going on here! Let's break it down a bit. Don't worry if these explanations are dense; they'll make more sense later on in the course:
The HTML
-
The HTML component creates a new element we haven't seen yet,
<canvas>
. The canvas is then given height and width attributes in HTML rather than with CSS, which can cause image warping. This canvas element is also given an ID of "paper" so it can be easily accessed in our CSS and JS scripts.
The CSS
-
The CSS component makes the screen colors dark, centers the canvas element, and gives it a border, as discussed in module 4.
That's about all we'll really need in terms of HTML and CSS for the remainder of the semester!
The JS
Now we begin looking at the JS, which is where all the action is.
-
First order of business is a comment stating the purpose of the game. This is also a good place to put lists of team members, helpful links, things to do, etc.
-
Next line has a string,
"use strict";
. This tells the JS interpreter, or the program built into the browser that executes the JS code, to disallow some common brittle programming practices. Be sure to add this line to the top of all of your JS scripts. Read more on"use strict";
if you're curious. -
The following line,
let canvas = document.getElementById("paper");
requests some information from the HTML document object using one of its functions,
getElementById()
, which looks for an element with an ID matching the parameter string, in this case,"paper"
. This function returns a structure called an object, one of the most important programming concepts, and stores this object in a new variable calledcanvas
. We'll discuss much more about objects later, but suffice to say they are collections of pieces of information (variables) and actions (functions) that work together as a unit. -
The line,
let ctx = canvas.getContext("2d");
stores another object in a variable for us to use. This time, we're calling on the
getContext()
function inside of our newcanvas
object. This function returns a canvas context object, which is what we will use to draw on the canvas. We call this variablectx
for short since we'll be typing it frequently. -
Now that we have a canvas context object to work with, we can begin drawing using its built-in properties and functions. The line,
ctx.fillStyle = "#ffffff";
Sets the drawing color of the canvas to white.
-
And the final line,
ctx.fillRect(100, 100, 70, 50);
draws a filled, white rectangle on the canvas. The canvas context
fillRect()
function takes four parameters, something we haven't seen yet. Recall that parameters are pieces of data that change the way the function works. These parameters are numbers which describe the location and size of the rectangle to be drawn. The first two numbers represent the x and y coordinates for the top-left of the rectangle. The second two numbers represent the width and height of the rectangle. All of these units are in pixels, the little dots on the computer screen that form an image.Another thing to note is that the coordinate plane is arranged in canvas in a different manner than a Cartesian geometric plane:
With this in mind, try changing the four parameters of
fillRect()
to draw rectangles at different locations and of different sizes. Try changing the color value assigned tofillStyle()
. See if you can draw more rectangles by repeating these two lines multiple times.By the way, I have a tool which will display the x y coordinates of an image. This might come in handy later on when you're trying to put things at specific places in your game.
Adding animation
So now we have a square on our canvas! Let's make it move.
Here's the truth: animation is a bit of a smoke-and-mirrors game; if you show a picture of a person for a split second, then show another picture of that person after they've moved slightly for another split second and repeat the process, you create the illusion of motion.
And that's exactly what we'll do on our canvas. To do so, we'll need two tools:
- number variables to keep track of the square's x and y position on the screen
- some kind of way for the program to draw the screen again and again, a few dozen times a second, over a period of time.
For the first tool, let's declare two variables and set them to some default values:
// Number variables to hold the x and y position of the rectangle
let x = 10;
let y = 10;
Then, we'll want to replace our literal numbers in the fillRect()
parameter with our variables:
ctx.fillRect(x, y, 70, 50);
For the second tool, we're going to write our first ever function. This function will be called about 60 times every second as long as the animation is running. Each time this function is called, it will calculate the latest position of everything on the screen and render the entire animation on the canvas. This function doesn't require any parameters, nor does it return any values, so it's very simple. Since it updates the screen, it's common to call this function update, render, or redraw.
// Updates the animation state and draws a frame
function update() {
// Clear the entire canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update the position of the rectangle
x += 2;
y += 2;
// Draw a rectangle on the screen
// top-left corner x, top-left corner y, width, height
ctx.fillRect(x, y, 70, 50);
// Ask the browser to move on to the next frame
requestAnimationFrame(update);
}
Other than the function definition, the x += 5;
line is new.
This simply adds 5 to the prior value of x
and stores this sum
back in x
. It's shorthand for x = x + 5;
.
Last, but not least, we need to actually call the function we just defined:
// Begin the animation
update();
Let's put it all together. As with previous examples, feel free to tweak numbers, remove/add lines of code and generally experiment until you're sure you have a good grasp on how it all works.
See the Pen block dodger (part 2) by ggorlen (@ggorlen) on CodePen.
I hope you caught that. The rectangle flies off the screen pretty quickly, so run the script again if you missed it.
Over and out
OK, we're animating! I know some of the snazzy animation code is intimidating at first, but stick with it, it'll make sense as the game comes together.
Til next time!