User Controls



Key Events

Many of the programs you have written in java and javascript are top-down programs. In other words, once they start, they have a sequence of code to execute that can only be altered by user input. Graphic programs, like a game or app, are often event based programs. This means that there are pieces of code, written in functions, that are sitting and waiting for some type of user interaction: a key press, mouse click, mouse over, etc. Games often have both types of code: pre-planned, ordered code that will run and event based code waiting for users to participate.

Listeners
In most languages that support event based programming, the event code is waiting in a function to be called. In order for the event to be recognized by the program, a listener is created. A listener is a piece of code that runs in the background of the program and 'listens' for the event to trigger. In order to make key press events, we will need to generate two listeners: one for when a key is pressed (keydown) and one for when a key is released (keyup).
function initialize(){
    ...
    document.addEventListener("keydown", "keyDownHandler");
    document.addEventListener("keyup", "keyUpHandler");
    ...
    update();
}
The addEventListener takes two parameters. The first is the event, chosen from a pre-determined list of JS events. The second is a function name, created by the user, that will run the code for that event. A full list of JS events can be found here.
The listeners for a game should be placed in the initialize() function.
Key Variables
In order to keep track of the keys that are being pressed and released, we will need a variable for each key control in the game. For now, we will just look at left and right movement, so we will track the left and right arrow keys. These variables will be used to track the current state of the key throughout the game. For our purposes, we will assign true to mean the key is down and false to signify that the key is up (not pressed). We will need to declare and initialize these variables for use in the game.
...
var leftKey, rightKey;
...
function initialize(){
    ...
    leftKey=false;
    rightKey=false;
    ...
    update();
}
Note that both keys are initialized to false as they will not be pressed at the start of the game.
Key Codes
Each key on the keyboard has a unique keycode. That code can be accessed through the JavaScript keyCode property of the key event. It is important for us to know the key codes for each of the keys that we are using. This will allow us to interpret the information provided by the keydown or keyup event that is triggering an action.
Turn the switch on to use the key code finder...

Off On
X


Event Handlers
Once we have the key codes for the game control keys that our players will be using, we can write our event handler functions. An event handler function will take the event as a parameter. The event parameter will allow us to access the keyCode from that event. We can then switch on that keyCode to alter the values of our key variables that we declared and initialized earlier in the program.
function keyDownHanlder(e){
    switch(e.keyCode){
        case 37: leftKey=true; break;
        case 39: rightKey=true; break;
    }
}

function keyUpHandler(e){
    switch(e.keyCode){
        case 37: leftKey=false; break;
        case 39: rightKey=false; break;
    }
}
Remember that we set the listeners earlier to call these event handler functions. When a key is pressed, it's key variable is set to true. When a key is released, it's key variable is set to false.

These functions are written in open code, usually after the draw method.

Animation Using Key Events

Instead of basing game animation on timing, we will now be animating based on key events. When a key is pressed, we can make certain actions occur like making the character move a certain direction, jump, squat, shoot something, etc. This type of code typically happens in the update method, as we will be altering the values of variables to make any of these things occur. Additionally, we will now make our movement conditional on the values of our key variables.
function update(){
    if(rightKey && charX<canvas.width-char.width){
        charX+=3;
    }
    else if(leftKey && charX>0){
        charX-=3;
    }
    ...
}
In the code above, we assume that the variable charX, representing the character's x position has been declared and initialized. We are also assuming that there is an image variable, called char, that has been initialized with a jpg or png file of appropriate size. The movement value (+=3/-=3) is a random value based on decisions made for movement within the game.
Animating Sprite Movement
Assuming that we have a simple sprite with one row of images, we have to make a decision when using key based controls - do we want the animation to continue when the character is standing still or not? Based on the answer, we either increment the frameCount conditionally (using the key variables) or absolutely (as in our animations.
if(rightKey && charX<canvas.width-char.width){
    charX+=3;
}
else if(leftKey && charX>0){
    charX-=3;
}
if(rightKey || leftKey)
    charFrame++;
The frame advancement is not controlled in the same condition as the movement because you might want the animation to continue as the character is on the edge of the screen, even though they cannot physically move any further.
Multidirectional Sprite Movement
Often, sprite sheets have a variety of movements for a character. They can walk different directions, jump, shoot, kick, etc. These movements are typically all saved in the same sheet, so that files don't have to be switched, with each action/direction in its own row. At right, is an example of the cat sprite that is designed for walking in two opposite directions.

When dealing with a sprite sheet with multiple movements, we need to control the row that the sheet is moving through as well as the column, so we will need to add a new variable that tracks the FrameY, similar to how we control column movement with FrameX. This value will be multiplied by the frame height to position in the correct row and will change whenever the user presses a key that changes direction, as opposed to the x values that increase based on timing.
<script>
    ...
    var catFrameY, catFrameX;
    var catFrameH, catFrameW;
    ...
    function initialize(){
        ...
        catFrameY=0;
        catFrameX=0;
        catFrameH=57;
        catFrameW=43;
        ...
    }
    function update(){
        ...
        if(rightKey && charX<canvas.width-char.width){
            catFrameY=0;
            catX+=3;
        }
        else if(leftKey && charX>0){
            catFrameY=1;
            catX-=3;
        }
        if((rightKey || leftKey)&& timing!3==0)
            catFrame++;
        }
        ...
    }
    function draw(){
        ...
        ctx.drawImage(cat, catFrameX*catFrameW, catFrameY*catFrameH, catFrameW, catFrameH, catX, catY, catFrameW, catFrameH);
        ...
    }
</script>