2017-12-19 55 views
-3

ベクトルstd::vector<Bullet*> bulletsを繰り返しています。敵との衝突を探しています。それは、次の場合を除いて、すべての場合において優れています。最後に発射された弾丸(複数の弾丸が存在しなければならない)が敵と衝突する場合。最後のstd :: vector要素を消去しようとすると、プログラムがクラッシュする

コード -

for(std::vector<Bullet*>::iterator it = bullets.begin(); it != bullets.end(); ++it) 
{ 
    if ((*it)->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     delete *it; 
     bullets.erase(it); 
     enemy->destroy(); 
     if (bullets.size() == 0) 
      break; 
    } 
} 

私はforループ内の特定の要素をコメントし、そしてbullet.erase(it)呼び出しがプログラムをクラッシュしていることが分かりました。 クラッシュが発生すると、戻りコード:134(0x86)が返されます。そのコードの問題は何ですか?

(*it)->getSprite()は、Bulletクラスからスプライトへのポインタを返します。ご検討

auto is_hit = [&enemy](Bullet *bullet) 
{ 
    if (bullet->getSprite()->getGlobalBounds().intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     delete bullet; 
     enemy->destroy(); 
     return true; 
    } 
    return false; 
}; 

bullets.erase(std::remove_if(bullets.begin(), bullets.end(), is_hit), bullets.end()); 
+0

['std :: vector :: erase'](http://en.cppreference.com/w/cpp/container/vector/erase)は、イテレータを無効にし、' ++ it'を呼び出した後に'erase'、未定義の動作です。 –

+1

どうして 'std :: vector :: pop_back()' –

+0

私は次のようなことを試みました:if(std :: next(it))== bullets.end() bullet.pop_back(); else bullets.erase(it); しかし、どちらもうまくいかないようです。 –

答えて

0

と [その最後の要素について] bullet.erase(IT)の呼び出しは、ある意味ではプログラム

をクラッシュすることが判明、あなたはおそらく途中で消去を行っています。

は、次の点を考慮

範囲、目標、および兵器型のテストパラメータは、例えば、達成するために10%のヒット率を組み合わせた可能性があることも可能です。したがって、1000ショットのコレクション(1000 == bullets.size())には、ターゲットに命中した(〜)100個の弾丸があります。

あなたのコードは、各要素を見つけ、bullets.erase()を使用してベクトルに100個の穴を作成します。ベクトルデータは連続的に維持されるので、消去方法は消去によって作成された穴を埋めるために他の要素も移動させる。

一般に、100回の消去では、毎回1000個以下のシャッフルが発生しますが、これは1度に1つの方法で実行される可能性があります比較的遅いプロセスです。現在の設計に、代わりに検索と消去の代替として


、あなたのコードを識別し、すべてをマークしたまで消去を延期は「交差」。

  • あなたはまだそれらを消去していない、同じように交差(ヒット)が、「マーク」それらを見つけることができます。オプションには、Bulletクラスにboolを追加するか、各箇条書きに対してこのフラグを保持するための一致するboolベクトルを維持することが含まれます。

  • ふたつのインデックスを使用して、

    から0に初期化I1(第一(左ほとんどの)ベクトル要素)と

    - に初期化I2(bullets.size() - 1)([最後右端の)ベク​​トルの要素]

- 最初のヒットを見つけるためにスピンインクリメントI1、

- 最後のミスを見つけるためにスピンデクリメントI2、

- その後のstd ::スワップ(弾丸[I1]、弾丸[I2])I1> = I2まで

を繰り返し今

すべてのヒットが連続とベクトルの末尾にあることを、 100ヒットのシングルイレースを実行する

これはシャッフリングをなくすはずです。

また、消去された要素は使用しないでください。処理の最後に消去が行われるためです。

+0

欠点はもちろん、残っている「逃した」弾丸はもはや元の順序ではないということです。 –

1

(push_back())

while(!gBoard.empty()) 
{ 
    Cell_t* cell = gBoard.back(); // fetch last element (a ptr) 
    gBoard.pop_back();    // remove last element 
    delete cell;     // remove cell from heap - raw pointer 
} 

おそらく、このスタイルをクリーンにして、複数のベクターを使用することができます。代替案より速いかもしれない。

問題では、各弾丸に少なくとも2つの宛先があるようです...ヒットまたはミス。

while (! Bullets.empty()) // spin through bullet list 
{ 
    Bullet* aBullet = Bullets.back(); // fetch copy of last element 
    Bullets.pop_back();    // remove last element 

    if (*aBullet)-> getSprite()->getGlobalBounds().  
      intersects(enemy->getSprite()->getGlobalBounds())) 
    { 
     // HIT! 
     Hit.push_back(aBullet); // capture the element to Hit bucket 
     enemy->destroy();  // tbd - a decision? or always final? 
     // no delete 
     if (bullets.size() == 0) // no more to compute, redundant to while 
      break; 
    } 
    else 
    { 
     // MISS 
     Missed.push_back(aBullet); // capture element to Missed bucket 
    } 
} // while 

assert(bullets.empty()); // bullets have been consumed 

// clean up spent bullets that intersected 
while (! Hit.empty()) 
{ 
    Bullet* aBullet = Hit.back(); // copy last element from Hit 
    Hit.pop_back();    // remove last element from Hit 
    delete aBullet;    // tbr - delete the dynamic memory 
} 

// clean up spent bullets that missed 
// move the bullet from Missed vec back into Bullets vec 
// for tbd - furthur evaluation ... did the bullet hit any other obj 
// the following also happens to 'undo' the seq reversal 
while (! Missed.empty()) 
{ 
    Bullets.push_back (Missed.back()); // copy last element from Missed 
    Missed.pop_back();     // remove last element from Missed 
    // tbd - also delete the missed bullet? 
    // or do you check for these bullets to collide with other objects 
} 
// possibly a copy can do this last loop, but this is simple and 
// undoes the reversal. 
1

次のコードスニペットは、私が最後尾に要素を追加することにその尾(相補アクションからベクトルをきれいにする方法を示しremove_iferaseコンボを使用することについては何

+0

Hit.size()とMissed.size()を数える機会に注意してください。 –

関連する問題