2017-11-05 16 views
0

私は小惑星が画面の下に落ちたC++とsfmlのゲームで作業しています。プレーヤーはそれらを破壊するためにレーザーを撃ちます。小惑星やレーザーが画面の外に行くとき、彼らは削除され、それぞれのstd ::ベクトルから消去されます。ポインタを実行するとC++アクセス違反が発生する

小惑星:

std::vector<Asteroid*>::iterator it; 
for (it = asteroids.begin(); it < asteroids.end();) { 
    (*it)->update(dt); 

    if ((*it)->getPosition().y > Game::window.getSize().y) { 
     delete * it; 
     asteroids.erase(it); 
    } 
    else { 
     it++; 
    } 
} 

レーザー:

for (int i = 0; i < lasers.size(); i++) { 
    lasers.at(i)->update(dt); 

    if (lasers.at(i)->getPosition().y < 0) { 
     delete lasers.at(i); 
     lasers.erase(lasers.begin() + i); 
     i--; 
    } 
} 

問題が来ます私はそれらの間の衝突を検出しようとします。私はレーザーの各インスタンスですべての小惑星をループし、親クラスGameObjectのメソッドを使ってそれらの衝突をチェックします。私はこの上でいくつかの時間を費やしてきたと私は見えることはできません

bool GameObject::isColliding(GameObject * g) { 

sf::Vector2f gPos = g->getPosition(); 
sf::Vector2f pos = this->getPosition(); // after waiting a few seconds and then testing the collision, I get this error here: Access violation executing location 0x00000000. 



if (gPos.x <= pos.x && pos.x <= gPos.x + g->width 
    || pos.x <= gPos.x && gPos.x <= pos.x + width) { 

    if (gPos.y <= pos.y && pos.y <= gPos.y + g->height 
     || pos.y <= gPos.y && gPos.y <= pos.y + height) { 

     return true; 
    } 
} 
return false; 

}

sf::Vector2f GameObject::getPosition() { 

if (isLoaded) { 
    if (animated) 
     return animatedSprite.getPosition(); 
    else 
     return sprite.getPosition(); // the asteroids are not animated, so this will be called. 

} 

}

for (int i = 0; i < Game::spawner->asteroids.size() - 1; i++) { 

    if (isColliding(asteroids.at(0))) { // Access violation executing location 0x071DE528. 
     printf("collided"); 
     //delete asteroids.at(i); 
     //asteroids.erase(asteroids.begin() + i); 
     break; 
    } 
} 

はここisCollidingとgetPosition方法であり、何が起こっているのか把握する。私はポインタとそのインデックスを安全に削除していると思うので、そこからどこに行くのかわかりません。参考までに、isColliding関数は、2つの異なるGameObject(プレーヤーと小惑星)で動作します。問題は何とかすべての小惑星のループに関連しているようです。

ありがとうございました。

小惑星削除UPDATED

:あなたは小惑星を通過し、それらを削除するには、イテレータを使用している

int toDelete = -1; 
for (int i = 0; i < asteroids.size(); i++) { 
    asteroids.at(i)->update(dt); 

    if (asteroids.at(i)->getPosition().y > Game::window.getSize().y) { 
     toDelete = i; 
    } 
} 

if (toDelete != -1) { 
    delete asteroids.at(toDelete); 
    asteroids.erase(asteroids.begin() + toDelete); 
} 
+0

このようなベクトルを反復処理することはできません。また、その上に 'erase'を呼び出します。 –

+0

'asteroids'が空の場合、' i asteroids.size() - 1'は真です! – aschepler

答えて

1

は、しかし、ドキュメントはイテレータが無効化されeraseを呼び出した後と述べている:

Erase documentation

位置(または先頭)を指すイテレータ、ポインタ、および参照は、すべてのイテレータ、ポインタ、およびr位置(または最初のもの)の前の要素への参照は、呼び出しの前に参照していたのと同じ要素を参照し続けることが保証されています。

したがって、最初の呼び出しの呼び出し後、ポインタは無効になり、何かが起こる可能性があります。破壊された小惑星を最初に特定して別々に消去するなど、削除のための別の戦略を試してください。

+0

イテレータ(またはレーザの場合はインデックス変数)は、消去を考慮して調整するだけではありませんか?たとえば、エントリを消去しないときにのみインクリメントします。 erase()はベクトル内の順序エントリを変更しません。 – panner2

+0

いいえ、イテレータはイレースの説明に合わせて調整することはできません。イテレータの仕組みではありません。消去を呼び出すと、イテレータは無効になり、何もできません。あなたはそれを回避しようとすることができますし、有効なポジションを見つけるかもしれませんが、それは彼らがどのように使用されるべきかではないので、保証はありません。 – Rodrigo

+0

ループ外の小惑星を削除しようとしていますが、問題は解決しません。どちらのエラーも、一見無作為な時間に起こる。元の質問に更新されたコードを含めました。 – panner2

関連する問題