0

私は Angry Birds のオプションなどの「ロールアウト」に似たものに取り組んでいますが、かなり重大な問題に直面しています。

ロールアウト自体は単なるトグル ボタンであり、トグル ボタンをタッチすると移動する他のいくつかのボタンが表示リストに追加されています。これらの各ボタンは、Sprite を拡張するクラスであり、タッチ イベント、begin、end、および out の個々のメソッドが含まれています。これらのボタンが初期化される (インスタンス化されない) と、タッチ開始リスナーが追加されます。このようなもの:

    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);

    }

これは、標準のボタン機能 (アップ/ダウン テクスチャとサウンド) のためだけのものです。これに加えて、ゲームを作成するときに、ロールアウト クラスに、発生するカスタム ロジック用の別のイベント リスナーを追加する追加のメソッドがあります。ボタンがタッチされたとき (ボタン自体は別の場所で作成されます)。

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

ロールアウト自体のボタンは、表示されるまで表示リストから削除されます。ロールアウトが閉じられると、ボタンは非アクティブになります(表示リストから削除され、ボタン クラス内の 3 つのボタン リスナーが削除されます)。

ロールアウトを初めて開いて閉じると、すべてが正常に機能します。その後、イベント ディスパッチ システムが不可解に機能しなくなります。位置やタイプに関係なく、画面上のすべての InteractiveObject が使用できなくなります。リスナーがまだロールアウトのトグル ボタンにあるかどうかを調べたところ、ありました。また、表示リストにあるのはロールアウト ボタン自体だけであることも確認しました。

私が気付いたのは、タッチ開始リスナーのボタンの非アクティブ化メソッドでリスナーの削除をコメントアウトするか、AddRolloutButton メソッドのリスナー メソッドに null を渡すと、すべてが正常に機能することです。この問題は、ロールアウト ボタンに同じタイプの複数のリスナーがあり、それらの 1 つまたはすべてを削除したことが原因のようです。

何が起こっているのかについて誰かが何か考えを持っているなら、それは非常に役に立ちます。同じタイプの複数のリスナーを InteractiveObject に追加することは完全に有効であるという印象を受けました。

アップデート:

私が抱えているこの問題によって、TouchEvents だけが壊れているようです。ロールアウトを開いたり閉じたりした後、ステージでマウス クリック リスナーを使用しようとしましたが、それでも機能します。そのため、タッチ イベントだけが壊れています。

4

3 に答える 3

0

AddRolloutButtonメソッドに問題があるようです。正しいリスナー関数を割り当てていますか?

あなたの例では、listener:Function引数はに等しくなければなりません_buttons[index]. OnTouchBegin

または、AddRolloutButtonメソッドを所有するクラスがボタンを制御しているように見えるため、トリガーする必要のあるメソッドがわかっているため、リスナー引数を完全に破棄する可能性があります。

たとえば、次のようになります。

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

ただし、できることはTouchEvent.TOUCH_BEGINDeactivate関数内のを削除しないことです。DisplayObjectがディスプレイリストにない場合、タッチイベントがトリガーされることはありません。これは、ボタンをディスプレイリストに再度追加するたびにリスナーを追加することを心配する必要がないことを意味します。

弱参照を使用するようにリスナーを設定すると、ボタンが不要になったときにボタンがガベージコレクションされるのを妨げることはありません。イベントリスナーに弱参照を使用させるには、addEventListenerメソッドの5番目の引数を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

Initializeロールアウトを閉じた後、ある時点でメソッドを再度呼び出しますか?

コードからは、すべてのイベント リスナーを削除してから、リスナーを再度Deactivate追加しないように見えます。TouchEvent.TOUCH_BEGIN

于 2013-02-24T23:25:23.540 に答える
0

イベントリスナーを削除して何を達成しようとしているのかわかりません。Button にはコールバックへの参照があるため、リスナーがアタッチされているかどうかに関係なく、そのコールバックへの参照があります。リスナーを追加すると、コールバックからボタンへの参照が作成されると思いますか? そうではありません--その逆です

ボタンが表示リストから削除されたときにコールバックを解放したい場合は、リスナーを削除した後にその参照を保持できません。Supervising PresenterRobotLegs Mediatorなどを使用して、これらの依存関係を管理することを検討してください。

あなたのやっていることがイベントシステム全体を狂わせているとは思えません。

私はこれを信じる傾向があります:

        if (リスナー != null)
        {
            _buttons[index].addEventListener(TouchEvent.TOUCH_BEGIN, リスナー);
        }

参照されているボタンが実際にステージ上にあるボタンではないか、リスナーが null であるため、失敗しています。

優先度のあるイベントを追加および削除すると失敗することがあるのを見てきましたが、通常、これは表示リストに反映されていないイベントの場合です

これをテストする方法の 1 つは、メイン ドキュメントまたはステージのタッチ イベントをリッスンして、それらのイベントが発生しているかどうかを確認することです。イベント システム全体が壊れている場合は取得できませんが、リスナー ロジックが間違っている場合は取得できます。

ボタンとイベントの willTrigger プロパティを確認することもできます。

于 2013-02-25T00:28:08.397 に答える