SyntaxScrewer's Blog

February 19, 2010

KeyBoarder – A multiple key press / state manager library

Filed under: ActionScript 3.0,Flash — geekymaira @ 3:55 pm

Download Link : Keyboard Library

I’ve recently started using the KEY_DOWN events a lot to detect movement in some projects I’m working on.
But I faced problems , solutions to which are available and I incorporated them too. But I wanted a better
optimized solution. So , I created my own library to handle it.

Let me explain the problem(s) and how I solved them using my library.

stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDownHandler);
var speed =10;
function onKeyDownHandler(evt:KeyboardEvent):void
{
	if (evt.keyCode == 37)  //Left key pressed
	{
		player_mc.x -=speed;  //Move left
	}

	if (evt.keyCode ==38) //Up key pressed
	{
               player_mc.y -=speed;    //Move up
	}

if (evt.keyCode ==39) //Right key pressed
{
player_mc.x +=speed;  //Move right
}

if (evt.keyCode ==40) //Down key pressed
{
player_mc.y +=speed;  //Move down
}

Copy & paste the code above in Flash and make a movie clip with an instance name of “player_mc” on the stage.
Now try using the arrow keys to move it around. You should observe 2 things.

1. When you keep any key pressed, the MC moves and pauses for a brief moment and then continues moving smoothly.

2. If you hold down any key and while it’s held down, you press another key, then the last key pressed takes precedence.
This causes a problem when you want your movie clip to move diagonally. Try keeping the down key held down and while its
down press the left. See what happens……….. So does that mean we can’t move diagonally using this method at all ??

3. Well you can, but you’d have to press both keys at the same time. But this is too hard to do. I mean you can’t expect your
users to be so precise at holding down keys. After all, theyre humans 😛

These problems can be tackled by storing the state of the key in a Boolean variable in the KEY_DOWN , KEY_UP handlers. You also move your application
logic inside a function that you call repeatedly from ENTER_FRAME.

Lets see how this is done by modifying the code above


var speed =10;
var bKeyDown:Boolean;
var bKeyUp:Boolean;
var bKeyLeft:Boolean;
var bKeyRight:Boolean;

stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUpHandler);
stage.addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);

function onKeyDownHandler(evt:KeyboardEvent):void
{
	if (evt.keyCode == 37) //Left key pressed
	{
		bKeyLeft=true;
	}

	if (evt.keyCode == 38) //Right Up pressed
	{
    bKeyUp=true;
	}

	if (evt.keyCode==39)
	{
	bKeyRight=true;  //Move right
	}

	if (evt.keyCode ==40)
	{
	bKeyDown=true;
	}
}

function onKeyUpHandler(evt:KeyboardEvent):void
{
	if (evt.keyCode == 37) //Left key pressed
	{
		bKeyLeft=false;
	}

	if (evt.keyCode == 38) //Right Up pressed
	{
    bKeyUp=false;
	}

	if (evt.keyCode==39)
	{
	bKeyRight=false;  //Move right
	}

	if (evt.keyCode ==40)
	{
	bKeyDown=false;
	}
}

function onEnterFrameHandler(evt:Event):void
{
	getKeys();
}

function getKeys():void
{
	if (bKeyLeft)  //Left key pressed
	{
		player_mc.x -=speed;  //Move left
	}

	if (bKeyUp) //Right key pressed
	{
               player_mc.y -=speed;    //Move up
	}

	if (bKeyRight)
	{
	player_mc.x +=speed;  //Move right
	}

	if (bKeyDown)
	{
	player_mc.y +=speed;  //Move down
	}
}

Copy and paste the modified code and now test your movie. It works perfectly now , doesnt it !!!! . So that’s great then , you’d say :). Well, it is no doubt
but I realized its not one of the best ways to achieve things. Using a 4 Byte Boolean variable for each key just seemed like memory wastage when all I wanted to
do was check if the key was on or off. This in a “perfect” world should be accomplished by using 1 bit per key, since that’s all we need to store a 0 & 1. Sadly, I
couldn’t find a BIT datatype in AS. I’m still researching. As of now, I’ve got a working solution which uses 1 Byte per key instead of 4 Bytes. That’s quite a lot of
saving when you want to detect the whole keyboard!!!!

So how did I do it ?

Well, I used a ByteArray class to hold multiple Bytes. For now I store 93 bytes in it, since I could only find keyCodes for 93 keys on my keyboard. I’m pretty sure
I’m not going to be needing more for a while. Anyway, so the ByteArray serves as a snapshot of the Keyboard keys at all times. I use bitwise operations (AND and OR) to set and unset the bytes in the ByteArray in the KEY_DOWN and KEY_UP event handlers
respectively. Each byte of the ByteArray serves as a location of a key. That basically means that every byte in the ByteArray is responsible for saving the state
of a particular key. I have manually mapped the ByteArray locations (indexes) to the keyCodes using a Dictionary Hash. Lastly, for each keyCode I have declared
a constant. This is just so that I can refer to the keys using proper names instead of keycodes. 😀

There are some issues that I want to sort out, but not now. If any of you know why these things are happening and how to sort them out, I’d really like to know.

The issues are :

– Sometimes I can hold down 4 keys at a time, sometimes only 3 keys, sometimes 5 keys. Dunno why.

– I haven’t been able to get ALT and F10 to work. The key presses for these keys seem to be handled from outside the swf.
In the flash player (by the Flash Player process) and in the Browser (by the Browser process). [I think!]

– I still feel that using 1 Byte per key is memory wastage. I want to use 93 bits instead. Is there any datatype which allows me to do that ? or can I make one ?

Download Link : Keyboard Library
It includes an example too !! Hope this benefits people. I know I’m going to use it. 🙂

Cheers!

-SyntaxScrewer

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

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

Create a free website or blog at WordPress.com.

%d bloggers like this: