1

宇宙船ゲームを作ろうとしていますがremoveChild()、発射物や敵船をステージから取り除く方法を使用しているときに問題が発生します。

コードの関連部分は次のとおりです。

var bulletsArr:Array = new Array();
var eShipsArr:Array = new Array();


for (var c = 0; c < eShipsArr.length; c++){
stage.addChild(eShipsArr[c]);
}
....

stage.addEventListener(KeyboardEvent.KEY_DOWN,shoot);

function shoot (e:KeyboardEvent):void{
if(e.keyCode==17){
    var pj:projectile = new projectile();
    pj.x = SShip.x;
    pj.y = SShip.y;
    stage.addChild(pj);
    bulletsArr.push(pj);
    if(bulletsArr.length >= 10){
       bulletsArr = bulletsArr.slice(1,10);
    }
}
}
stage.addEventListener(Event.ENTER_FRAME,checkHit);

function checkHit (e:Event):void{
for (var d = 0; d < bulletsArr.length; d++){
    for(var f = 0; f < eShipsArr.length; f++){
        if(bulletsArr[d].hitTestObject(eShipsArr[f])){
            trace(bulletsArr[d].parent);
            stage.removeChild(bulletsArr[d]); //ArgumentError: Error #2025!!!!
        }
    }
}
}

を使用するremoveChild()stage、トレースは を返しますnull。それがなければ、トレースは戻りますStage object。どちらの場合も、同じエラーがジャンプします。

4

1 に答える 1

0

すでに削除された子を削除しようとしている可能性がありますか?

配列から削除していないため、次のループまたは次のcheckHit呼び出しには、ステージからすでに削除されている可能性のあるオブジェクトのチェックが含まれます。ステージ上にないオブジェクトでもhitTestObjectチェックが返されます。true

テストされていません(配列要素を削除するときの長さの問題を回避するために、箇条書きの配列が逆方向に繰り返されていることに注意してください):

for (var d = bulletsArr.length - 1; d >= 0; d--){
    for(var f = 0; f < eShipsArr.length; f++){
        if(bulletsArr[d].hitTestObject(eShipsArr[f])){
            trace(bulletsArr[d].parent);
            stage.removeChild(bulletsArr[d]); 
            bulletsArr.splice(d, 1); // remove bullet from array
        }
    }
}

編集: 1つの弾丸が2つ以上の船と衝突する可能性がある場合に備えて、テストされていない(正しく入力された)コードを次に示します。必要なのは弾丸を削除することだけです。

for(var f:Number = 0; f < eShipsArr.length; f ++)
{
    for(var d:Number = bulletsArr.length - 1; d >= 0; d --)
    {
        if(bulletsArr[d].hitTestObject(eShipsArr[f]))
        {
            stage.removeChild(bulletsArr[d]);
            bulletsArr.splice(d, 1);
        }
    }
}

交換されたループ、その方法で削除された弾丸は、再度チェックされません。

1つの弾丸が2つ以上の船と衝突する可能性があり、弾丸と衝突した船でも何かを行うことを計画している場合は、次のことを試してください。

    for(var d:Number = bulletsArr.length - 1; d >= 0; d --)
    {
        var bullet:DisplayObject = bulletsArr[d];
        var bulletHitSomething:Boolean = false;

        for(var f:Number = 0; f < eShipsArr.length; f ++)
        {
            if(bullet.hitTestObject(eShipsArr[f]))
            {
                if(!bulletHitSomething)
                {
                    bulletHitSomething = true;
                    stage.removeChild(bullet);
                    bulletsArr.splice(d, 1);
                }
                // do other, ship specific stuff here
            }
        }
    }

現在の箇条書きオブジェクト参照は変数に格納され、すべてのチェックは、配列アクセスを使用して、配列内の要素ではなく、その変数に対して実行されます。存在しないインデックスにアクセスする可能性がある配列アクセス方法とは異なり、この方法では、同じ箇条書きでの連続チェックが問題ないはずです。また、変数は、弾丸がすでに何かに当たったかどうかを格納するため、その弾丸を再度削除しようとはしません。

于 2012-10-20T13:20:20.130 に答える