Canyon Runner Tutorial

In this tutorial, we’ll build a canyon running game with JavaScript. The idea is to pilot a ship through a winding canyon, with the player’s score increasing the longer they can avoid crashing into the sides. The canyon veers and narrows, so it gets tricky!

Building this game will involve coding domain objects (pieces the game has to have in order to be the kind of game it is: in our case, a ship and a canyon) as well as implementation details (for example, how to capture user input from the keyboard). The major steps will be:

  1. Set up the canvas (that is, our video game screen) and draw our ship
  2. Write code to allow the player to control the ship
  3. Draw the canyon the player must navigate
  4. Set up a loop to repeatedly advance the ship through the canyon and update our canvas drawing
  5. Write code to detect collisions between the ship and the canyon wall
  6. End the game loop when the ship crashes and display the player’s score

Were going to move pretty quickly, so feel free to discuss on repl talk if you have any questions or want to ask for a more step-by-step explanation.

As idle as a painted ship // Upon a painted ocean

First, we’ll want to create a project using the HTML, CSS, and JS template, since we’ll have one HTML page, one CSS file, and one JS file for our game logic.

Here’s the setup for our `index.html` and `index.css`:



And now: our ship! (We’ll also add a Game class, which is in charge of coordinating all the pieces of our game.) From now on, we’ll be adding code only to the index.js file. Start by adding the following (and try typing it out rather than copying and pasting):

Great! We have a ship, but like our poetic quote says, it’s idle — we have no way to move it (yet). Let’s fix that next.

Up, Up, Down, Down, Left, Right, Left, Right

In order to move our ship around, we’ll have to add code that accepts keyboard input (in our case, the four arrow keys) and uses that input to move the ship. Let’s add the below code just after our Ship class:

We’ll also want to update our Game class’ start() function to register these event handlers:

If we run our code now, click into the canvas, and use the arrow keys, our ship should move around! Our complete code should now look like this:

The Canyon

Now we’ve got a moving ship, but nowhere to maneuver around. Let’s add a Canyon class to the top of our index.js file, above our Ship class:

There’s a lot going on here, so let’s unpack it a little. The constructor() function sets up some useful fields, like this.leftWall and this.rightWall, that we use later to make sure our canyon walls don’t wander outside the bounds of the canvas. The initializeMap() function creates the starting canyon walls, relying on getVectors() to randomly draw them (using our maximum left and right values to make sure we draw inside the canvas). Just like we do for our ship, we include a draw() method for our canyon so we can display it on the canvas.

Our code should now look like this:

But there’s a bug: our canyon walls now vanish when our ship moves! This is because the this.ctx.clearRect() call in the ship’s draw() function clears the canvas before redrawing the ship. Let’s fix that and tie all the pieces of our game together by introducing the main game loop.


Just like the “loop” in REPL, we’ll want to set up a repeating cycle so we can respond to user input. Let’s use JavaScript’s setInterval() function to do that, continuously updating our ship’s position and its flight through the canyon:

Note that we’ve added let intervalId; just after let deltaY = 0;. We want to keep a reference to the interval ID so we can cancel it when the game ends. Check out the MDN documentation for setInterval() linked above; the MDN docs are great for improving you understanding of JavaScript.

Collision Detection

We’re nearly done! Now we’ll want to write some code to make sure we end the game when the ship crashes (that is, when any part of the ship touches the canyon walls). Let’s go ahead and update our loop() function, like so:


Finally, we’ll add scorekeeping logic to our game, completing our code:

And that’s it! You now have your very own canyon runner game in just over 200 lines of JavaScript. How high a score can you get?

If you’re ready for more of a challenge, feel free to fork this REPL and consider adding the ability to pause and unpause the game, add more interesting behaviors (like different canyon layouts or enemy ships), or even add sound effects and music! Here’s a more advanced version of this game that a friend of mine made a few years ago; you can play it here.

I hope you enjoyed this tutorial!

I write poems & programs. More here:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store