views:

2899

answers:

3

I'm writing a flash application in Flex/AS3, and I can't seem to assign keyboard focus to it. I was mindful of this problem early on in development and added a splash screen with a "play now" button, to entice the user to click. However, the user must then click a second time on the application for the keyboard to work!

To make matters worse, I have an in-game shortcut that returns you to the main menu. If you return to the main menu then click the "play now" button, the SWF loses focus again!

I'm probably messing up children objects or accidentally destroying an object that captured the keyboard focus, but I'm not quite sure how it works. Can you help point me in the right direction?

My application is a single .SWF file, and I am running it directly in my browser (not calling it via a webpage, though I will eventually). Here is the file in question:

http://www.space-squid.com/game/Main.swf When you click on "Normal" you have to click a second time to actually grab the keyboard focus. :( Feel free to ask questions!

Edit: Here's some code I'm using.

Some of the first code that executes in my primary class:

empty_sprite = new Sprite();
addChild(empty_sprite);
empty_sprite.stage.addEventListener(keyboard hooks...);

I've also tried this just in case I should have set the hooks on my root object:

this.stage.addEventListener(keyboard hooks...);

In case the otherwise empty sprite was causing issues:

background_image = new BackgroundImage();
background_image.x = etc etc alignment data;
addChild(background_image);
background_image.stage.addEventListener(keyboard hooks...)

In all of these examples my keyboard hooks work fine, as long as I click the second time.. but never the first. :(

SECOND EDIT: Well I've narrowed the problem down. Perhaps someone can help me straighten this out, it's probably a structure problem:

public function Main {
    Some stuff...
    empty_sprite = new Sprite(); // Create a new stage sprite
    addChild(empty_sprite);
    empty_sprite.stage.addEventListener(keyboard hooks...);        

    addChild(BackgroundImage); // I lay down my background image which is persistant

    addChild(PlayNowButton); // I display my PlayNow button to the screen

    More stuff...
}

public function StartGame() {
    removeChild(PlayNowButton); // This is the point of failure; this removes focus.
    removeChild(otherMenuOptions);
    ...
    addChild(gameComponents);
}

As you can see, I create the play now button - and it appears that becomes the object of focus. My keyboard events aren't being trapped as it's the background that is looking for the focus. Not sure if that makes sense, hopefully someone can straighten me out with this!

If I comment out that single line (removeChild(PlayNowButton)) the game works perfectly fine and retains keyboard focus - with the downside of having a "playnow" button overlaid on the screen forever.

To be honest I'm not even sure if the game itself ever receives focus on the first click but I'm not sure how to test for that.

A: 

I'm assuming this is a browser project?

Here is how I do it:

package com.whatever.utilities {

    import flash.external.ExternalInterface; 

    public class Browsers {

        public static function FocusThisSwf():void {
            if(!ExternalInterface.available)
                return;
            ExternalInterface.call("eval", "document.getElementById('" +
                ExternalInterface.objectID + "').focus()");
        }
        // ...
     }
     //...
}

Any hiccups, make sure your embed/object markup has an ID and Name attribute!

Ben
Updated the question; this would work to give the SWF focus but clicking "play now" removes it again. :(
Andy Moore
Assuming there is only one SWF in your HTML/XML document, once it has focus it shouldn't ever lose it - unless something else in the document or a browser add-on is interfering.Do you have a live demonstration, or a pastie of the page source?*(ed: if it isn't in a document, you'll have no end of browser troubles)*
Ben
I have an example up here: http://www.space-squid.com/game/Main.swfWhen you click on "Normal" you have to click a second time to actually grab the keyboard focus.
Andy Moore
@18:32 April 27 - I looked at your example, and it was working. Is this because you have since fixed it?
Ben
Yep fixed it and posted an answer below for myself. I've got to wait before I can mark it though :)
Andy Moore
+1  A: 

The code you are looking for is:

gameWorldObject.stage.focus = this;

Since Flash has obtained focus, your keyboard event handler is simply not focused within the flash application itself. You can switch where the current focus is within the application using the above code.

Alternatively, instead of destroying the PlayNow button, making it invisible will do the trick. Then make it visible again later when you need it to. Very easy if it's a MovieClip or a Sprite object:

PlayNowButton.visible = false; // or true obviously, as the case may be

(It's hard writing to myself this way)

Andy Moore
A: 

thanks. another guy, another project, but gameWorldObject.stage.focus = this; worked for me

alex