1
\$\begingroup\$

I'm trying to detect collision between two list of bullets and asteroids. The code works fine, but when the bullet intersects with an asteroid, and that bullet passes through another asteroid, the code gives an assertion, and it says about it can't increment the iterator. I'm sure there is a small bug in that code, but I can't find it.

for (list<Bullet>::iterator itr_bullet = ship.m_Bullets.begin();
     itr_bullet!=ship.m_Bullets.end();)
{
    for (list<Asteroid>::iterator itr_astroid = asteroids.begin();
         itr_astroid!=asteroids.end();
         itr_astroid++)
    {
        if(checkCollision(itr_bullet->getCenter(),itr_astroid->getCenter(),
           itr_bullet->getRadius(), itr_astroid->getRadius()))
        {
            itr_astroid = asteroids.erase(itr_astroid);
        }
    }
    itr_bullet++;
}
\$\endgroup\$
2
  • \$\begingroup\$ There are lots of collision detection questions on the site. Did you really not find what you were looking for with those? \$\endgroup\$
    – House
    Sep 1, 2012 at 1:35
  • \$\begingroup\$ I did, but it seems I have a problem with iterating through the list and erasing an item from it \$\endgroup\$ Sep 1, 2012 at 1:36

1 Answer 1

1
\$\begingroup\$

The problem is that you're removing an asteroid from the list, and then incrementing the iterator without first checking whether you're already at the end of the list.

The usual approach, when iterating over a container, is to remove the 'increment' step from the for clause, and instead to either do the erase (which implicitly does a safe increment), or else increment inside the code inside the for loop:

for (list<Asteroid>::iterator itr_astroid = asteroids.begin(); itr_astroid!=asteroids.end();)
{
    if(checkCollision(itr_bullet->getCenter(),itr_astroid->getCenter(), itr_bullet->getRadius(), itr_astroid->getRadius()))
    {
        itr_astroid = asteroids.erase(itr_astroid);
    }
    else
    {
        itr_asteroid++;
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ I want to remove the bullet also when the collision occurs, so that it can't pass through other asteroids \$\endgroup\$ Sep 1, 2012 at 1:28
  • \$\begingroup\$ Then I'd do something similar to what you're already doing; when checkCollision() returns true, you want to set a "this bullet hit something" variable, and then break out of the for loop which is iterating over asteroids. Then you check to see whether the "this bullet hit something" variable is set, and if so, erase the bullet. If not, iterate the bullet iterator, as you are already doing in your code. \$\endgroup\$ Sep 1, 2012 at 1:35
  • \$\begingroup\$ Thanks!. As you are a professional game programmer, What do you suggest more for reading to not fall in those simple situations again ? \$\endgroup\$ Sep 1, 2012 at 1:41
  • \$\begingroup\$ There's really no simple thing I can point you to, to eliminate these sorts of issues.. it's really just experience, and learning to read man pages (and STL documentation, in this instance) when something goes wrong. And Google sometimes helps a lot, too. :) \$\endgroup\$ Sep 7, 2012 at 11:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .