Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Collision: Erasing two sprites from two different vectors (Solved)  (Read 1836 times)

0 Members and 1 Guest are viewing this topic.

argh

  • Newbie
  • *
  • Posts: 16
    • View Profile
    • my blog
    • Email
Collision: Erasing two sprites from two different vectors (Solved)
« on: September 19, 2015, 05:09:42 pm »
Hi everyone,

I have a problem erasing two elements when they collide. I go thru the 2 vectors of sprites and check if they have intersected with each other, if true, then I erase the two elements from the two vectors (bullets & enemies).

My problem is the following: I can erase one, but how can I erase the second one?

That is how the function looks like so far.
void collision()
  {
          for (auto e = enemies.begin(); e != enemies.end(); e++)
          {
                  for (auto i = bullets.begin(); i != bullets.end(); i++)
                  {
                          sf::FloatRect enemiez = e->getGlobalBounds();
                          sf::FloatRect bulletz = i->getGlobalBounds();

                          if (bulletz.intersects(enemiez))
                          {
                                bullets.erase(i);
              //enemies.erase(e); <-- if i uncomment this line i get a "vector iterator not incrementable!" exception.
                                break;
                          }
                  }
          }
  }
 


I understand that it is a problem with the size and the index in the vector and erasing won't work in the same iteration of the loop. I tried also to erase the enemies(e) in the outer loop, but no good.

I have no idea how else I can solve this? Should I try a totally different approach or am I on the right track?

Thank you for your help in advance!
PS This is my first project with SFML (newest version of SFML and Visual Studio 2013).
« Last Edit: September 19, 2015, 06:00:37 pm by argh »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Collision: Erasing two sprites from two different vectors
« Reply #1 on: September 19, 2015, 05:25:27 pm »
Reading the documentation of vector::erase always helps.

Return value: An iterator pointing to the new location of the element that followed the last element erased by the function call.

So in the context of your code...

void collision()
  {
      for (auto e = enemies.begin(); e != enemies.end(); /* don't increment here */ )
      {
          bool collides = false;

          for (auto i = bullets.begin(); i != bullets.end(); i++)
          {
              sf::FloatRect enemiez = e->getGlobalBounds();
              sf::FloatRect bulletz = i->getGlobalBounds();

              if (bulletz.intersects(enemiez))
              {
                bullets.erase(i);

                // assign the return value and set the flag that a collision happened
                e = enemies.erase(e);
                collides = true;

                break;
              }
          }

          // only increment if no collision happened
          if (!collides)
            e++;
      }
  }

Notice how I assigned your iterator to the return value of erase()? This is because once you erase an element your previous iterator is invalidated. Also I added a boolean so if you remove an element you don't increment the iterator and skip the collision check for the next element.
« Last Edit: September 19, 2015, 05:32:49 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

argh

  • Newbie
  • *
  • Posts: 16
    • View Profile
    • my blog
    • Email
Re: Collision: Erasing two sprites from two different vectors
« Reply #2 on: September 19, 2015, 05:48:41 pm »
Yes and ty it helped a lot. It works as intended and also helped me correct another function 8)