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

Author Topic: Removing a sprite from vector  (Read 6601 times)

0 Members and 1 Guest are viewing this topic.

Tweezy

  • Newbie
  • *
  • Posts: 43
    • View Profile
Removing a sprite from vector
« on: May 08, 2013, 10:25:23 pm »
Hi. I am using this code to draw five sprites to my screen:

        //load the invaders images
        sf::Texture invaderTexture;
        invaderTexture.loadFromFile("images/invader_1.png");
        std::vector<sf::Sprite>invaderSprites(10, sf::Sprite(invaderTexture));

                        for (int i = 0; i < 5; i++)
                        {
                                invaderSprites[i].setPosition((65*i), 10);
                                invaderSprites[i].setScale(1.8*1,1.8*1);
                                invaderSprites[i].setColor(sf::Color::Transparent);            
                        }

I have all my collision detection working, but when the projectile hits the sprite I want it to be removed. I thought using .erase would work well, but unfortunately I am having some issues. I have tried this;

invaderSprites.erase(invaderSprites.begin()+x)

It just pops it back to the starting point (Which I can see by .begin part). I've tried doing sf::Color::Transparent but that doesn't seem to be functioning at all!

Any ideas how I can move past this?

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Removing a sprite from vector
« Reply #1 on: May 09, 2013, 09:18:50 am »
Presumably you want to remove the sprite because the invader is 'dead'. Perhaps try using a different approach with a state based class - something like:


enum State
{
    Alive,
    Dying,
    Dead
};

class Invader
{
public:
    State state;
    sf::Sprite sprite;
    Invader(sf::Texture& texture) : state(Alive)
    {
        //set sprite texture
    }

    Update()
    {
        switch state
        {
         case Alive:
         //do sprite movement and collision detection
         case Dying:
         //maybe play a death animation
         case Dead:
        }
    }
};

 

then:

sf::Texture texture;
texture.loadFromFile("texture.png");
std::vector<sf::Sprite>invaders(10, Invader(texture));

for(auto i = invaders.cbegin(); i != invaders.cend(); ++i)
{
    Invader& invader = *i;
    invader.Update();
    if(invader.state != Dead) renderTarget.draw(invader.sprite);
}
 

Tweezy

  • Newbie
  • *
  • Posts: 43
    • View Profile
Re: Removing a sprite from vector
« Reply #2 on: May 09, 2013, 10:47:47 am »
Ah good idea, so if a invader has been defeated it moves to a different state with four invaders instead of five.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Removing a sprite from vector
« Reply #3 on: May 09, 2013, 11:01:55 am »
But eventually, you still don't want to store a lot of dead objects. Especially in bigger projects, where processing speed and memory usage might become a bottleneck, you want to minimize the amount of active objects.

Don't iterate with indices, unless you really need the random access. For iteration, you should use iterators:
for (auto itr = sprites.begin(); itr != sprites.end(); ++itr)
    doSomething(*itr);
or the range-based for loop:
for (sf::Sprite& sprite : sprites)
    doSomething(sprite);

To erase an element during iteration, you can use erase() and assign its return value:
for (auto itr = sprites.begin(); itr != sprites.end(); )
{
    doSomething(*itr);

    if (isDead(*itr))
        itr = sprites.erase(itr);
    else
        ++itr;
}
However, for std::vector this is very inefficient, since erase() moves all the following elements. In general, you should therefore stick to the STL algorithms std::remove() and std::remove_if(). This is also called the "erase-remove idiom".
auto firstToRemove = std::remove_if(sprites.begin(), sprites.end(), &isDead);
sprites.erase(firstToRemove, sprites.end());

Consult www.cppreference.com for detailed information on the STL.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Tweezy

  • Newbie
  • *
  • Posts: 43
    • View Profile
Re: Removing a sprite from vector
« Reply #4 on: May 09, 2013, 11:24:01 am »
Thank you for all your help and wisdom guys. This seems like quite a good way to achieve what I need. I shall read up on it at cplusplus so I completely understand, and then I will code my own version.

Thanks again people.

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Removing a sprite from vector
« Reply #5 on: May 09, 2013, 02:24:31 pm »
But eventually, you still don't want to store a lot of dead objects. Especially in bigger projects, where processing speed and memory usage might become a bottleneck, you want to minimize the amount of active objects.

This is a very good point - I didn't think of that. I was working on the assumption that at the end of a round each invader may be reset to Alive for the beginning of a new round. A good example of why making assumptions is bad :)