0

そのため、JavaScriptでゲームを設計していますが、衝突検出機能に関連するものを削除する方法に問題があります。それは小惑星なので、いくつかのオブジェクトはそれに応じて名前が付けられています。

私の衝突検出機能は、プレイヤーと小惑星、または弾丸と小惑星の間に衝突があるかどうかをチェックするように設計されています。弾丸と小惑星の場合、弾丸と小惑星の両方が消えると予想されます。

ただし、衝突をチェックする方法を考えると、衝突した弾丸と小惑星の両方を削除するのは難しいようです。これが私の関連コードです:

for (var i=0;i<$_.mapObjs.length;i++) { //get one object to check
    var superBox = $_.mapObjs[i].hitBox; //get it's properties
    var objectName = $_.mapObjs[i].name;
    var isAsteroid =(objectName.indexOf("asteroid") == -1)?false:true; //is the object an asteroid?
    for (var y=0;y<$_.mapObjs.length;y++) { //get the object to check it against
        if (objectName !== $_.mapObjs[y].name) { //if we are not checking the object against its self
            var subName = $_.mapObjs[y].name;
            var subIsAsteroid = (subName.indexOf("asteroid") == -1)?false:true; //is the second object an asteroid?
            if (!(isAsteroid) || !(subIsAsteroid)) { //if we are not checking two asteroids against each other
                var subBox = $_.mapObjs[y].hitBox;
                var collision = rectIntersectsRect(superBox,subBox); //check for a collision using rectIntersectsRect
                if (collision) { //if there is a collision
                    if ((objectName == "player" && subIsAsteroid) || (isAsteroid && subName == "player")) { //if either of the objects are the player, then the player dies
                        if (!player.invincible)
                            player.death(); 
                    } else if ((objectName == "blankObject" && subIsAsteroid) || (isAsteroid && subName == "blankObject")) { //if either of the objects are a bullet, then we destroy the asteroid
                        Console.log(i + "," + y); //this is the problem area
                        Console.log("getting rid of " + objects[i].name + " and " + objects[y].name);
                        if (subIsAsteroid) { //splice the asteroid out of the second array
                            objects.splice(y,1);
                        } else { //splice the asteroid out of the first array
                            objects.splice(i,1);
                        }
                    }
                }
            }
        }
    }
}

さて、小惑星と弾丸の両方が衝突したときに消える必要があるので、私は変更します

if (subIsAsteroid) {
    objects.splice(y,1);
} else {
    objects.splice(i,1);
}

objects.splice(y,1);
objects.splice(i,1);

ただし、衝突が発生するたびに、この関数は、両方の位置が弾丸と小惑星のオブジェクトを参照しているy場合でも、配列から2つのオブジェクトをランダムに削除します。i私は何が間違っているのですか?

4

2 に答える 2

1

.splice()ランダムな要素を削除するだけでなく、.splice(y,1)操作で1つの要素を削除すると、後のすべての要素のインデックスがy以前より1つ少なくなり、後のすべての要素が「上に移動」します。したがって、iがより大きい場合はy、必要な要素を参照しなくなります。

インデックスが高い要素を最初に削除すると、問題はありません。

objects.splice(Math.max(y,i), 1);
objects.splice(Math.min(y,i), 1);

そうは言っても、との関係はあなたのコードからはわかり$_.mapObjsませobjectsんが、問題が発生する可能性があると思います。$_.mapObjsループインデックスを使用して、yおよびループインデックスとして反復するネストされたループがありますが、その後、に基づいてiから要素を削除し、からのインデックスを削除します。これらの2つの配列には、同じ順序で同じ要素がありますか?これは、「ランダムな」要素の削除を説明している可能性があります。スプライシングする必要がありますか?その場合、次のループ反復で要素をスキップしないように、削除後に調整する必要があります。objectsyi$_.mapObjs$_.mapObjsyi

于 2012-08-28T05:59:44.017 に答える
0

これは、最初のインデックスをスプライスすると、配列が変更されるためと考えられます。これは、2番目のインデックスが正しい場合と正しくない場合があることを意味します。要素のインデックスが変更されたためです。このようなことをすることをお勧めします:

objects[y] = null;
objects[i] = null;

while( (remIndex = objects.indexOf(null)) !== -1 ){
    objects.splice(remIndex, 1);
}

デモ

于 2012-08-28T05:41:31.217 に答える