Input Handling

...But, first...

Generalised Smileys


A bit of magic to turn a "default" smiley into a totally
general one: any position, any size, any angle...
function drawSmileyAt(ctx, cx, cy, radius, angle) {
    ctx.save();

    ctx.translate(cx, cy);
    
    ctx.rotate(angle);
    var scale = radius / g_defaultSmileyRadius;
    ctx.scale(scale, scale);
    
    ctx.translate(-g_defaultSmileyX, -g_defaultSmileyY);
    
    drawDefaultSmiley(ctx);
    
    ctx.restore();
}

Input Events


As previously discussed, input from the user (or, in fact, from any external source) arrives into the computer in the form of "events" --- or, at a lower level, "interrupts".

Depending on the Operating System, a program may have direct access to these events, or it may be able to detect them indirectly via "polling" (i.e. asking about them).

Also, although the state of external inputs can potentially change at any time, it is helpful to hold them constant for the duration of each individual update or frame.

A Polling System


In a polling system, input events such as key presses will be handled by the OS, which will therefore be able to keep track of which keys are "up" or "down" at any given time.

Individual programs are then able to easily query the state of the keyboard at any particular time.

An Event System


In an event-driven system (such as JavaScript in the browser), the program has to deal with the "raw" events itself, and perform its own state-tracking over time.

In some ways, this provides a lot of flexibility,
but in others it can be a bit of an annoyance...

Interacting With Events


In the browser, events are queued up when they arrive,
but will only be processed when the currently active
script-functions have finished their execution i.e.
when the function call-stack is empty.

Listening to Events


You declare your program's interest in handling a particular kind of event by registering a "listener" for it.

Like this...

window.addEventListener("keydown", handleKeydown);
window.addEventListener("keyup", handleKeyup);

Handling Events


...and the handler function itself could be like this:
var KEY_X = 'X'.charCodeAt(0); // This is a "constant"

// NB: Handler assumes the presence of a global canvas context, `g_ctx`
function handleKeydown(evt) {
    if (evt.keyCode === KEY_X) {
        g_ctx.fillRect(10, 10, 50, 50);
        console.log("You pressed X!");
    }
}
The global variable is "needed" because there's no direct way of passing other params into the handler.

(However, there are indirect ways, such as "closures", which I'll ignore here).

Future Proofing


In practice, I recommend that you do it like this:
var g_keys = [];

function handleKeydown(evt) {
    g_keys[evt.keyCode] = true;
    
    // Maybe do stuff here based on the new state of g_keys
}

function handleKeyup(evt) {
    g_keys[evt.keyCode] = false;
}

function initKeyboardHandlers() {
    window.addEventListener("keydown", handleKeydown);
    window.addEventListener("keyup", handleKeyup);
}
This is a bit closer to how it's done in real games.

Still Pumped From
Using The Mouse


Handling mouse-events is pretty similar.
Here's a simple example:
var g_mouseX = 0, g_mouseY = 0;

function handleMouseMove(evt) {
    g_mouseX = evt.clientX - g_canvas.offsetLeft;
    g_mouseY = evt.clientY - g_canvas.offsetTop;
    
    // Maybe do stuff here with g_mouseX and g_mouseY
}

function initMouseHandlers() {
    window.addEventListener("mousemove", handleMouseMove);
}

Which Leads Me Nicely Onto...

Homework


Take your "default smiley" from last week, modified
so that it can now be drawn in a generalised form
(I've done that part for you), and allow it to be controlled
INTERACTIVELY, IN REAL-TIME, BY YOU!

i.e. get it to move about subject to input events which you
(or any other suitable human/animal/robot/whatever)
generate "live" at runtime.

It's almost like a game!
...almost.

PS: Watch Out For
"Broken Smileys"



Input Handling

By Pat Kerr

Input Handling

With a particular focus on the JavaScript event loop.

  • 3,193