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

Author Topic: Removing units individually by clicking on them.  (Read 11163 times)

0 Members and 1 Guest are viewing this topic.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Removing units individually by clicking on them.
« Reply #15 on: July 11, 2014, 07:10:02 pm »
Yes, you should definitely read about the STL in a good book. Knowing how to deal with standard containers is absolutely crucial in C++, and a prerequisite for working with SFML and game development in general...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #16 on: July 12, 2014, 12:09:48 pm »
The funny thing is, that I've been reading books, tutorials, watching tutorials and reading very much code for some time now, but it's not the same as real "goal-oriented" example code.

By the way:
EnemyList.remove_if([](sf::Sprite sprite){return sprite.getGlobalBounds().contains(mousecoords); });

This is shows a cryptic error (can't even translate that) about the mousecoords:
« Last Edit: July 12, 2014, 12:13:45 pm by Bogdan »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Removing units individually by clicking on them.
« Reply #17 on: July 12, 2014, 12:18:16 pm »
Should be [=] instead of just []. Which means to capture the parameters by copy inside the lambda, instead of not capturing anything (since mousecoords are defined outside).
Laurent Gomila - SFML developer

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Removing units individually by clicking on them.
« Reply #18 on: July 12, 2014, 12:20:00 pm »
Also worth mentioning is that that lambda in the remove_if requires a C++11 compiler.

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #19 on: July 12, 2014, 01:03:22 pm »
Ok, I've got only VS 2010. :(
Thats supposedly the reason why the programme  abruptly crashes after first rightklicking on any sprite, eventhough main.cpp does compile without errors. Or has it to do with my self compiled dlls? -> (Unhandled exception at 0x554c6919 (sfml-graphics-d-2.dll) in generating Window 1.exe: 0xC0000005: access violation at reading at position  0xfeeefef6.) I must admit that I'm using the Master Version of SFML (commit 0a64da654c; 9.7.2014).

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Removing units individually by clicking on them.
« Reply #20 on: July 12, 2014, 01:14:33 pm »
Thats supposedly the reason why the programme  abruptly crashes
What? The fact that you're not using the latest compiler? Certainly not. VS 2010 may not support the latest C++11 standard (but it does support lambda expressions), however it's not fundamentally broken.

You're doing wrong something else, show a minimal complete example if you expect useful answers.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: Re: Removing units individually by clicking on them.
« Reply #21 on: July 12, 2014, 01:17:55 pm »
Should be [=] instead of just []. Which means to capture the parameters by copy inside the lambda, instead of not capturing anything (since mousecoords are defined outside).
That's what happens when you write from a tablet on the fly :( mea culpa

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #22 on: July 12, 2014, 01:24:14 pm »
Now with this code, I get the error after removal attempt of the last unit.
Ok, here is the minimal code:


#include <SFML/Graphics.hpp>
#include <iostream>
#include <list>

int main()
{

    sf::RenderWindow mMainWindow(sf::VideoMode(1000, 600), "Map");
    mMainWindow.setFramerateLimit(30);
   
    sf::Image unitimage;
    unitimage.loadFromFile("unit.png");
    sf::Texture unittexture;
    unittexture.loadFromImage(unitimage);
    sf::Sprite unitsprite(unittexture);

    std::list<sf::Sprite>EnemyList;
    std::list<sf::Sprite>::iterator EnemyIt;

while (mMainWindow.isOpen())
    {
        sf::Event event;
        while (mMainWindow.pollEvent(event))
            {
            if (event.type == sf::Event::Closed)
                {
                mMainWindow.close();
                }
            if(event.type == sf::Event::MouseButtonPressed)
                if(event.mouseButton.button == sf::Mouse::Left)
                    {
                    sf::Sprite *Sprite;
                    Sprite = new sf::Sprite;
                    Sprite->setTexture(unittexture);
                    Sprite->setPosition(sf::Mouse::getPosition(mMainWindow).x,sf::Mouse::getPosition(mMainWindow).y);

                    EnemyList.push_back(*Sprite);
                    std::cout << "Objects count: " << EnemyList.size() << std::endl;
                    }          
            }

    for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();EnemyIt++)
        {
        mMainWindow.draw(*EnemyIt);
            if(event.mouseButton.button == sf::Mouse::Right)
                {
                sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)));
                   
                    EnemyList.remove_if([=](sf::Sprite unitsprite){return unitsprite.getGlobalBounds().contains(mousecoords); });
                   
                }
        }
        mMainWindow.display();
        mMainWindow.clear(sf::Color(0, 200, 0, 255));

    }
    return 0;
}
 
« Last Edit: July 12, 2014, 01:32:37 pm by Bogdan »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Removing units individually by clicking on them.
« Reply #23 on: July 12, 2014, 01:35:51 pm »
Why do you create pointers to dynamically allocated memory just to dereference them in the next statement? That's an invitation for massive memory leaks, see also this article of mine. Just store std::vector<sf::Sprite>.

The remove_if() has to be placed outside iteration, otherwise you invalidate the iterators. You should really learn about the STL, these are basics and we can't explain you everything... ::)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Removing units individually by clicking on them.
« Reply #24 on: July 12, 2014, 01:38:03 pm »
You have no idea about what you're writing, have you? Instead of blindly copying what we tell you, you should do it your own way, which may not be the best but which at least you understand ;)

