簡體   English   中英

在調用相關命令之前從屏幕中刪除對象(錯誤#1009)

[英]Object removed from screen before the relevant command is called (Error #1009)

我很抱歉,如果它要求太多,但我現在太困惑了。 我正在為AS3中的侄子制作這個非常簡單的射擊游戲。 這一切似乎都運行得很好,除了一個非常惱人的錯誤,每隔一兩次或第三次啟動游戲就會突然出現。

IT是Error #1009: Cannot access a property or method of a null object reference. 問題始終在相關類( EnemyClassBulletClassMissileClass )中的parent.removeChild(this)命令。 這種情況在兩種情況下發生:調用Main checkFinishConditions方法並且需要刪除EnemyClass實例時。 所以,如果我得到#1009錯誤,這是否意味着該實例已被刪除? 第二種情況是在Main類中檢查inst.hitTestObject(enemyInstance) 這是否意味着EnemyClass實例已經被刪除了? 說實話,我完全迷失了。

private function checkCollision():void 
        {
            //loop through missiles
            for (var i:int = 0; i < aMissileArray.length; i++) {
                //get the current missile
                var currentMissile:missileClass = aMissileArray[i];
                //loop through enemies
                for (var j:int = 0; j < aEnemyArray.length; j++) {
                    var thisEnemy:EnemyClass = aEnemyArray[j];                                      
                    if (currentMissile.hitTestObject(thisEnemy)) {                          
                        var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);                       
                        addChild(thisExplode);
                        currentMissile.destroyThis();
                        aMissileArray.splice(i,1);
                        thisEnemy.deleteEnemy();
                        aEnemyArray.splice(j, 1);                       
                        aDamageArray.splice(j, 1);  
                        scoreValueText += 1;    
                        j--;
                        i--;
                    }
                    //break;
                }
            }
            //loop through bullets
            for (var l:int = 0; l < aBulletArray.length; l++) {
                //get the current missile
                var currentBullet:BulletClass = aBulletArray[l];
                //loop through enemies
                for (var k:int = 0; k < aEnemyArray.length; k++) {
                    var currentEnemy:EnemyClass = aEnemyArray[k];                                       
                    if (currentBullet.hitTestObject(currentEnemy)) {                        
                        currentBullet.destroyThis();
                        aBulletArray.splice(l, 1);                          
                        aDamageArray[k] -= 1;   
                        l--;
                        if (aDamageArray[k] < 1) {              
                            //create an explosion           
                            var thisBulletExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);                       
                            addChild(thisBulletExplode);                    
                            currentEnemy.deleteEnemy();
                            aEnemyArray.splice(k, 1);                           
                            aDamageArray.splice(k, 1);
                            scoreValueText += 1;    
                            k--;

                        }
                        break;
                    }
                }

            }

        }

有很多代碼需要查看,但我看到的一個潛在問題是:

        for each(var currentDieEnemy:EnemyClass in aEnemyArray) {                                                                               
            aEnemyArray.splice(0, 1);
            currentDieEnemy.deleteEnemy();                                  
        }  

潛在的問題是你“假設”這個循環的順序是基於數組的實際索引順序的順序。 您可能希望在那里留下痕跡來驗證實際發生的情況,因為我相信它們可能會出現故障。

有關詳細信息,請參閱此問題 - For-Each Loop AS3:方向是否有保證?

因此,想象一下場景中第3個項目是第一個並且您在0索引處拼接項目的場景。 現在,您在數組中有一個項目從顯示列表中刪除,但不是從數組中刪除。 那么當你到達那個項目時會發生什么? 幾乎所描述的內容都會發生,因為parent屬性為null,因為您已經從顯示列表中刪除了它。

解決這個問題的方法是做這樣的事情:

while (aEnemyArray.length > 0)
{
   var currentDieEnemy:EnemyClass = aEnemyArray[0];
   currentDieEnemy.deleteEnemy();
   aEnemyArray.splice(0,1);
}

我在這段代碼中發現了另一個問題:

        for (var j:int = 0; j < aEnemyArray.length; j++) {
            var thisEnemy:EnemyClass = aEnemyArray[j];                                      
            if (currentMissile.hitTestObject(thisEnemy)) {                          
                var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);                       
                addChild(thisExplode);
                currentMissile.destroyThis();
                aMissileArray.splice(i,1);
                thisEnemy.deleteEnemy();
                aEnemyArray.splice(j, 1); // now array composition is different.                       
                aDamageArray.splice(j, 1);  
                scoreValueText += 1;                    
            }
        }

循環遍歷數組並在循環索引處拼接項時,必須意識到數組的組成會發生什么。 這是一個例子

假設敵人3因碰撞而需要拼接。 鑒於您的代碼,這是發生的事情:

Before (j == 2)
(0) enemy1
(1) enemy2
(2) enemy3
(3) enemy4
(4) enemy5

AFTER
(0) enemy1
(1) enemy2
(2) enemy4
(3) enemy5

因此,當循環繼續時,j現在將遞增並等於3。

結果是,敵人4沒有被評估,因為陣列的組合崩潰以填充由拼接創建的洞,並且您沒有調整循環索引變量。

那么,在這種情況下你可以做的只是簡單地減少塊末尾的循環索引變量,如下所示:

 aEnemyArray.splice(j, 1); // now array composition is different.                       
 aDamageArray.splice(j, 1);  
 scoreValueText += 1;   
 j--;   // decrement loop index variable.

因此,雖然這是一個解決方案,但這里要點的主要內容是在拼接后更改陣列的組成。

是的,你是以一種奇怪的方式從數組中拼接你的對象。 首先,您將遍歷循環中的數組並進行拼接。 這可能導致幾個子彈的問題,當他們應該或不說移動時不會觸發碰撞。 一旦你調用bullets.splice(i,1);看看你是否在索引i處運行子彈循環bullets.splice(i,1); 接下來要迭代的子彈變為位置i ,然后你增加i並且該子彈仍然未被處理。

接下來,您有嵌套循環,並在內部循環中從OUTER循環中刪除對象。 這意味着一旦你刪除了外部循環的對象,你的內部循環現在無效,你必須搶先終止內部循環。

        //loop through bullets
        for (var l:int = aBulletArray.length-1; l>=0; l--) {
            // first, traverse both arrays backwards
            //get the current missile
            var currentBullet:BulletClass = aBulletArray[l];
            //loop through enemies
            for (var k:int = aEnemyArray.length-1; k>=0; k--) {
                var currentEnemy:EnemyClass = aEnemyArray[k];                                       
                if (currentBullet.hitTestObject(currentEnemy)) {                        
                    currentBullet.destroyThis();
                    aBulletArray.splice(l, 1);                          
                    aDamageArray[k] -= 1;   
                    if (aDamageArray[k] < 1) {              
                        //create an explosion           
                        var thisExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);                     
                        addChild(thisExplode);                  
                        currentEnemy.deleteEnemy();
                        aEnemyArray.splice(k, 1);                           
                        aDamageArray.splice(k, 1);
                        scoreValueText += 1;                            
                    }
                    // and since we don't have "currentBullet" anymore, do this
                    break;
                }
            }
        }

修復所有其他迭代通過你進行拼接的數組,就像我在這部分代碼中所做的那樣,你應該避免在這些循環中出現1009錯誤。

此外,您不應發布整個項目代碼,而是僅發布相關部分,例如報告為拋出錯誤的整個函數,並解釋產生錯誤的行 - 它在錯誤的堆棧跟蹤中寫為數字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM