Key.isDown - AS3

As I’m sure most of you who’ve tried the ‘Flex SDK 2’ or ‘Flash 9 Public Alpha’ are aware, Key.isDown is no more.

Unfortunately, that leaves me in a bit of a bind. The ‘obvious’ solution is to keep track of KEY_DOWN and KEY_UP events, but that doesn’t actually work.

  1. Hold down a key, any old key
  2. Change application focus off of flash
  3. Release your key
  4. Change application focus back to flash

The key is now ‘stuck’ until pressed and released.

This is what we in the game development industry refer to as a “BUG”.

There are ‘FOCUS’ based events in Flash, but they are only for Flash’s internal keyboard focus. There don’t appear to be any notifications about application focus… which would be handy, because not only could I clear my cached key status if focus is lost, but I could also PAUSE the game and prompt to click on it to resume.


package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;

    // Properties for base Sprite (main)
    [SWF( backgroundColor='0x000000', frameRate='10', width='320', height='240')]
    public class main extends Sprite
    {
        private var keybits : Array /*uint*/ = new Array( 0,0,0,0, 0,0,0,0 );
        public function main()
        {
            stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDown );
            stage.addEventListener( KeyboardEvent.KEY_UP, keyUp );
        }
        public function isKeyDown( code:int ):Boolean
        {
            return 0 != (keybits[code>>5] & (1<<(code&0x1f)));
        }
        private function keyDown( event:KeyboardEvent ) : void
        {
            // Update key array
            var code:uint = event.keyCode;
            keybits[code>>5] |= (1<<(code&0x1f));
            trace("Down:" + code + "..." + keybits);
        }
        private function keyUp( event:KeyboardEvent ) : void
        {
            // Update key array
            var code:uint = event.keyCode;
            keybits[code>>5] &= ~(1<<(code&0x1f));
            trace("Up:" + code + "..." + keybits);
        }
    }
}

Copy/paste that into main.as
With the Flex SDK…
mxmlc -compiler.debug main.as
fdb main.swf
(Enter c when prompted - this thing works just like gdb, only not quite close enough that any gdb front-end will work with it. The trace output will appear in the DOS window.)

Do the procedure as outlined above.

Press other keys to see the original key’s state is unchanging until it’s pressed again.

This could be annoying to users if (for example) another web page or application grabs focus away, or they miss the window with the mouse, and Flash loses focus. Especially if they had something like a ‘shoot’ key down with a finite ammo supply, or the ‘move’ key down near the edge of a cliff.

The question: Does anybody have a solid work-around for this?

I already posted a message to Adobe about maybe either…

  1. Put something like Key.isDown back into the libraries.
  2. Generate all applicable KEY_UP events whenever Flash loses focus.
  3. Add an APP_FOCUS sort of event set.

A quick test in Flash 8 shows that this code works as expected under Flash 8 (the control key status updates correctly whether Flash has focus or not).


(Layer 1:Frame 1)
import Key;
function onEnterFrame():Void
{
         trace( "U"+Key.isDown(Key.UP)+" D"+Key.isDown(Key.DOWN)+" L"+Key.isDown(Key.LEFT)+" R"+Key.isDown(Key.RIGHT) );
}

Another possible solution could be to ‘mix’ AS2 and AS3 code in the project and communicate between them somehow. Then I could write the bulk of the code in AS3 and have a tiny lib for the lost features… namely some wrapper around Key.isDown(). This might have to be my solution for the near term.