SDL deleting from vector

Hi guys,

Ran into a bug yesterday and it's really frustrating because the code looks right so I am looking for some help.

simple rect collision detection

1
2
3
4
5
6
7
8
9
10
bool check_collision(SDL_Rect *box1, SDL_Rect *box2){

	if(box1->x+box1->w<=box2->x)return false;
	if(box1->x>=box2->x+box2->w)return false;
	if(box1->y+box1->h<=box2->y)return false;
	if(box1->y>=box2->y+box2->h)return false;

	return true;
}


fire the weapon

1
2
3
4
5
6
7
8
9
10
while(SDL_PollEvent(&event)){
		

		if(event.key.keysym.sym==SDLK_f && event.type==SDL_KEYDOWN)//fire the weapon here
			main_weapon.push_back(new MainWeapon(ship->get_box()->x, ship->get_box()->y,7,5));

		

	}


asteroid and weapon decleration

1
2
3
4

std::vector < MainWeapon* > main_weapon;
std::vector < Asteroid* > asteroids;


finally the collision function


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

void World::collision_weapon_asteroid(){

	for(unsigned int i=0;i<main_weapon.size();i++){//through all the weapons
	
		for(unsigned int 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				
				
			}	
		}
	}
}


the order of the game is of course standard.

1.handle input
2. handle logic
3. render
4. update



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!

Thanks,

Mike
Think about what main_weapon[i] and asteroids[j] will be after you have erased main_weapon[i] and asteroids[j].
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?

Mike
Last edited on
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].
Last edited on
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.


Thanks,

Mike
I'd do something like this:

I also tend to prefer iterators over indexes when doing this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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;
}
Last edited on
Thanks Disch,

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")

Mike
Topic archived. No new replies allowed.