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

Author Topic: sf::Sprites and std::lists  (Read 2322 times)

0 Members and 1 Guest are viewing this topic.

DrewCelery

  • Newbie
  • *
  • Posts: 6
    • View Profile
sf::Sprites and std::lists
« on: May 29, 2014, 04:21:09 am »
Hi, I'm trying to do something fairly simple with my code, where if I right-click a tile it gets removed from the std::list of drawables I defined. Here's a snippet of my code:

if (sf::Mouse::isButtonPressed(sf::Mouse::Right)){
for each(sf::Sprite Tile in BGCollTiles){
if(Tile.getGlobalBounds().contains(sf::Mouse::getPosition().x,sf::Mouse::getPosition().y)){
BGCollTiles.remove(Tile);}}}

I end up getting a long list of linker errors related to std::list and sf::Sprite. However, I have similar code that compiles fine relating to collisions, so I'm not sure what's wrong. Any help would be appreciated.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: sf::Sprites and std::lists
« Reply #1 on: May 29, 2014, 07:52:45 am »
Could you show us what the errors actually are?  And preferably some complete and minimal code?  Right now the only problem that jumps out to me is that you're changing a list while iterating over it in the wrong/naive way (see questions like https://stackoverflow.com/questions/10360461/removing-item-from-vector-while-in-c11-range-for-loop and https://stackoverflow.com/questions/16269696/erasing-while-iterating-an-stdlist), but that shouldn't cause any linker errors.

Also, it's very hard to read your code with no indenting and so few line breaks.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: sf::Sprites and std::lists
« Reply #2 on: May 29, 2014, 11:23:49 am »
for each(sf::Sprite Tile in BGCollTiles)
That's C++/CLI, not C++.

Correct would be
for (sf::Sprite& Tile : BGCollTiles)
Note the reference.

However, you need iterators when you want to remove the element. Calling remove() during iteration is not good; you need erase().
for (auto itr = list.begin(); itr != list.end(); /* nothing */)
{
    if (/* need to remove */)
        list = list.erase(itr);
    else
        ++itr;
}
« Last Edit: May 29, 2014, 11:26:07 am by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

DrewCelery

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: sf::Sprites and std::lists
« Reply #3 on: May 30, 2014, 12:12:31 am »
Thanks for the input. I played with it a bit more and here's what I have (with more legibility).

if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
{
        for (std::list<sf::Sprite>::iterator it = BGCollTiles.begin(); it != BGCollTiles.end();)
        {
                if(it->getGlobalBounds().contains(sf::Mouse::getPosition(App).x,sf::Mouse::getPosition(App).y))
                {
                        BGCollTiles.erase(it);
                }
        else
                ++it;
        }
}

Now it compiles, but right-clicking a tile crashes the program. Clicking anywhere else works fine. Also, I failed to mention that I am using Visual Studio 2009, so I don't have access to C++11. Is there any way I can pull this off without it?

Sorry, i'm still new to C++ so go easy on me, haha.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: sf::Sprites and std::lists
« Reply #4 on: May 30, 2014, 12:29:25 am »
C++11 isn't necessary for something this simple, don't worry about that.

If C++ is new to you, you need to go finish learning the language before you can use a library written in it.  There's no getting around that.

And when asking for help, always post complete and minimal examples along with the exact error you get and where it happens.

In this case, you appear to have not fully grasped the links/examples in our previous posts because you aren't using the return value of erase().  If you don't do that the iterator becomes invalid (after all, you just deleted what it was pointing to) and that causes undefined behavior, in this case a crash.

And one minor point: the contains() function can take a Vector2, so you can just write
if(it->getGlobalBounds().contains(sf::Mouse::getPosition(App)))
« Last Edit: May 30, 2014, 12:37:02 am by Ixrec »

DrewCelery

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: sf::Sprites and std::lists
« Reply #5 on: May 30, 2014, 01:08:23 am »
Whoops, my bad. I replaced

BGCollTiles.erase(it);

with

it=BGCollTiles.erase(it);

and it now works. Thanks for the help guys.