2017-04-02 3 views
1

私の大学のプロジェクトのゲームで作業しています。私は衝突のためにチェックされたすべての弾丸を持っている弾丸のベクトルを持っています。しかし、一度に5個の弾丸を発射しようとすると(ショットガンショット)、すべてが正しく生成されます。その後、ベクトルを通過し、弾丸が生きているかどうかを確認します。何らかの理由で、NULLポインタまたはポインタのデータが破損しています。誰かがこれを修正する方法を知っていれば本当に感謝します。ありがとう!5つのオブジェクトポインタを1つのスコープでプッシュし、オブジェクトのブール値がfalseであるかどうかを確認してエラーを返します。

弾丸チェック:

void Bullet::checkOutOfRange() 
{ 
    if(type == "enemy_bullet") 
    { 
     if(body->GetPosition().x <= -10.0f) 
     { 
      alive = false; 
     } 
    } 
    // checks if the body is out of the window size 
    else if (body->GetPosition().x > 510.0f || body->GetPosition().x < -10.0f || body->GetPosition().y > 291.0f || body->GetPosition().y < -10) 
    { 
     alive = false; 
    } 
} 

弾丸衝突検出:ゲーム内

class MyContactListener : public b2ContactListener 
{ 
    void BeginContact(b2Contact* contact) override 
    { 
     if (contact && contact->IsTouching()) 
     { 
      Entity* A = static_cast<Entity*>(contact->GetFixtureA()->GetBody()->GetUserData()); 
      Entity* B = static_cast<Entity*>(contact->GetFixtureB()->GetBody()->GetUserData()); 


      //------ 
      if((A->type == "player_bullet" && B->type == "enemy") || (A->type == "enemy" && B->type == "player_bullet")) 
      { 
       Bullet *bullet = nullptr; 
       Enemy *other = nullptr; 
       if (A->type == "player_bullet" && B->type == "enemy") 
       { 
        bullet = dynamic_cast<Bullet*>(A); 
        other = dynamic_cast<Enemy*>(B); 
       } 
       else if (A->type == "enemy" && B->type == "player_bullet") 
       { 
        bullet = dynamic_cast<Bullet*>(B); 
        other = dynamic_cast<Enemy*>(A); 
       } 
       if ((A && B) || (B&&A)) 
       { 
        other->bodySprite.set_animation("death"); 
        bullet->alive = false; 
        other->alive = false; 
       } 
      } 
     } 
    } 
} 

弾丸チェック:

for (auto itr = player_bullets.begin(), itrEnd = player_bullets.end(); itr != itrEnd; ++itr) 
    { 
     (*itr)->checkOutOfRange(); // go to declaration to see where the bullets stop 
     (*itr)->bodySprite.set_position((*itr)->body->GetPosition().x, (*itr)->body->GetPosition().y); 
     (*itr)->bodySprite.set_rotation((*itr)->bulletDir * 180/PI); 
     (*itr)->moveBullet(20.0f); 
     if ((*itr)->alive == false) 
     { 
      input_world->DestroyBody((*itr)->body); 
      delete *itr; 
      itr = player_bullets.erase(itr); 
     } 
    } 

ショットガン、ショットのspawn:

void spawnShotgunShot(float x, float y, float dir, b2World *world) 
{ 
    // maybe bad pointer management? 
    Bullet *bullet_ptr1 = new Bullet(x, y, dir, world, "player_bullet", PLAYER_BULLET, ENEMY); 
    player_bullets.push_back(bullet_ptr1); 
    Bullet *bullet_ptr2 = new Bullet(x, y, dir + 0.5, world, "player_bullet", PLAYER_BULLET, ENEMY); 
    player_bullets.push_back(bullet_ptr2); 
    Bullet *bullet_ptr3 = new Bullet(x, y, dir + 0.25, world, "player_bullet", PLAYER_BULLET, ENEMY); 
    player_bullets.push_back(bullet_ptr3); 
    Bullet *bullet_ptr4 = new Bullet(x, y, dir - 0.5, world, "player_bullet", PLAYER_BULLET, ENEMY); 
    player_bullets.push_back(bullet_ptr4); 
    Bullet *bullet_ptr5 = new Bullet(x, y, dir - 0.25, world, "player_bullet", PLAYER_BULLET, ENEMY); 
    player_bullets.push_back(bullet_ptr5); 
} 

そして、ここではそれにSLNとtestbuildです: Link to testbuild

答えて

0

あなたの問題は、弾丸をチェックするループであなたのitrEnd変数です。ループの始めにplayer_bullets.end()に初期化してから、ループ条件としてitr != itrEndをチェックします。しかし、ベクトルから箇条書きを削除すると、イテレーターが消去された後にイテレーターが無効になります(イテレーターを含む)。ベクトルのオリジナルのイテレーターは、小さなサイズに基づく新しいものではなく、引き続き使用しています。

itrEnd変数を削除し、ループ条件としてitr != player_bullets.end()をチェックしてください。これは、要素が消去されて変更された場合でも、常に「現在の」エンドイテレータを使用していることを保証します。関連ノートで


あなたはベクターから要素を消去するとき、あなたが戻ってerase呼び出しから取得するイテレータを消去されたものの後の要素ためです。次の反復の開始時に、ループの++itrはループ状態を再度確認する前にその要素を通過します。つまり、ベクトルから箇条書きを削除するたびに、ループはその後ろの箇条書きをスキップします。 の最後のの箇条書きが削除されると、ループは最後のイテレータをスキップし、ベクトルの最後を反復し続けます。

修正方法については、this SO questionを参照してください。

関連する問題