void World::collision_weapon_asteroid(){
for(unsignedint i=0;i<main_weapon.size();i++){//through all the weapons
for(unsignedint j=0;j<asteroids.size();j++){//through all the asteroids
if(check_collision(main_weapon[i]->get_box(),asteroids[j]->get_box())){//if there's a collision
delete main_weapon[i];
main_weapon.erase(main_weapon.begin()+i);//delete the weapon
delete asteroids[j];
asteroids.erase(asteroids.begin()+j);//delete the asteroids
}
}
}
}
It's all pretty simple and straight forward, but oftentimes (not always) when the weapon hits the asteroid, the program crashes. If for example I turn off the delete main_weapon[i] and main_weapon.erase(main_weapon.begin()+i); the program works perfectly, but of course the bullets go right though the asteroid object, which is not what I want. It's only the weapon deletion which is causing no end of trouble.
If anyone knows what's going on or has encountered a similar problem, please let me know!
They will be both one element smaller, and the size of both vectors should be adjusted accordingly. So in the next iteration of the main loop, there should be no issue. At least that's my impression. What am I missing?
I just give you a scenario of when things go wrong:
Imagine that main_weapon.size() is 2 and asteroids.size() is 3. When i == 1 and j == 0 you find a collision so main_weapon[1] and asteroids[0] are erased, making main_weapon.size() == 1 and asteroids.size() == 2. What happens next is that j is increased to 1 and a new collision test is made between main_weapon[1] and asteroids[1]. This is a problem because main_weapon[1] doesn't exist. Even if there was one more weapon you still have a problem here because you would miss to check the new main_weapon[1] against the new asteroids[0].
Bloody Hell, I think you are right! So I guess the other question is, how does a noob get around this problem? I remember looking online for game tutorials and I am pretty sure a few of them used this 2xfor loop with erasure algorithm.
auto i = main_weapon.begin();
while( i != main_weapon.end() )
{
bool hit = false; // true if the weapon hit an asteroid
for(auto& j : asteroids) // C++11 style for loop
// for(auto& j = asteroids.begin(); j != asteroids.end(); ++j) if you can't use above loop
{
if( /* *i collides with *j */ )
{
hit = true;
delete *j; // use smart pointers so you don't have to do this!
asteroids.erase( j );
break; // escape the 'j' loop
}
}
if(hit)
{
delete *i; // smart pointers!!!!
i = main_weapon.erase( i );
}
else
++i;
}
I am at work right now, but will give this some thought and try your algorithm out when I get home. (In addition I have to do some research on your "smart pointers")