[英]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.
問題始終在相關類( EnemyClass
, BulletClass
或MissileClass
)中的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.