Here you're iterating on your list, and for every element, you call a function which also iterates on the entire list to find and remove elements. Besides, you're using a sf::Event outside the event loop, which doesn't make sense at all and could result in unexpected behaviour.
Laurent Gomila - SFML developer

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #25 on: July 13, 2014, 04:03:09 pm »
Ok, many thanks for your help. It works now "sufficiently".

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #26 on: July 28, 2014, 09:33:14 am »
Finally I'm implementig the std::vector (after having done some console experiments, which have shown, that it indeed has a better functionality) and there is no error so far, but I don't know what to do for removing only one sprite at a time instead of all sprites. I know that the struct is incomplete and always set to "true" (probably will need an additioanal bool) , but what additional argument to put inside it for it to work properly. Any hints?

#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <algorithm>

struct IsUnitRemoved {
bool operator() (const sf::Sprite& e) const {
return 1;
}
};

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(1200, 900), "Window");
    mMainWindow.setFramerateLimit(60);

        sf::Image image;
    image.create(50, 50, sf::Color::Red);
    sf::Texture texture;
    texture.loadFromImage(image);

    std::vector<sf::Sprite> SpriteVector;
        std::vector<sf::Sprite>::iterator SpriteIt;

    while (mMainWindow.isOpen())
    {
        sf::Event event;

                bool creating = false;
                bool rightclick = false;

                sf::Vector2i mousePos;

        while (mMainWindow.pollEvent(event))
        {
                        switch (event.type)
                        {
                        case sf::Event::Closed:
                                mMainWindow.close();
                                break;
                        case sf::Event::KeyPressed:
                                creating = (event.key.code == sf::Keyboard::A);
                                break;
                        case sf::Event::MouseButtonPressed:
                                if (event.mouseButton.button == sf::Mouse::Right)
                                        rightclick = true;
                                        mousePos = sf::Vector2i (event.mouseButton.x, event.mouseButton.y);
                                        break;
                        }
                }
                if (creating)
                {
                        sf::Sprite newSprite;
                        newSprite.setTexture(texture);
                        newSprite.setPosition(mMainWindow.mapPixelToCoords(sf::Vector2i(sf::Mouse::getPosition(mMainWindow).x-50,sf::Mouse::getPosition(mMainWindow).y-50)));
                        SpriteVector.push_back(newSprite);
                }
                if (rightclick)
                 {
                        for(SpriteIt = SpriteVector.begin();SpriteIt != SpriteVector.end(); )
                        {
                        sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)));
                                if(SpriteIt->getGlobalBounds().contains(mousecoords))
                                {
                                        SpriteIt = SpriteVector.erase(std::remove_if(SpriteVector.begin(), SpriteVector.end(), IsUnitRemoved()),SpriteVector.end());
                                }
                                else
                                {
                                        ++SpriteIt;
                                }
                        }
        }      
    mMainWindow.clear();
    for(auto &SpriteIt = SpriteVector.begin();SpriteIt != SpriteVector.end();++SpriteIt)
        {
                mMainWindow.draw(*SpriteIt);
        }
    mMainWindow.display();
    }
    return 0;
}


Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: Removing units individually by clicking on them.
« Reply #27 on: July 28, 2014, 11:13:49 am »
                        for (SpriteIt = SpriteVector.begin(); SpriteIt != SpriteVector.end(); SpriteIt++)
                        {
                                sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)));
                                if (SpriteIt->getGlobalBounds().contains(mousecoords))
                                        SpriteVector.erase(SpriteIt);
                                /* Add a break if you only want the one on the bottom to be erased */
                                /* If you use a doubly linked list you can push_front(sprite)   */
                                /* to have everything new on top                                   */
                        }
 
« Last Edit: July 28, 2014, 11:22:16 am by Strelok »

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Removing units individually by clicking on them.
« Reply #28 on: July 28, 2014, 01:10:03 pm »
Ok, it works, thanks. The new ones even are created on top of the old ones, but what to do to remove the top one (not the bottom one), if I use vector?


I know how to select the topmost one, but not how to remove it:

      
if (rightclick)
                 {
                for (auto& SpriteIt = SpriteVector.rbegin(); SpriteIt != SpriteVector.rend(); ++SpriteIt)
                                if (SpriteIt->getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y))))
                                {
                                        SpriteVector.rbegin();                                                                                 
                                        std::cout << "sprite selected" << std::endl;
                                        std::cout << SpriteIt->getPosition().x << std::endl;
                                        std::cout << SpriteIt->getPosition().y << std::endl;
                                        break;
                                }

        }
   

Removal of last "topmost" element in cpp:
vector.erase (vector.begin()+vector.size()-1);
« Last Edit: July 28, 2014, 01:58:00 pm by Bogdan »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Removing units individually by clicking on them.
« Reply #29 on: July 28, 2014, 01:29:12 pm »
Have you even tried google? This is a very basic question with regards to using the standard library. If you do not even know how to remove something from a stl container I highly suggest you get a good C++ book and learn how to write C++ instead of trying to learn it at the same time as SFML.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor