It's Time to Put Some Wear on those WASD keys.

As you probably know, sometimes it can be more appropriate to use the keyboard for input. If you are a PC gamer then your fingers probably feel comfortable over the WASD keys. It is pretty straightforward to get input from the keyboard. However, you can get into a tricky situation when you are holding down several keys at the same time. In order to detect keys you will set up an event listener on the window. It will look something similar to:

window.addEventListener("keypress", function(e) { console.log(e.key); });

Try pasting that line into the console. Now click back to the webpage and hit some letters. You will notice that they show up in the console. In this next example we are going to see the canvas tool fillText. This can be used to write letters to the canvas. As you will see, you can change the size and font with ctx.font.

<!DOCTYPE HTML>
<html>
<head>
<title>Keyboard Input</title>
</head>
<body style="margin:0px; overflow:hidden;">
<canvas id="canvas"></canvas>
<script>

var can = document.getElementById("canvas");
var ctx = can.getContext('2d');
var cw = can.width = window.innerWidth;
var ch = can.height = window.innerHeight;

window.addEventListener("keypress", function(e) { write(e); });

function write(event) {
  ctx.font="70px Courier";
  clear();
  ctx.fillStyle = "lime";
  ctx.fillText(event.key, cw/2-30, ch/2+30);  
}

clear();
function clear() {
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, cw, ch);
}

</script>
</body>
</html>


  • Line 15 is our listener. Notice that we are attaching the listener to the window. Inside the anonymous function we simply call our own function write(). However, you can also place your commands directly inside the anonymous function.
  • Line 18 declares the font size and type that we wish to use
  • Line 19 calls our clear() function to wipe the screen, we will talk more about functions in the next section.
  • Line 20 sets the color to "lime"
  • Line 21 draws the text to the canvas. fillText takes 3 arguments (text to draw, x pos, y pos)
  • Line 24 this call to clear() runs once as the script starts to make the canvas black
  • Line 25 This is the clear function. It should look familiar, it draws a black rectangle over the whole screen

So the keypress event is great for detecting if letters are being pressed, but have you tried pressing the arrow keys? Nothing happens! To detect arrow keys you will want to listen for the keydown and keyup events. Another problem with keypress is that if you hold down one key and then press another then it will not recognize your are still holding the first key. This is that tricky situation I mentioned up above. Our goal should be to know when any key is being pressed until it is released. This way we could do something like move a character or object on the screen and be able to move and jump at the same time.

A solution is to create an array of all the keys (their numeric keyCodes to keep it simple) that are currently down. Arrays are variables that contain several values. To make an array you will assign a variable to values (or empty) surrounded by solid brackets.

var animals = ["cow", "chicken", "dog", "cat"];

Once again, if you are unclear about arrays, please visit w3schools since they have great tutorials. There are four methods that we will need to operate on our array.

  • push - This adds a value to the end of the array
  • indexOf - This checks if a value exists in an array
  • splice - This can remove an element from an array
  • length - This returns the length of the array


It can be very helpful to play around with these commands in the JavaScript Console in order to get a better understanding of how they work. One feature that is very helpful is when you make an array, once you type its name followed by a period then all the methods (kind of like tools it comes with) are shown to you. This ability to explore objects and their methods is one of the reasons why JavaScript is so nice to work with.

This next example is going to use an array called "keys" to keep track of which keys are currently pressed down. This is accomplished by pushing the keyCode when the "keyup" event is detected and splicing the keyCode when the "keydown" event is detected. Before we add or remove to the array we check the array with an if statement so we avoid any errors like duplicate keyCodes in the array. Now lets move a square around the screen with the arrow keys. First we will need to track the position, this is easy to do with an object that has x and y properties. The next part is a little bit tricky, we need to constantly check to see what keys are down so we can apply movement. We do with animate(). Inside animate we can check to see if the keyCodes we care about are inside the keys array and apply movement if they are. Finally we will call draw() each frame so that the canvas will be cleared and the square will be updated.


<!DOCTYPE HTML>
<html>
<head>
<title>Keyboard Input</title>
</head>
<body style="margin:0px; overflow:hidden;" onload="animate()">
<canvas id="canvas"></canvas>
<script>

var can = document.getElementById("canvas");
var ctx = can.getContext('2d');
var cw = can.width = window.innerWidth;
var ch = can.height = window.innerHeight;

var keys = [];
var box = {x:cw/2, y:ch/2};

window.addEventListener("keydown", function(e) {
  if ( keys.indexOf(e.keyCode) == -1) keys.push(e.keyCode)
});

window.addEventListener("keyup", function(e) {
  var index = keys.indexOf(e.keyCode);
  if (index > -1) keys.splice(index,1)
});

function animate() {
  window.requestAnimationFrame(animate);
  if (keys.indexOf(38) >= 0) box.y -= 1;
  if (keys.indexOf(40) >= 0) box.y += 1;
  if (keys.indexOf(37) >= 0) box.x -= 1;
  if (keys.indexOf(39) >= 0) box.x += 1;
  draw();
}

function draw() {
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, cw, ch);
  ctx.fillStyle = "yellow";
  ctx.fillRect(box.x, box.y, 10, 10);
}

</script>
</body>
</html>


  • Line 6 notice the onload="animate()" that will call the animate function after the body loads
  • Line 15 this is our empty keys array that represents any keys that are pressed
  • Line 16 this is an object that contains x and y set to the middle of the canvas. This is what we move around
  • Line 19 inside our keydown anonymous function we add the newly pressed key's keyCode to the keys array (if its not already there)
  • Line 23 inside our keyup anonymous function we find the index (location) of the key that needs to be removed from the keys array. IndexOf() will return the location of the first match
  • Line 24 with the index from line 23 we check to make sure it exists before we use splice to remove it
  • Line 27 the animate() function will get called over and over to process movement and call draw()
  • Line 28 creates animation by requesting the window to call the animate() function again. This happens as fast as possible
  • Line 29 checks to see if 38 is in the keys array. 38 is the Up Key. If it is there the box is moved up.
  • Line 30 same idea as 29, 40 is the Down Key
  • Line 31 same idea as 29, 37 is the Left Key
  • Line 32 same idea as 29, 39 is the Right Key
  • Line 40 inside the draw function, which gets called over and over from line 33, a yellow box is drawn at the coordinates of the box.


Hopefully you are starting to see how you might be able to turn this code into some type of game. We will talk about functions in the next section.