views:

1166

answers:

2

N.B. Keep in mind the difference between key code and character code. For example, the number 1 (one) and the character ! (bang) both have the same key code but different character codes. Likewise, the number 7 from the row of numbers and the number 7 from the numpad have different key codes but the same character codes.

I'm programming a music rhythm game in Adobe Flex and would like to bind keyboard keys. This isn't a problem, but I certainly would have a problem, say, setting the default keys to A, S, D, and F and telling the user that this is the case.

If you take a look at the documentation for flash.ui.Keyboard, you'll see that there are constants for keyboard keys to key codes. However, these are only available in Adobe AIR and not the browser. This makes sense since not all operating systems and keyboards are alike (or present!), so key codes can vary.

So, how can I assign default keys that have meaning instead of picking key codes and praying?

My only sane thought is to store the character codes for the key bindings and then provide an character code to String mapping so I can tell the user what to press. However, my gut tells me that this will break in subtle or not-so-subtle ways. Like CAPSLOCK.

Thanks.

Update: I am currently using radekg's answer, but I still think that this will break easily. I would feel more comfortable with some persuasion that this is correct.

+3  A: 

Hi, according to Flash 8 documentation you can simply rely on ASCII codes. Take a look at these topics of the Flash 8 documentation:

As far as I'm aware of all modern operating systems use standard ASCII. These codes have not changed since Flash 5 era. To compare letters if you don't want to rely on ASCII codes:

private function compareChar(code:Number):void {
    if ( "a" == String.fromCharCode( code ).toLowerCase() ) {
        trace("A pressed");
    } else {
        trace("You pressed " + String.fromCharCode(code));
    }
}
...
compareChar(65); // 65 is A
compareChar(96); // 96 is numpad 0

However I think you can rely on ASCII codes. Hope this helps.

radekg
I think your event.keyCode's should be code's instead. I accidentally found the String global function docs instead of the String class docs and thus missed fromCharCode. Also, I didn't think to use toLowerCase(), so thanks for that.
Andrew Keeton
Also, see the edit I made about key code vs. character code.
Andrew Keeton
Thank you for pointing out these mistakes, fixed. Regarding fromCharCode - here is the URL to the docs (if anyone wants to check it quickly): http://livedocs.adobe.com/flex/3/langref/String.html#fromCharCode().toLowerCase() is required as String.fromCharCode(65) returns "A" and not "a". Of course the condition could be changed to:if ("A" == String.fromCharCode( code ) ) ...
radekg
+1  A: 

Radekg is mostly correct.

Flash has a built in Class flash.ui.KeyLocation with four static properties: LEFT, RIGHT, NUM_PAD, STANDARD. This means that you can have a definitive idea which key has been pressed, even if the keyboard has been remapped. If you this in combination with String.fromCharCode, you should be able to solve this problem rather neatly.

Your final code might look like:

import flash.ui.KeyLocation;
import flash.events.KeyboardEvent;

function handleKeyboardEvent( event:KeyboardEvent )
{
    // This will work for a majority of the keys.
    var key:String = String.fromCharCode( event.charCode ).toLowerCase();

    // Use strict comparison
    if( event.keyLocation !== KeyLocation.STANDARD )
    {
        // The key is a number, then it needs to be re-identified.
        if( event.keyLocation == KeyLocation.RIGHT  )    key = "r" + key;
        if( event.keyLocation == KeyLocation.LEFT   )      key = "l" + key;
        if( event.keyLocation == KeyLocation.NUM_PAD)   key = "n" + key;
    }

    switch( key )
    {
        case "r1":
            // Do something with the one which is not on the keypad.
            break;
        case "n.":
            // Do something with the number pad's period.
            break;
        case "n":
            // Do something with the letter N.
            break;
    }
}

I will admit, I am not certain what will happen with String.fromCharCode and control keys (F1, Alt, Ctrl, etc), but the KeyboardEvent does support event.shiftKey, event.ctrlKey, event.altKey

Christopher W. Allen-Poole
Very creative answer with KeyLocation! I guess I'll just have to accept that there's no "pretty" way to do this.Since I'm targeting the browser, Flash doesn't get focus for the function keys (which is a shame, it would be nice to have them).
Andrew Keeton
Have you tried ExternalEvironment.call( "setFocus( " + Application.application.id + " );" )? (Forgive me if my syntax is a bit off). It is far from perfect, but it allows you to force the browser to set focus on the swf, and therefore its child components.
Christopher W. Allen-Poole