2012-09-07 42 views
1

我正在開發小型Flash遊戲。遊戲包含20個關卡和主菜單。級別之間的轉換是通過刪除幀上的每個對象以及所有事件偵聽器來完成的。然後,該代碼將在下一級別對象...如何從AS3中的對象中自動刪除Event Listener

捕捉和刪除事件偵聽器是通過這個代碼實現:

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,使每一位聆聽到在陣列中添加。第二個函數檢查EventListeners是否仍然存在(不是預先刪除),只是從陣列中刪除每個Listener。

此代碼適用於分配給舞臺的EventListeners。但是,當EventListener直接分配給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個級別。

感謝您的建議。

+0

很難理解你的問題。具體來說:「此代碼適用於未分配給對象的EventListener。當某個EventListener被分配給一個對象時,他不會被添加到該數組中,所以我不能在以後刪除它。「 – BadFeelingAboutThis

+0

我已經上傳的代碼的第一個函數只捕獲通過這種方式添加的addEventListeners: - stage閱讀進度(Event.ENTER_FRAME,啓動);或 - 的addEventListener(Event.ENTER_FRAME,開始); 但是,當我的addEventListener分配給爲前一個對象: - Start_btn.addEventListener(Mouse.CLICK,點擊) ; 該代碼沒有捕獲它,並沒有把它放在一個數組中,這意味着我不能在以後使用第二個函數 – Stefan4024

+0

不知道你是如何覆蓋該階段的addEventListener函數的嗎?你的Start_btn(或者wha tever)將不得不繼承你已經顯示的代碼的類。 – BadFeelingAboutThis

回答

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

不知道會雖然解決您的問題。如果您添加新對象時創建了事件偵聽器,則應在對象被銷燬/刪除時刪除這些偵聽器。

+0

我被設置爲1,因爲一開始我添加一個EventListener將檢查該級別是否通過。所以我不刪除它,因爲我必須再次添加它。 – Stefan4024

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 
} 

這將使你的聽衆停止監聽時,將項目從顯示列表中刪除,並添加時重新添加它們。你必須修改你的數組來包含捕獲階段和弱引用等其他偵聽器信息。如果您不想再次添加它們,只需在removedFromStage處理程序中調用clearEvents(),並完全取出addedToStage偵聽器/處理程序。

這是假設您發佈的代碼(和我的添加)是您希望應用它的所有對象的基類。

+0

你可以給我一些關於代碼的解釋。我不知道它是如何工作的。所以簡單的解釋可以幫助我。 我將第一行添加到構造函數中,我不需要第二行,因爲clearEvents()可以正常工作。此外,我添加了ToStafe功能的代碼,但我再次遇到同樣的問題。所以請給我解釋cod – Stefan4024

+0

如果你在你的資源上執行了removeChild()之後將你的資源保存在內存中,你將只使用addedToStage監聽器/處理器 - 並且計劃稍後使用addChild()再次顯示它們。 – BadFeelingAboutThis

+0

我不明白你是如何覆蓋舞臺的addEventListener函數的,也許如果你更新你的問題來顯示你提供的代碼的上下文。它是你的文檔類嗎?或所有遊戲資產擴展的基礎類? – BadFeelingAboutThis