1

私は小さなフラッシュゲームに取り組んでいます。ゲームには 20 のレベルとメイン メニューが含まれています。レベル間の遷移は、フレーム上のすべてのオブジェクトとすべてのイベント リスナーを削除することによって行われます。次に、コードは次のレベルからオブジェクトを追加します...

イベント リスナーのキャッチと削除は、次のコードによって行われます。

override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
    {
        super.addEventListener(type, listener, useCapture, priority, useWeakReference);
        arrListeners.push({type:type, listener:listener});

    }

    private function clearEvents():void
    {
       for(var i:Number = 1; i<arrListeners.length; i++){
          if(this.hasEventListener(arrListeners[i].type))
        {
             this.removeEventListener(arrListeners[i].type, arrListeners[i].listener);
          }
       }
       arrListeners = []
    }

このコードは、内部の addEventListeners をオーバーライドし、すべてのリスナーを配列に追加します。2 番目の関数は、EventListeners がまだそこにある (以前は削除されていない) かどうかをチェックし、配列からすべてのリスナーを削除するだけです。

このコードは、ステージに割り当てられた EventListener に対して正常に機能します。ただし、EventListener が Object に直接割り当てられた場合、配列には追加されないため、後で自動的に削除されることはありません。

オブジェクトを削除すると、それに割り当てられたイベント リスナーも削除されます。しかし、そのオブジェクトを再度追加すると、リスナーが 2 回実行されます。レベルを自由に移動できるので、行ったり来たりできます。そして、あなたが戻ってきたとき、私は問題を受け取ります。実行中のイベント リスナーの量が 2 倍になるため、システムが過度に使用され、動作が遅くなります。

では、このコードを修正するか、Object に割り当てられた EventListeners をキャッチして最終的に削除する方法を教えてください。

コード:

package

{
     Public Class Main extends MovieClip
     {
          Public function Main()
          {
               Intro();
          }
          Private function Intro():void
          {
             //Constructor contains a lot of addChild and a EventListeners. So I will upload what I think i important for this problem.
             Play_btn.addEventListener(MouseEvent.CLICK, clicked);
             function clicked (e:MouseEvent):void
             {
                 clearEvents();
                 clearChild(); // function that removes all children on stage
                 FirstLevel();
              }
           }
           Private function FirstLevel():void
           {
              //Also adding children and EventListeners, that affect the gameplay
              Next_level_btn.addEventListener(MouseEvent.CLICK, clicked1);
              function clicked1 (e:MouseEvent):void
             {
                 clearEvents();
                 clearChild();
                 SecondLevel();
              }
              Main_Menu_btn.addEventListener(MouseEvent.CLICK, clicked1);
              function clicked1 (e:MouseEvent):void
              {
                 clearEvents();
                 clearChild(); 
                 Intro();
               }
            }

次の 20 レベルについても同様です。

アドバイスありがとう。

4

2 に答える 2

0

オブジェクト(removeChild(object))を削除しても、そのイベントリスナーは自動的に削除されません。あなたはそれを自分でする必要があるでしょう。このようなものが機能する可能性があります:

クラスコンストラクター内:

super.addEventListener(Event.ADDED_TO_STAGE,addedToStage,false,0,true);  //only if you want the listeners added back again the next time this object is added to the stage  eg. addChild(this)
super.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage,false,0,true);

ハンドラー:

//this runs whenever the object is added to the display list
//if you don't want the listeners re-added, remove this function.
private function addedToStage(e:Event):void {
    for(var i:int=0; i<arrListeners.length; i++){
        super.addEventListener(arrListeners[i].type, arrListeners[i].listener, arrListeners[i].useCapture, arrListeners[i].priority, arrListeners[i].useWeakReference);
    }
}

//this runs whenever the object is removed from the display list
private function removedFromStage(e:Event):void {
    for(var i:int=0; i<arrListeners.length; i++){
        super.removedEventListener(arrListeners[i].type, arrListeners[i].listener, arrListeners[i].useCapture);
    }

    //OR if you want the listeners gone forever, use your clearEvents() method instead of the for loop above
}

これにより、アイテムが表示リストから削除されたときにリスナーがリスニングを停止し、追加されたときにそれらを再度追加します。キャプチャフェーズやweakReferenceなどの他のリスナー情報を含めるように配列を変更する必要があります。それらを再度追加したくない場合は、removeedFromStageハンドラーでclearEvents()を呼び出し、addedToStageリスナー/ハンドラーを完全に削除します。

これは、投稿したコード(および私の追加)が、適用するすべてのオブジェクトの基本クラスであると想定しています。

于 2012-09-07T20:48:37.560 に答える
0

配列のインデックスは0から始まり、clearEventsは次のようになります。

 private function clearEvents():void
 {
     for(var i:int= 0; i<arrListeners.length; i++){
        if(this.hasEventListener(arrListeners[i].type))
        {
             this.removeEventListener(arrListeners[i].type, arrListeners[i].listener);
        }
     }
     arrListeners = []
 }

それでも問題が解決するかどうかはわかりません。新しいオブジェクトを追加するときに作成されるイベントリスナーがある場合は、オブジェクトが破棄/削除されたときにそれらのリスナーを削除する必要があります。

于 2012-09-07T20:38:40.200 に答える