0

我正在研究类似于“愤怒的小鸟”“推出”选项等的东西,但我遇到了一个相当大的问题。

推出本身只是一个切换按钮,显示列表中添加了几个其他按钮,当您触摸切换按钮时它们会移动。这些按钮中的每一个都是扩展 Sprite 的类,并包含用于触摸事件、开始、结束和结束的单独方法。当这些按钮被初始化(未实例化)时,将添加触摸开始侦听器。像这样的东西:

    public function Initialize():void 
    { 
        this.addEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin, false, int.MAX_VALUE);
    }

    private function OnTouchBegin(e:TouchEvent):void
    {
        this.removeEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin);
        this.addEventListener(TouchEvent.TOUCH_END, OnTouchRelease, false, int.MAX_VALUE);
        this.addEventListener(TouchEvent.TOUCH_OUT, OnTouchOut, false, int.MAX_VALUE);
    }

    private function OnTouchRelease(e:TouchEvent):void
    {
        this.addEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin, false, int.MAX_VALUE);
        this.removeEventListener(TouchEvent.TOUCH_END, OnTouchRelease);
        this.removeEventListener(TouchEvent.TOUCH_OUT, OnTouchOut);
    }

    private function OnTouchOut(e:TouchEvent):void
    {
        this.addEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin, false, int.MAX_VALUE);
        this.removeEventListener(TouchEvent.TOUCH_END, OnTouchRelease);
        this.removeEventListener(TouchEvent.TOUCH_OUT, OnTouchOut);
    }

然后,当这些按钮从屏幕上隐藏时,会调用一个方法来删除当前在它们上活动的任何侦听器:

    public function Deactivate():void 
    {
        this.removeEventListener(TouchEvent.TOUCH_OUT, OnTouchOut);
        this.removeEventListener(TouchEvent.TOUCH_END, OnTouchRelease);
        this.removeEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin);

    }

这仅适用于标准按钮功能(向上/向下纹理和声音),除此之外,当我制作游戏时,在我的 rollout 类中,我有一个额外的方法,它将为应该发生的自定义逻辑添加另一个事件侦听器当按钮被触摸时(按钮本身在其他地方创建)。

    public function AddRolloutButton(listener:Function):void
    {
        if (listener != null) 
        {
            _buttons[index].addEventListener(TouchEvent.TOUCH_BEGIN, listener);
        }

卷展栏本身的按钮会从显示列表中删除,直到它们被显示。当 rollout 关闭时,按钮被停用(从显示列表中删除,并且按钮类中的 3 个按钮侦听器被删除)。

在我第一次打开和关闭推出时,一切都运行良好。在那之后,事件调度系统就莫名其妙地死掉了。屏幕上的每个 InteractiveObject,无论位置或类型如何,都会变得不可用。我在推出切换按钮上追踪了听众是否仍然存在,并且确实存在。我还确认推出按钮本身是显示列表中唯一的东西。

我注意到的是,如果我在触摸开始侦听器的按钮的 deactivate 方法中注释掉侦听器删除,或者在 AddRolloutButton 方法中为侦听器方法传入 null,则一切正常。问题似乎源于在推出按钮上有多个相同类型的侦听器,然后删除其中一个或全部。

如果有人对正在发生的事情有任何想法,那将非常有帮助。我的印象是向 InteractiveObject 添加多个相同类型的侦听器是完全有效的。

更新:

我遇到的这个问题似乎只破坏了 TouchEvents。在打开和关闭推出后,我刚刚尝试在舞台上使用鼠标单击侦听器,这仍然有效。所以,只有触摸事件会被破坏,如果这有帮助的话。

4

3 回答 3

0

好像你的AddRolloutButton方法出了点问题。您确定要分配正确的侦听器功能吗?

在您的示例中,listener:Function参数应等于_buttons[index]. OnTouchBegin

或者,由于拥有该AddRolloutButton方法的任何类似乎都在控制按钮,因此您可能会完全放弃 listener 参数,因为您知道需要触发什么方法。

例如像这样:

public function AddRolloutButton():void {
    var currentButton:MyButtonClass = _buttons[index] as MyButtonClass;
    currentButton.addEventListener(TouchEvent.TOUCH_BEGIN, currentButton.OnTouchBegin);
    [...]
}

但是,您可以做的是永远不要删除函数TouchEvent.TOUCH_BEGIN中的Deactivate。当 DisplayObject 不在显示列表中时,将永远不会触发触摸事件。这意味着您不必担心每次要再次将按钮添加到显示列表时添加侦听器。

如果您将侦听器设置为使用弱引用,则不会妨碍按钮在不再需要时被垃圾收集。要使您的事件侦听器使用弱引用,请将addEventListener方法的第五个参数设置为 true。

addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

public function Initialize():void { 
    this.addEventListener(TouchEvent.TOUCH_BEGIN, OnTouchBegin, false, int.MAX_VALUE, true);
}
于 2013-02-24T21:45:07.513 回答
0

我不确定您要通过删除事件侦听器来完成什么。由于 Button 具有对回调的引用,因此无论是否附加了侦听器,它都具有对该回调的引用。您是否认为添加侦听器会创建从回调到按钮的引用?它没有——反之亦然

如果您真的希望 Button 在从显示列表中删除时释放回调,那么它在删除侦听器后就无法保留该引用。考虑使用Supervising PresenterRobotLegs Mediator 之类的东西来管理这些依赖项。

我严重怀疑整个事件系统是否被你正在做的事情所困扰。

我更倾向于相信这一点:

        如果(听众!= null)
        {
            _buttons[index].addEventListener(TouchEvent.TOUCH_BEGIN, listener);
        }

失败了,要么是因为引用的按钮不是实际在舞台上的那个,要么是因为 listener 为 null ..

曾经见过添加和删除具有优先级的事件可能会导致失败的情况,但通常这是与未在显示列表上传播的事件有关。

您可以测试的一种方法是简单地收听主文档或舞台上的触摸事件,看看您是否收到了这些事件。如果整个事件系统很糟糕,你不会得到它们,但如果你的监听器逻辑是错误的,你会的。

您可能还想检查按钮和事件的 willTrigger 属性。

于 2013-02-25T00:28:08.397 回答
0

Initialize您是否在关闭推出后的某个时候再次调用该方法?

从您的代码看起来好像您删除了所有事件侦听器,Deactivate然后再也不添加TouchEvent.TOUCH_BEGIN侦听器。

于 2013-02-24T23:25:23.540 回答