Level-Up Coding

Level 6: Listeners and if statements let you respond to input

After moving things on the screen, the next step in making a game is to allow the user to control the action. Javascript does this by setting up listener functions that will be called when events happen. An event is an input from the user, like a key press or a mouse click. This lesson will show you how to set up input listeners and do different things based on the input.


Listening to key presses

To make your program respond to the keyboard, you need to do two things:

The first thing is to write listener functions that can respond to events. An example function that can listen for key presses is as follows:

    var onKeyDown = function(event)
    {
        // print the key code to the console
        console.log(event.keyCode);
    }

This function doesn’t do much yet. It just prints a number in the web console based what key was pressed. Remember that the console is a special place in the browser where you can print messages to help in your program. You learned how to open it in a previous lesson. Each key on the keyboard has a special keyCode. Some of the key codes are shown below. To find out what other key codes are, make a page with the onKeyDown listener function above. Then run the page and type a key. The code for that key will be printed in the web console.

        W: 87           left arrow:  37             space: 32      
        A: 65           right arrow: 39
        S: 83           up arrow:    38
        D: 68           down arrow:  40

The next thing that you need to do is to hook up the listener function so that the page actually calls it when a key press event happens. To do this, in window.onload you would write the following:

    window.addEventListener("keydown", onKeyDown);

Now if you run the page and open the web console, it should print a key code every time you press a key on the keyboard!


Listening to key releases

If you want a function to run whenever a key is released, you have to add another function like onKeyUp to your program, and then add a line of code to hook it up as a listener:

    window.addEventListener("keyup", onKeyUp);

If statements to decide what to do

With the velocity listener functions in place, you can use if statements to change how the ship moves.

An if statement is part of the code that decides to do one thing or another based on some condition. You can use the key codes to change the velocity of the ship when those keys are pressed. In the function ‘onKeyDown’ add the code:

    var ship = gameState.ship;
    if (event.keyCode == 65) 
    {
        ship.vx = -10.0;
    }
    if (event.keyCode == 68) 
    {
        ship.vx = 10.0;
    }

There are a couple of things you should notice about the code. Earlier in the code we used = to mean an assignment (copying the value from the right side to the variable on the left side).

The code event.keyCode == 65 is not an ssignment. The == is a comparison operator, which checks to see if the value in event.keyCode is 65 or not. If the comparison in an if statement is true, then the program runs the code inside the curly braces. If not, then the program skips that code. Here are some of the comparison operators in Javascript:

    ==, !=        equal, and not equal
    >,  >=        greater than, greater than or equal to
    <,  <=        less than, less than or equal to

The else condition

Sometimes you want to do something if a comparison is true, and you want to do something else if the comparison is false. In Javascript, you can make your code do this by using an else statement with an if. Suppose that you want to make the ship move right when you press the right arrow key, and stop if any other key is pressed. You can do this with an else like this:

    var ship = gameState.ship;
    if (event.keyCode == 65) 
    {
        ship.vx = 10.0;
    }
    else
    {
        ship.vx = 0.0;
    }

Stopping when key released

In a lot of games, the player starts moving when you press a key, and then stops moving when you release the key. To do this, you can add a listener function called onKeyUp that sets the velocity to 0 if the A or D keys are released. In code, when you want to check if one of two different conditions is true, you can use the OR operator, which is written as two vertical bars ||:

    var onKeyUp = function(event)
    {
        var ship = gameState.ship;
        if (event.keyCode == 65 || event.keyCode == 68)
        {
            ship.vx = 0;
        }
    }

Finally, you would add the function as a listener to key up events with the following code:

    window.addEventListener("keyup", onKeyUp);

Boolean operators

The OR operator || is called a Boolean operator because it works on Boolean (true/false) values. In Javascript, there is also an AND operator, written && and a NOT operator written !.


Listening to the mouse

To listen to the mouse, you would once again write listener functions to respond to mouse events. Some of the events that you can respond to are mousedown, mousemove, mouseup, and click.

For example, suppose you want to write a function to respond to click events. You could write:

    var onMouseClicked = function(event)
    {
        // get the mouse coordinates relative to the canvas
        var rect = canvas.getBoundingClientRect();
        var mx = event.clientX - rect.left;
        var my = event.clientY - rect.top;

        ....
    }

To add this function as a click listener, you could write this code in window.onload:

    canvas.addEventListener("click", onMouseClicked);

Screen coordinates and canvas coordinates

One of the great things about programming video games is that it gives you a chance to solve geometry and math problems. Dealing with the location of mouse events is one example of this.

You have seen before that when you draw a sprite on the canvas, the coordinates of the sprite are offsets from the top left corner of the canvas. This is true even if the canvas moves on the screen.

The problem is that when you click with the mouse, the mouse coordinates are given to the listener are offsets from the top left corner of the window, not the canvas!

To fix this problem you have to subract the coordinates of the top left corner of the canvas from the mouse position. The figure below shows this situation.

Luckily, Javscript allow you to get the bounding rectangle of the canvas with the function getBoundingClientRect. The code to get mouse position (mx,my) relative to the canvas is given by the code below:

    var rect = canvas.getBoundingClientRect();
    var mx = event.clientX - rect.left;
    var my = event.clientY - rect.top;

Placing the center of a sprite

Suppose you want to set the location of a sprite so that the center is at position (mx,my). If you set the sprite position to (mx,my), then the top left corner of the sprite will be there, not the center. To get the center of the sprite to (mx,my) we have to subract have the width from mx, and half the height from my, as in the following code:

    sprite.x = mx - (sprite.w * 0.5);
    sprite.y = my - (sprite.h * 0.5);

The diagram below shows this graphically.


Terms


Exercise

  1. Copy the example code level6example.html” and save it as an HTML page in its own folder.

  2. Just like you did before, copy the shipImage.png and robotImage.png files to the same folder where you saved the HTML page. You can right click on them and select the “save image as” option to do this.

  3. Add an onKeyDown function that will make the ship go left or right based on key presses, as described above.

  4. Add onKeyDown as a listener to keydown events as described using window.addEventListener, as described in the lesson.

  5. Add onKeyUp function that will make the ship stop when a key is released, as described above. Also, add onKeyUp as a listener to keyup events.

  6. Add mouseClicked as a function that will set the position of the robot so that the center of the robot is at the point you clicked. Also, add mouseClicked as a listener to the canvas that listens to click events.

Once everything is done, the page should move the ship back and forth based on keyboard input, and change the position of the robot based on mouse input.


Bonus Level

  1. Change the if statements in animateGame to stop the ship at the edges of the canvas, rather than wrapping around.