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.

Enabling Eclipse’s “IntelliSense”

IntelliSense is actually Microsoft’s implementation of auto-completion, used in Visual Studio. Eclipse has a similar feature. It’s called Content Assist. If for some reason yours is turned off (like the way how mine magically did) , here’s how to re-enable it.

Go to Window->Preferences->Java->Editor->Content Assist->Advanced.

content-assist

The one you’d be most interested in is Java Proposals. It list the functions and properties of an object whenever you type a ‘.’ after an object name.

suggestions

 

enjoy

 

Eclipse carriage return fix

Ever got this error in eclipse before “Incorrect line ending: found carriage return (\r) without corresponding newline (\n)” ? Its the singly most annoying thing to happen when opening android layout xml files. Its caused by a bug in the previous version of the editor that made inconsistent line endings in the files. The new editor picks it up as an error.

carriage return

I fixed this by copying and pasting the xml code in notepad then pasting it back inside eclipse. A quicker fix is to press Ctrl + Shit + F and then saving the file.

hope i saved u a headache

Dev Diary #3

Motion Tracking

I really want to do motion tracking for cutscenes. But from what i’ve seen online, getting the equipment alone is thousands of dollars and a lot of work to setup. I found a software called NI-Mate. NI-Mate allows me to do motion tracking with just a kinect. This is what i’ve been looking for, since its costs me no money for equipment (my friend has a kinect) and Blender is free and so is NI-Mate.

Here’s the link to the website.

Using motion tracking would make doing cutscenes less time-consuming and really tell the story in a way that we want it to.

Baking Normal Maps

A common technique artists use for producing high quality game assets is to use render baking. They bake ambient occlusion, specular and normal maps. This can all be done in blender. In my last imagine cup game, i baked ambient occlusion and shadow maps for certain scenes. They looked great, too bad they weren’t in the finished product.

Follow this tutorial on how to bake normals in Blender. Its for Blender 2.5 but it works in Blender 2.6x. An external tool commonly used to do the same thing is xNormal.

I tried it out myself. I sculpted some abs on a 120k poly mesh the baked the normals to a texture and applied it to a 130 poly mesh.

sculpt

This is a technique we’ll definitely be using.

Screenshots

Here are a few development screenshots. They aren’t from levels that will be in the game

climb sky and bloom screen drones

enjoy

Installing Typescript for Visual Studio 2010

I was frustrated that the TypeScript plugin was only available for VS2012. I love TypeScript’s syntax and typesafety. I tried using SharpDevelop to make a TypeScript app but its error reporting is terrible. Also, sharp develop doesnt have a solution system where i can work on multiple projects at the same time. My aim is to create a game engine for the web using TypeScript and i think TypeScript is ideal for the job.

Enough blabbering, lets get our hands dirty. Get 7zip if your dont have it already. You can use winrar if you want. Download the TypeScript installer here.

Open the installer as an archive and extract the TypeScriptLS.vsix_File and rename it to TypeScriptLS.vsix .

open archive

vsix_File

vsix

double click on it to install it

installer

success

If you open visual studio, you’ll see the Typescript Project type. Creating it should give an error about a missing file called Microsoft.typescript.targets. No need to worry, open the installer as an archive with 7-zip again and extract it.

targets

Go in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\ and create a folder called TypeScript. Put Microsoft.typescript.targets in there.

new file

Create your TypeScript project now and it will work.

new project

and run it :)

finish

enjoy :)

OffsetX and OffsetY in Firefox

offsetX and offsetY are used to get the position relative to an element of a mouse event. This works in Chrome and a few other browsers, but not in firefox. At times you will need these values, especially when making canvas games. Here’s a little function to calculate the offset for you:


function getOffset(evt)
{
if(evt.offsetX!=undefined)
return {x:evt.offsetX,y:evt.offsetY};

var el = evt.target;
var offset = {x:0,y:0};

while(el.offsetParent)
{
offset.x+=el.offsetLeft;
offset.y+=el.offsetTop;
el = el.offsetParent;
}

offset.x = evt.pageX - offset.x;
offset.y = evt.pageY - offset.y;

return offset;
}

use it like this:


div.onmousemove = function(evt)
{
var offset = getOffset(evt);
console.log(offset.x+","+offset.y);
}

enjoy :)

Nothing to show

Whenever i tell someone that i make games the first thing they ask is “show a game you’ve made”. I feel bad, since i dont have any. I know how to make games, but i dont have any to show for it. Why? over the years all i’ve made is small demos, prototypes and half done games that i got bored of. Most of which i’ve lost. The few i have completed are the old imagine cup games that i’m not proud to say i made.

The problem is that i keep trying to make big games. The types that require a 50+ person dev team. This leads to me getting bored quickly when i’m not seeing progress or when i look a the insane amount of work i have to do. I usually do this by myself by the way. Recently, its the simple games that are becoming popular. Rovio’s Angry Birds franchise is testimony to this.

After i finish making this years imagine cup game, i’m going to start making simple games and publishing them online. They’ll be in javascript so u can play them in your browser. I may be publishing a few windows games as well. I’ve been working on a c++ game engine and i’m a bit anxious to use it.

Microsoft’s imagine cup ends July 12 So expect my first game somewhere i mid august.

I know i havent been making much dev diary post recently. At this stage in development, its hard to post anything without revealing too much. I’ll start making more in the coming week.

That’s it for now. The up-coming month going to be a difficult one for me, development-wise, so i wont be posting much. I promise to make up for it afterwards.

see ya