【问题标题】:Buttons only work once按钮只能工作一次
【发布时间】:2014-06-19 20:05:02
【问题描述】:

我的按钮只工作一次有问题。该按钮触发一个自定义事件。自定义事件触发,并且我的 DocumentClass 上的侦听器第一次将其拾取,但此后任何时间都没有响应。

复制 Click Here,然后点击“开始游戏”,然后点击右上角的菜单按钮,然后点击主菜单,然后点击“开始游戏”,然后点击右上角的菜单按钮,然后注意不能再次点击主菜单。那是我的问题。它应该会继续工作。

DocumentClass 添加子 openScreen。 openScreen 触发 DocumentClass 事件以添加子 playScreen 并删除 openScreen。当单击 playScreen 上的菜单按钮时,playscreen 添加子 menuScreen。 **单击主菜单按钮时,它会触发 DocumentClass 侦听的事件。触发的函数会移除 playScreen 并添加一个打开的 Screen。这一系列事件只有一次完全生效,才会在**步骤时挂断。

文档类

public class DocumentClass extends MovieClip 
{
    public var playScreen:PlayScreen = new PlayScreen();
    public var openScreen:OpenScreen = new OpenScreen();
    public var started:Boolean = false;     

    public function DocumentClass() 
    {
        openScreen.addEventListener( GameEvent.STAR, OnPlayClick);
        playScreen.addEventListener( GameEvent.NG, NewGame);
        playScreen.menuScreen.addEventListener( GameEvent.NG, NewGame, true,  0, true);
        playScreen.menuScreen.addEventListener( GameEvent.MM, onMain);
        addChild(openScreen)


    }

