Help with vectors please!!!

Started by
3 comments, last by rip-off 14 years, 11 months ago
Hi guys, I just a few days ago started to program my own top-down shooter game. However, while programming the destroying of enemies and bullets on collision with each other I have run into some errors:

Debug assertion failed!
...
Expression: ("this->_Has_container()", 0)
...
I believe this is to do with the code:

	for(std::vector<Player>::iterator i = enemies.begin(); i != enemies.end(); i++) {
		for(std::vector<Particle>::iterator j = bullets.begin(); j < bullets.end(); j++) {
			if((*i).ALIVE() && (*j).ALPHA() > 0.0f) {
				if((*j).X() > (*i).X() -(*i).W()/2 && (*j).X() < (*i).X() + (*i).W()/2
					&& (*j).Y() > (*i).Y() - (*i).H()/2 && (*j).Y() < (*i).Y() + (*i).H()/2) {
						if(enemies.size() > 1) {
							std::swap(*i, *(enemies.rbegin()));
						}
						enemies.pop_back();
						if(bullets.size() > 1) {
							std::swap(*j, *(bullets.rbegin()));
						}
						bullets.pop_back();
				}
			}
		}
	}
Please please help!!! Note: I add new elements to the vectors (enemies) and (bullets) at the beginning, not the end. The idea of that code was to loop through checking for collisions of enemies with bullets, and if they collide, move them to the end of the vector and erase them. The error occurs whenever my bullets hit the enemies.
Advertisement
Think what happens when the iterator is pointing to the last element of one of the vectors and you try erasing it. The iterator is now pointing to garbage and then you increment it because of the for loop. At this point you've got bad ju-ju because you've tried incrementing an invalidated iterator.

Also, adding elements to the beginning of a vector is fairly inefficient. vectors work best when you add and remove at the end. If you want to add and remove at both ends use a deque.
You are modifying the vectors while iterating over them. This will cause your iterators to be invalidated.

There are a number of ways of getting around this. One is to use integers to index the array, they cannot be invalidated (just be sure not to cache the size of the array, as it will change during iteration). Another is to build a collection of the indices you want to remove, and once you have collision detection finished then remove them.

Or something like this:
#include <algorithm>struct PlayerBulletCollision{    PlayerBulletCollision(const Player &player)    :        player(&player) {}    bool operator()(const Particle &particle) const    {        // return true if *player hits particle    }private:    Player *player;};typedef std::vector<Particle> Particles;struct PlayerBulletsCollision{    PlayerBulletsCollision(Particles &particles)    :        particle(&particles) {}    bool operator()(const Player &player)    {        Particles::iterator end = particles->end();        Particles::iterator it = std::remove_if(particles->begin(), end, PlayerBulletCollision(player));        bool result = (it != end);        particles->erase(it, end);        return result;    }private:    Particles *particles;};typdef std::vector<Player> Players;void wherever(Players &players, Particles &particles){    Particles::iterator end = players->end();    Particles::iterator it = std::remove_if(players->begin(), end, PlayerBulletsCollision(particles));    players->erase(it, end);}

That is untested, but I think it might work.
Hey guys,

Thanks for the very quick replys!
I fixed my problem!!! As I go through the collisions I just set a flag for the enemies and bullets that were hit to say dead. Then I loop through the vectors swapping the dead elements with the end and using pop_back(), then break the loop. Once the loop removes all of the dead elements it seta a flag saying done and exits the entire loop.

Thanks a lot!

-NWalton

EDIT:

BTW, currently I'm not really worried about efficiency as this is my first 2d game (programming with c++, sdl, opengl), and I'm just experimenting. I even made my own image format!!!
I will mention that the "remove_if, erase" solution I showed you is idiomatic C++ for removing objects from a vector, while also being quite efficient.

This topic is closed to new replies.

Advertisement