Input for javascript games – part 1

shooter

When making javascript games, you’ll need a way to handle input from the user (whether its from the keypad, mouse, or controller). You can currently do this by responding to input events from the window element this:

window.onkeyup = function(event)
{

}
window.onkeydown = function(event)
{

}

The main focus of this tutorial is for keyboard input. The following will be about mouse and controller input. For the onkeyup and onkeydown events, the only property of interest is keyCode. It is an integer telling which key was pressed. Here’s how you would test if the A key was pressed:


if(event.keyCode == "A".charCodeAt(0))//the character code for A is 65
 consolg.log("a was pressed");

note: ensure the character is upper case.

Handling input for games like this poses 3 problems.

  1. You’ll have to respond to events when the browser fires them, not  when you want to.
  2. Handling events in such a manner will cause your code to be structured oddly since you have to use two functions to determine when a key is up or down.
  3. The third is how the input is sent. If you realize when you press and hold down a key, the event is fired then pauses for about a second then continuously fires afterwords. Try this in any input field right now where the caret is visible; press and hold the left or right key. This is done in order to prevent the cursor from sliding all over the screen when you only want to move the cursor one step to the left or right. This is not suited for games.

this demo highlights all these problems (check the source for problems 1 and 2): unbuffered.html (move the box with the arrow keys)

Lets get back to the first problem. I did a test to see when the browser issues key events. Here’s the code:


<div id="log">
</div>
<script type="text/javascript">
var log = document.getElementById("log");
function print(text)
{
 log.innerHTML+=text+"<br/>";
}

function clear()
{
 log.innerHTML="";
}

window.onkeydown = function(event)
{
 print("keydown");
}

window.onkeyup = function(event)
{
 print("keyup");
}

window.setInterval(function()
{
 print("update..");//updating starts here

print("render..");//rendering ends here

//clear();
},1000);
</script>

and here’s the result:

event cycle

i’d like to handle my input between the beginning of the update function and the end of the rendering function. The result shows that the input is being handled after the render function (same as being before the update function). The solution to this is buffered input. I was first introduced to this when messing around with ogre3d a few years ago: definition and tutorial.

It’s basically storing all the pressed keys in an array whenever input events are handled, then checking them at a later part of the code. Here’s how to do it:


//create an array to hold the state of each key
//true means the key is down, false means its up
var keys = new Array(222);
for(var i=0;i<222;i++)
 keys[i]=false;
window.onkeydown = function(event)
{
 //set value of key in array to false
 keys[event.keyCode]=true;
}

window.onkeyup = function(event)
{
 //set value of key in array to false
 keys[event.keyCode]=false;
}

....

var LeftArrow=37;

....

if(keys[LeftArrow]==true)

player.moveLeft();

here’s a key code reference: http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes

check it out: buffered.html (move the box with the arrow keys)

I created a array of 222 elements to store all the states for the keys (it’s actually less and the array should be fragmented, but i’m going to keep things simple). All elements in the array are set to false, which means they are all up. In the onkeydown event, the value at the keyCode’s index is set to true meaning they key is down. In the onkeyup event, the opposite happens.

So now we’ve got a nice way to handle input. But we’re only half way there. We are only storing the current state of the keys on the keyboard. What about that split second when the user presses or releases a key? checking for keypresses comes in handy for checking if the player pressed the spacebar in order to make the player jump and checking for keyreleases comes in handy for checking if the player releases the ‘x’ key which would fire a cannon that was charged by holding down the said key. There are many other uses.

The solution for this comes by using a second array. One array holds the keys for the previous frame and one for the current frame.

//create two arrays and initialize the values of both to false
var keys = new Array(222);
var prev_keys = new Array(222);
for(var i=0;i<222;i++)
 keys[i]=prev_keys[i]=false;

at the end of each cycle, copy over the current keys to the previous keys

//swap over arrays
for(var i=0;i<222;i++)
prev_keys[i]=keys[i];

In the part of the code the keyup and keydown states are checked using the two arrays:

if a key was up the previous frame and down in this frame then they key was just pressed

function isKeyPressed(key)
{
 if(prev_keys[key]== false && keys[key]==true)
 return true;
 else
 return false;
}

if a key was down the previous frame and up in this frame then they was just released

function isKeyReleased(key)
{
 if(prev_keys[key]== true && keys[key]==false)
 return true;
 else
 return false;
}

check out the demo: buffered_2.html (move the box with the arrow keys and shoot by pressing the X key)

that’s the end of part one. Part two will be about handling mouse input.

source: input.zip

checkout my input library input.js on github. I’ll be adding features from this and the following input tutorials i’m going to make.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s