# Key Press Handler

I have made a class to import into my projects to more easily handle the state of the keyboard so I can use stuff like:

if(Keys.returnKey(37)){


As opposed to setting up key listeners.

Please give this code a general review:

/*
ALWAYS DO THIS FIRST:
Keys.init(stage);

THEN YOU CAN DO THESE:
Keys.returnKey(5);
Keys.returnArray(37,38,39,40);
Keys.returnLastKeyPressed(37,38,39,40);
*/
package{

import flash.events.KeyboardEvent;
import flash.display.DisplayObjectContainer;

public class Keys{

private static var _key_arr:Array=[];
// Contains boolean values for each keycode
private static var _last_key:int=0;
// Last key pressed
private static var _last_valid_key:int=0;
// Last valid key pressed

// PUBLIC FUNCTIONS:

public static function init(STAGE:DisplayObjectContainer){
// Prepares class for use, call this once before you start using the other functions

for (var i=0; i<222; i++){
_key_arr[_key_arr.length]=false;
}

}

public static function returnKey(INDEX:int):Boolean{
// Returns a single value from _key_arr at the index of INDEX

return _key_arr[INDEX]

}

public static function returnArray(... args):Array{
// Returns values from _key_arr to the locations passed as the parameter(s)

var returnMe:Array=[]

for (var i=0; i<args.length; i++){
returnMe[i]=_key_arr[args[i]];
//Extracts the values of the keys passed in as args from the key array.
}

return returnMe;
}

public static function returnLastKeyPressed(... args):int{
// Returns the keyCode of the key most recently depressed

if(args.indexOf(_last_key)!=-1){
_last_valid_key=_last_key;
}

return _last_valid_key

}

// PRIVATE FUNCTIONS:

private static function keyD(event:KeyboardEvent){
// Sets the pressed key's value to true and sets the last key pressed

_key_arr[event.keyCode]=true;

_last_key=event.keyCode;
}

private static function keyU(event:KeyboardEvent){
// Sets the pressed key's value to false

_key_arr[event.keyCode]=false;
}
}
}


Looking at it from a general perspective...

Put your comments that describe functions in javadoc-style outside your functions. Comment blocks before functions are a common format when it comes to describing a function. Because it's at the same indentation level as the function, it can't be mistaken as a comment about a specific section of your function.

Additionally, end each statement with a semicolon. Even when it's not required, for some people it's just as annoying as not ending your sentences with a period. More importantly, by putting the semicolon there, you state that the statement is finished. Right now, it looks like you wanted to say more... but forgot and moved on. Your code then feels unfinished.

Looking at it from a performance perspective... (since it's tagged as such)

From the official documentation, it states that:

As a result of its restrictions, a Vector has three primary benefits over an Array instance whose elements are all instances of a single class:

Performance: array element access and iteration are much faster when using a Vector instance than they are when using an Array.

Type safety: in strict mode the compiler can identify data type errors. Examples of data type errors include assigning a value of the incorrect data type to a Vector or expecting the wrong data type when reading a value from a Vector. Note, however, that when using the push() method or unshift() method to add values to a Vector, the arguments' data types are not checked at compile time. Instead, they are checked at run time.

Reliability: runtime range checking (or fixed-length checking) increases reliability significantly over Arrays.

The trade-offs for this are that you need to use a sequential set of indices and that you must contain a single type.

for (var i=0; i<222; i++){
_key_arr[_key_arr.length]=false;
}


But that's what you're doing anyway, so you could just use a vector. That should give it a speed up. Let's look at some more things.

    public static function returnArray(... args):Array{
// Returns values from _key_arr to the locations passed as the parameter(s)

var returnMe:Array=[]

for (var i=0; i<args.length; i++){
returnMe[i]=_key_arr[args[i]];
//Extracts the values of the keys passed in as args from the key array.
}

return returnMe;
}


args.length triggers a recalculation of the length of the array. This is unneeded if the array's length doesn't change. Thus, I prefer to write the following (and it's a standard I follow when writing my own for loops, unless I'm toying with the index or the array's length):

for(var i:uint = 0, isize:uint = args.length; i < isize; i++){
returnMe[i]=_key_arr[args[i]];
}


This tends to be faster. Of note here are two things.

Namely that

1. I define isize as the length of the array
2. I use uint.

You are not using arrays that will reach the size of MAX_INT, thus there is no reason to use int. args.length returns an uint, and there is a performance penalty for comparing int with uint, compared to comparing uint with uint (because it has to convert it first).

Moving on...

The official documentation for KeyboardEvent.keyCode states (and so should your IDE) that its datatype is uint. So make your _last_key and _last_valid_key of datatype uint, as they can't hold negative values anyway. Alternatively, initialize them to -1 to indicate that no keys have been pressed yet.

Additionally, since a vector (you're gonna make your _key_arr a vector, right?) can't have negative indices, alter public static function returnKey(INDEX:int):Boolean to require a uint as well.