    public function OnPlayClick(gameEvent:GameEvent):void{
        trace("start")

        addChildAt(playScreen,0)
        var tweenX:Tween = new Tween(openScreen, "x", None.easeIn, 0, -480, .5, true);
        tweenX.addEventListener(TweenEvent.MOTION_FINISH, onTweenDone);


    }
    public function NewGame(gameEvent:GameEvent):void{
        removeChild(playScreen)
        playScreen = new PlayScreen();
        addChild(playScreen)
        playScreen.begin()
    }
    public function onMain(gameEvent:GameEvent):void{
        playScreen.removeChild(playScreen.menuScreen)
        this.removeChild(playScreen)
        //openScreen = new OpenScreen();
        openScreen.x = 0
        addChild(openScreen)
        playScreen = new PlayScreen();

菜单屏幕 公共类 MenuScreen 扩展了 MovieClip {

    public function MenuScreen() 
    {
        backButton.buttonMode = true
        backButton.addEventListener( MouseEvent.CLICK, OnBackClick );

        exitButton.buttonMode = true
        exitButton.addEventListener( MouseEvent.CLICK, OnExitClick );

        restartButton.buttonMode = true
        restartButton.addEventListener( MouseEvent.CLICK, OnRestartClick );

        mainButton.buttonMode = true
        mainButton.addEventListener( MouseEvent.CLICK, OnMainClick );

        //NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onSystemKey);

        backButton.AnswerText.text = "Return to Game"
        restartButton.AnswerText.text = "Restart"
        mainButton.AnswerText.text = "Main Menu"
        exitButton.AnswerText.text = "Exit"
    }

    public function OnBackClick(myEvent:MouseEvent):void{
        this.dispatchEvent( new GameEvent( GameEvent.BAC ))

    }
    public function OnExitClick(myEvent:MouseEvent):void{
        //NativeApplication.nativeApplication.exit();

    }
    public function OnRestartClick(myEvent:MouseEvent):void{
        this.dispatchEvent( new GameEvent( GameEvent.NG ))
        trace("restrt click")
    }
    public function OnMainClick(myEvent:MouseEvent):void{
        this.dispatchEvent( new GameEvent( GameEvent.MM ))
        trace("main click")
    }

    protected function onSystemKey(e:KeyboardEvent):void
    {
        if(e.keyCode == Keyboard.BACK)
        {
            e.preventDefault();
            this.dispatchEvent( new GameEvent( GameEvent.BAC ))
        }
        else if(e.keyCode == Keyboard.HOME)
        {
            //handle the button press here. 
        }
        else if(e.keyCode == Keyboard.MENU)
        {
            //handle the button press here.
        }
    }


}

打开屏幕

 public class OpenScreen extends MovieClip 
{

    public var hs:String

    public function OpenScreen() 
    {
        startButton.buttonMode = true
        startButton.addEventListener( MouseEvent.CLICK, OnStartClick );

        exitButton.buttonMode = true
        exitButton.addEventListener( MouseEvent.CLICK, OnExitClick );


        //NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onSystemKey);
        readObject()
        highScoreText.text = String(hs)
        trace(highScoreText.text)
        startButton.AnswerText.text = "Start"
        //restartButton.AnswerText.text = "Restart"
        //mainButton.AnswerText.text = "Main Menu"
        exitButton.AnswerText.text = "Exit"
    }

    public function OnStartClick(myEvent:MouseEvent):void{
        trace(this.hasEventListener( GameEvent.STAR ))
        this.dispatchEvent( new GameEvent( GameEvent.STAR ))


    }
    public function OnExitClick(myEvent:MouseEvent):void{
        //NativeApplication.nativeApplication.exit();

    }


    protected function onSystemKey(e:KeyboardEvent):void
    {
        if(e.keyCode == Keyboard.BACK)
        {

            //NativeApplication.nativeApplication.exit();
        }
        else if(e.keyCode == Keyboard.HOME)
        {
            //handle the button press here. 
        }
        else if(e.keyCode == Keyboard.MENU)
        {

        }
    }

【问题讨论】:

    标签: actionscript-3 flash air


    【解决方案1】:

    看起来原因是因为在您的 onMain 方法中,您从舞台上移除,然后创建了一个全新的播放屏幕实例。所以你的听众会依附于旧的。这也会造成内存泄漏。

    public function onMain(gameEvent:GameEvent):void{
            playScreen.removeChild(playScreen.menuScreen)
            this.removeChild(playScreen)
            //openScreen = new OpenScreen();
            openScreen.x = 0
            addChild(openScreen)
            playScreen = new PlayScreen(); //RIGHT HERE - this is creating a whole new play screen, your listeners are attached to the old one.
    }
    

    大概应该是这样的:(在构造函数中取出播放画面代码,声明时不要实例化)

    //Create a function that kill your current play screen
    public function clearPlayScreen():void {
        if(!playScreen) return; //don't do anything if there isn't a play screen
        playScreen.removeChild(playScreen.menuScreen)
        this.removeChild(playScreen);
    
        //remove your listeners so the old play screen can be garbage collected - other they will all stay in memory causing a memory leak
        playScreen.removeEventListener( GameEvent.NG, NewGame);
        playScreen.menuScreen.removeEventListener( GameEvent.NG, NewGame, true);
        playScreen.menuScreen.removeEventListener( GameEvent.MM, onMain);
    
        playScreen = null;
    }
    
    public function NewGame(gameEvent:GameEvent):void{
        clearPlayScreen(); //kill the old play screen if it exists
    
        playScreen = new PlayScreen();
        addChild(playScreen);
    
        //add the listeners to the new play screen
        playScreen.addEventListener( GameEvent.NG, NewGame);
        playScreen.menuScreen.addEventListener( GameEvent.NG, NewGame, true,  0, true);
        playScreen.menuScreen.addEventListener( GameEvent.MM, onMain);
    
        playScreen.begin();
    }
    
    public function onMain(gameEvent:GameEvent):void{
        clearPlayScreen();
    
        //openScreen = new OpenScreen();
        openScreen.x = 0;
        addChild(openScreen);
    }
    

    【讨论】:

    • 这是一个问题是有道理的,这样做可以解决我的按钮不起作用的问题。新的 playScreen 是我制作新游戏的方式,因为所有游戏机制都包含在 playScreen 中。有没有更好的方法将孩子重置为被调用之前的状态?
    • 可能是一种更高效的方式,但这取决于您的整个应用程序。如果性能足够好,清除和重新实例化并没有什么问题 - 只需确保没有任何内容将先前的播放屏幕保留在内存中(如事件侦听器)
    猜你喜欢
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多