1
votes

I am working on small flash game. The game contains 20 levels and main menu. The transition between levels is made by deleting every object on the frame and also all event listeners. Then the code adds objects from the next level...

Catching and the removing event listeners is done by this code:

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 = []
    }

This code overrides internal addEventListeners and makes every Listener to be added in an array. Second function checks if the EventListeners is still there(not prevoiusly removed) and the just remove every Listener from the array.

This code works fine for EventListeners that are assigned to the stage. However, when an EventListener is assigned directly to an Object then it's not added to the array, so it doesn't get removed automatically later.

I know that when you remove the object, also you remove the Event Listeners assigned to it. But when I add that object again the Listeners run twice. You can freely move through levels, so you can go back and forth. And when you go back I recieve problems. System is overused and is woring slower, because the amount of Event Listeners that are running is doubled.

So, can you modify this code or give me an advice how can I catch EventListeners that are assigned to Object and eventually remove them.

Code:

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

And so on for the next 20 levels.

Thanks in advice.

2
Having a hard time understanding your question. Specifically: "This code works fine for EventListeners that are not assigned to an object. When some EventListener is assigned to an Object then he is not added to the array, so I can not remove it later."BadFeelingAboutThis
First function from the code that I have uploaded only catches addEventListeners that are added on this way: - stage.addEventListener(Event.ENTER_FRAME, started); or - addEventListener(Event.ENTER_FRAME, started); But when I addEventListener that is assigned to an object for ex: - Start_btn.addEventListener(Mouse.CLICK, clicked); The code doesn't catch it and doesn't put it in an array, which means that I can't remove later using second functionStefan4024
not sure how you're overriding the stage's addEventListener function? Your Start_btn (or whatever) would have to inherit the class whose code you've shown.BadFeelingAboutThis
Where (what context) does your first block of code fit? Is it a part of your main class? or another class?BadFeelingAboutThis
Every function is part of Main class. Also function Main only conatins one line that calls function Intro.Stefan4024

2 Answers

0
votes

Arrays indices start from 0, clearEvents should be :

 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 = []
 }

Not sure if that will fix your problem though. If you have event listeners that are created when you add new objects you should remove those listeners when the object is destroyed/removed.

0
votes

Removing an object (removeChild(object)) does NOT automatically remove it's event listeners. You would need to do that yourself. Something like this could work:

in your class constructor:

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

The handlers:

//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
}

This would make your listeners stop listening when the item is removed from the display list, and re-add them when added. You'd have to modify your array to include the other listener information like capture phase and weakReference. If you don't want them added again, just call your clearEvents() in the removedFromStage handler and take out the addedToStage listener/handler altogether.

This is assuming that the code you posted (and my additions) is the base-class of all the object you want it applied to.