-->

Flash AS3 KeyboardEvent not firing

2019-06-11 08:49发布

问题:

I have a class like this:

public class GameOverScreen extends MovieClip {
    public function GameOverScreen(useMouseControl:Boolean) {
        if(useMouseControl){
            Mouse.show();
            restartButton.addEventListener(MouseEvent.CLICK, onClickRestart);
        }
        else{
            this.addEventListener(KeyboardEvent.KEY_DOWN, onPushSpace);
        }
    }

    public function onClickRestart(mouseEvent:MouseEvent):void{
        dispatchEvent(new NavigationEvent(NavigationEvent.RESTART));
    }

    public function onPushSpace(keyboardEvent:KeyboardEvent):void{
        trace(keyboardEvent);
        dispatchEvent(new NavigationEvent(NavigationEvent.RESTART));
    }...

It's an ending screen of a game. (surprise!) I want it to restart my game if I push down the space button, or click on the restartButton on the screen. As you can see the screen gets a boolean value in the constructor, wich decide that we're using keyboard or mouse to control the game. It works well with mouse, but with the key, i have to click on the restart button (wich is on the screen), till it does nothing, and after clicking it, and I push a button I get the playScreen, but my keylistener is somewhy still in work, and if i push any key, it restarts the game.

The point of my main class is: if the player dies, he get a gameOverScreen, and the playscreen will be dismissed, the gameOverScreen also gets a listener, it listens for an event called RESTART, if the event is dispatched, a new playScreen is created, and the game over dismissed.

public class Avoider extends MovieClip { ....
     public function onAvatarDeath(avatarEvent:AvatarEvent):void {

        var finalScore:Number = playScreen.getFinalScore();
        var finalTime:Number = playScreen.getFinalTime();

        gameOverScreen = new GameOverScreen(useMouseControl);
        gameOverScreen.addEventListener(NavigationEvent.RESTART, onRequestRestart);
        gameOverScreen.setFinalScore(finalScore);
        gameOverScreen.setFinalTime(finalTime);
        addChild(gameOverScreen);

        playScreen = null;
    }

    public function restartGame():void {
        playScreen = new PlayScreen(useMouseControl);
        playScreen.addEventListener(AvatarEvent.DEAD, onAvatarDeath);
        addChild(playScreen);

        gameOverScreen = null;
    }

    public function onRequestRestart(navigationEvent:NavigationEvent):void {
        restartGame();
    }

I hope it's understandable, if not please note it what is not clean. Thanks

UPDATE

my onAddToStage function

public function onAddToStage(event: Event):void{
    stage.focus = this;
this.addEventListener(KeyboardEvent.KEY_DOWN, onPushSpace);
    }

回答1:

Try adding your key listener to the stage:

stage.addEventListener(KeyboardEvent.KEY_DOWN, onPushSpace);

Otherwise your current class needs to be in focus, which is why only works until you've clicked it. Be sure to remove that listener when your game over screen is done though.

Alternatively you could give your game over screen focus through code when it loads (in the constructor):

public function GameOverScreen(useMouseControl:Boolean) {
    this.addEventListener(Event.ADDED_TO_STAGE,addedToStage,false,0,true);

    if(useMouseControl){
        Mouse.show();
        restartButton.addEventListener(MouseEvent.CLICK, onClickRestart, false, 0, true);
    }
    else{
        this.addEventListener(KeyboardEvent.KEY_DOWN, onPushSpace, false, 0, true);
    }
}

private function addedToStage(e:Event):void {
    stage.focus = this;
    stage.stageFocusRect = false;  //make sure there's no dumb yellow rectangle
}

Also a little tip - I notice your not removing your game over screen from the display list once it's finished. You'll want to do that to make it truly go away (and remove your restart event listener).

public function restartGame():void {
    playScreen = new PlayScreen(useMouseControl);
    playScreen.addEventListener(AvatarEvent.DEAD, onAvatarDeath);
    addChild(playScreen);

    gameOverScreen.removeEventListener(NavigationEvent.RESTART, onRequestRestart);
    removeChild(gameOverScreen);
    gameOverScreen = null;
}