0

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);
    }
BadFeelingAboutThis
  • 14,445
  • 2
  • 33
  • 40
Ferenc Dajka
  • 1,052
  • 3
  • 17
  • 45
  • A suggestion (not related to your problem), why not enable both mouse and keyboard instead of one or the other? Seems like you'd always want the restart button to have the click handler even when a space bar shortcut is enabled. – BadFeelingAboutThis Aug 23 '12 at 17:58
  • Unfortunetly it isn't true. I'd like it to work only with the mouse, or only with the keyboard, it's becouse I want it like this :D. Seriously, that's the goal of a tutorial I'm currently on, so i need to do it like that. – Ferenc Dajka Aug 23 '12 at 18:04
  • did you get a satisfactory solution? If my answer lead you there, please accept it. If not, update your question. – BadFeelingAboutThis Sep 07 '12 at 20:33

1 Answers1

2

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;
}
BadFeelingAboutThis
  • 14,445
  • 2
  • 33
  • 40
  • so the focus remains on the stage, wich is the avoider (the main class), and that's why if i drop the gameScreen, the listener still remains there? – Ferenc Dajka Aug 23 '12 at 17:48
  • Exactly, though technically the stage is the parent of the main class. You do it this way because then as long as the swf/app has focus, you'll get your key events. – BadFeelingAboutThis Aug 23 '12 at 17:53
  • but if i write **this** it supposed to refer to the class I write it in, so in my case the gameOverScreen, isn't it? – Ferenc Dajka Aug 23 '12 at 17:55
  • Yes, but in order to have your gameOverScreen dispatch keyboard events, it has to have focus (or one of it's children do). You could give it focus through code (I'll update the answer to show how) and then it would probably work without attaching the listener to the stage. When you first show the game over screen, the focus is still on whatever you last clicked – BadFeelingAboutThis Aug 23 '12 at 18:02
  • Good idea, but the stage points to null, however i can figure it out, how to pass it to the gameOverScreen. I think it's important to keep the keyboard listening things in the gameOverScreen, it belongs there I suppose as the mouselistening belongs there too. – Ferenc Dajka Aug 23 '12 at 18:09
  • The stage isn't populated until the game over screen is added to the display list, I'll update the code - should have foreseen that – BadFeelingAboutThis Aug 23 '12 at 18:10
  • yeah that's cool, I did the same, thank you :), but it is really not clear, why is the listener added to the main stage, if i say **this**.addEventListener? Check my update please. – Ferenc Dajka Aug 23 '12 at 18:22
  • that should work. is it possible something else in your application is stealing away the focus after you set it? – BadFeelingAboutThis Aug 23 '12 at 18:23
  • using your existing code, change the keyboardEvent listener to be attached to the stage, then in the key push handler, trace out stage.focus to see what has the focus. – BadFeelingAboutThis Aug 23 '12 at 18:25
  • no, sorry for not explaining clearly, my problem with **this** is, that the listener remains active, after dropping the gameOverScreen, why's that, if I add it to the gameOverScreen with: "this.addEventlistener(...", anyways I'm going to check the focus, now it makes yellow boxes on the screen. – Ferenc Dajka Aug 23 '12 at 18:36
  • something ain't rigth, I must hava an other actionlistener on my stage, if i make the method wich handles keypress only listen to the space button, even than if i push up or down keys, the yellow boxes moving, so it has to listen to it somewhere else too – Ferenc Dajka Aug 23 '12 at 18:42
  • Make sure you're using weak listeners, and maybe add a removedFromStage handler that removes the listener. You can get rid of the yellow focus box, a google search on the matter should steer you in the right direction. – BadFeelingAboutThis Aug 23 '12 at 19:50
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15735/discussion-between-londondrugs-mediaservices-and-ferenc-dajka) – BadFeelingAboutThis Aug 23 '12 at 19:52