ミニオン オブジェクトの ArrayList があり、シールドがミニオンと衝突したときに、そのミニオンを ArrayList から削除したいと考えています。ただし、1つの方法でしか機能させることができず、他の方法では機能しません。誰でも理由を説明できますか?
3 つのケースすべてで、Android の Renderer の onDrawFrame() メソッドを使用しているため、いつ呼び出されるかを制御できません。ただし、3つの方法すべてのコードは次のとおりです。
方法 1: (機能しません)
public void onDrawFrame(GL10 gl) {
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
問題は、最後の行minions.remove(indexesToRemove.get(i));
が実際にはミニオンを削除しないことです。適切なインデックスで呼び出されます。デバッガーをステップ実行してまっすぐに実行しましたが、配列リストはまったく変更されていません。どうしてこれなの?実際、デバッガーでは、その行「minions.remove(indexesToRemove.get(i));」何十億回も呼ばれます。
方法 2: (まだ機能しません)
public void onDrawFrame(GL10 gl) {
synchronized(minions){
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
}
ここで、私は考えました...「おそらく、完全に同期されていないため、drawFrame が何度も呼び出され、間違ったタイミングで配列リストにアクセスしているため、ロックする必要があります。しかし、それでも機能しません。再び、その行minions.remove(indexesToRemove.get(i));
は適切なインデックスで適切に呼び出されますが、実際にはオブジェクトを削除しません.画面上の盾がミニオンにぶつかるのを見ていますが、ミニオンには何も起こりません(配列リストから削除されません)
方法#3(これは実際に機能します)
public void onDrawFrame(GL10 gl) {
ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
int len = colliders.size();
for(int i=0; i<len; i++){
GameObject collider = colliders.get(i);
if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
minions.remove(collider); // <---- why does THIS work instead?
}
}
}
このコードは完全に機能します。シールドがミニオンを叩き、ミニオンは死んでしまいます。ここでわかるように、唯一の違いは、ArrayList.remove(object)
インデックスで削除するのではなく、オーバーロードされたメソッドを使用していることです。行のようにminions.remove(collider);
。なぜこれが機能するのですか?
誰でも説明できますか?
余談ですが、arraylist の別のインスタンス変数のコピーを格納する以外に、管理するためのより良い方法はありArrayList<Minion> colliders = new ArrayList<Minion>(minions);
ますか?
注: Shield と Minion はどちらも、境界として長方形の形状を持つ通常の Java オブジェクトです。そのすべての数学は問題なくチェックアウトします。デバッガーでテストしましたが、衝突検出は正確です。onDrawFrame()
また、メソッドで正確な境界/位置を更新しています。