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

Author Topic: Counting sprites of specific type in vector  (Read 3145 times)

0 Members and 1 Guest are viewing this topic.

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Counting sprites of specific type in vector
« on: February 28, 2015, 08:27:26 pm »
Hi,

is there a way to count sprites (of specific type) in a vector?

The following code doesn't work and I don't know why? Many thanks in advance for any help.

            int mycount = std::count (EnemyVector.begin(), EnemyVector.end(), sprite);
            std::cout << "number of red squares: " << mycount  << std::endl;

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

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(600,600), "Map", sf::Style::Close);
    mMainWindow.setFramerateLimit(60);
    mMainWindow.setKeyRepeatEnabled(false);

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

    std::vector<sf::Sprite> EnemyVector;

    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:
                                if (event.key.code == sf::Keyboard::A)
                                {
                                        creating = true;
                                        break;
                                }
            case sf::Event::MouseButtonPressed:
                                if (event.mouseButton.button == sf::Mouse::Right)
                                {
                                        rightclick = true;
                                        mousePos = sf::Vector2i (event.mouseButton.x, event.mouseButton.y);
                                        break;
                                }
                break;
            }
                }
        if (creating)
        {
            sf::Sprite sprite;
            mousePos = (mousePos == sf::Vector2i(0, 0) ? sf::Mouse::getPosition(mMainWindow) : mousePos);
                        sprite.setTexture(texture);

            sprite.setOrigin(static_cast<float>(sprite.getTextureRect().width) / 2, static_cast<float>(sprite.getTextureRect().height) / 2);
            sprite.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
            EnemyVector.push_back(sprite);

                        int mycount = std::count (EnemyVector.begin(), EnemyVector.end(), sprite);
                        std::cout << "number of red squares: " << mycount  << std::endl;
                }
                if (rightclick)
                {
                        for (auto& SpriteIt = EnemyVector.rbegin(); SpriteIt != EnemyVector.rend(); ++SpriteIt)
            {
                sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)));
                if (SpriteIt->getGlobalBounds().contains(mousecoords))
                                {
                                        EnemyVector.erase( std::next(SpriteIt).base() );

                                        sf::Sprite sprite;
                                        int mycount = std::count (EnemyVector.begin(), EnemyVector.end(), sprite);
                                        std::cout << "number of red squares: " << mycount  << std::endl;
                                        break;
                                }
            }
        }

        mMainWindow.clear();
        for (auto& enemy = EnemyVector.begin(); enemy != EnemyVector.end(); ++enemy)
        {
            mMainWindow.draw(*enemy);
        }
        mMainWindow.display();
    }
    return 0;
}
 
« Last Edit: February 28, 2015, 08:48:33 pm by Bogdan »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Counting sprites in vector
« Reply #1 on: February 28, 2015, 08:31:10 pm »
Maybe RTFM? I have lost count how many times we have said this isn't a general C++ help forum..... I mean you can find the answer in like 10 seconds top with google.

Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Counting sprites in vector
« Reply #2 on: February 28, 2015, 08:39:14 pm »
I know about vector.size, but what if I have different/many sprite types in one vector, for example red, blue, green etc. squares and want to count the red ones?
« Last Edit: February 28, 2015, 08:42:43 pm by Bogdan »

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Counting sprites in vector
« Reply #3 on: February 28, 2015, 08:58:58 pm »
It'd be easier to make a sorted version of the vector of sprites and than keep track of the numbers in a map.  Than again it depends on what you are up to for the most part.  Since this is C++ info and not SFML info it is why you are getting chewed out.


https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=C%2B%2B+counting+the+number+of+occurrences+an+object+in+a+vector&spell=1

http://www.mochima.com/tutorials/STL_algorithms.html

http://www.geeksforgeeks.org/count-number-of-occurrences-in-a-sorted-array/

I could look up more but sites like stackoverflow are more helpful for this kind of thing.  Also there should be some info on CPPReference and a few other sites to speed things a long.

What I normally do is leave my normal vector alone and make a sorted copy of it.  Than use a map to hold at least one of each object that is different and a counter.  Sure it isn't the best solution but it has worked fine for some time.
I have many ideas but need the help of others to find way to make use of them.

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Counting sprites of specific type in vector
« Reply #4 on: February 28, 2015, 09:58:55 pm »
Is this really a pure cpp problem? In clean cpp it works just fine with numbers:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
        std::vector<int> EnemyVector1;
        EnemyVector1.push_back(10);
        EnemyVector1.push_back(10);
        EnemyVector1.push_back(10);
        int mycount = std::count (EnemyVector1.begin(), EnemyVector1.end(), 10);
        std::cout << "number of 10s: " << mycount  << std::endl;
        system( "pause" );
}


But he doesn't seem to accept "sprite", whatever I try (counting, sorting....). In the code above it's the "sprite" in the following line, that causes a cryptic error:
int mycount = std::count (EnemyVector.begin(), EnemyVector.end(), sprite);

I don't understand why it can't simply count the sprites. Isn't it an sfml based problem? It wouldn't be difficult to make variables as counters, that increment whenever a sprite of a specific type is created (for example increment variable a by hitting button A and increment variable b by hittung button B), but if I want to remove a sprite by mouse click, it will not recognise which sprite type/color has been removed.
« Last Edit: February 28, 2015, 10:00:34 pm by Bogdan »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Counting sprites of specific type in vector
« Reply #5 on: February 28, 2015, 10:25:03 pm »
Quote
I don't understand why it can't simply count the sprites
Because it has no operator ==.

So in this case, reading the doc would actually have helped you ;)

T shall be a type supporting comparisons with the elements pointed by InputIterator using operator==

But the problem here is not how to make std::count work with sprites, that is just the solution you think you need. If you tell us about the problem you try to solve, we'll be able to show you the right solution (which probably doesn't involve std::count).
Laurent Gomila - SFML developer

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Counting sprites of specific type in vector
« Reply #6 on: March 01, 2015, 01:41:28 am »
Well to fully use count you need to do operator overloading.  Open up a blank C++ project and make a custom class with several different sub classes.  You'll have the same issues if you don't tell C++ how to compare your classes & objects.  Since it doesn't know how to do that for you by default.  It knows how to compare datatypes like numbers already so that is why it works.


We also need to know what kind of check are you wanting to do.  Type Only, Static Stats Only, Changing Stats Only, Location, Action, etc.  Judging from what you are saying I'd say Type Comparison is what you are looking for.


Was trying to come up with an example but even I need to work on my C++ more.  In this case it can get count partly working but it still needs changes for it to work with subclasses.  Think of it as a challenge to figure it out. :)

in .h file
bool operator ==(const TypeCheckedOBJ &)const;
bool operator !=(const TypeCheckedOBJ &rightside)const
{
        return !(*this == rightside);
}

 

in .cpp file

bool TypeCheckedOBJ::operator ==(const TypeCheckedOBJ &rightside)const
{
        return (typeid(*this) == typeid(rightside));
}
 

in main
TypeCheckedOBJ test1("Test1"), test2("Test2");
TypeCheckedOne test3("Test3"), test4("Test4");
TypeCheckedTwo test5("Test5"), test6("Test6");

vector<TypeCheckedOBJ> objlist;
objlist.push_back(test1);
objlist.push_back(test2);
objlist.push_back(test3);
objlist.push_back(test4);
objlist.push_back(test5);
objlist.push_back(test6);

cout << "Count Test_1: " << count(objlist.begin(), objlist.end(), test1) << endl;
cout << "Count Test_2: " << count(objlist.begin(), objlist.end(), test3) << endl;
cout << "Count Test_3: " << count(objlist.begin(), objlist.end(), test5) << endl;
 
I made a base class and two sub classes off of it to test.  In this case count likely fails for the sub classes because everyone is because changed to the base class.  From here though it should be easy to find a solution.  Since this is a pure C++ issue hunt around some site that help C++ programmers.


Keep in mind this code above is what can be used with any class if you change out the class names.  Meantime I'll keep working on this for when it might be useful again.

Keep in mind though there are many other ways but since you wanted to use count I wanted to see if count was even usable.  It is just there might be more work than it is worth to get it to fully work.
« Last Edit: March 01, 2015, 01:44:01 am by StormWingDelta »
I have many ideas but need the help of others to find way to make use of them.

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Counting sprites of specific type in vector
« Reply #7 on: March 01, 2015, 12:23:07 pm »
Ok, as I see that this code doesn't work for me, I have another, more simple approach.
But the problem with it is, that it only works with red squares. The question is, how to detect if a red or a blue square was erased. Knowing this, I could make a simple if condition, that decrements the right variables.


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

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(600,600), "Map", sf::Style::Close);
    mMainWindow.setFramerateLimit(40);
    mMainWindow.setKeyRepeatEnabled(false);

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

        sf::Image image2;
    image2.create(50, 50, sf::Color::Blue);
        sf::Texture texture2;
        texture2.loadFromImage(image2);

    std::vector<sf::Sprite> EnemyVector;

                int numberofredsquares = 0;
                int numberofbluesquares = 0;

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

        bool creating = false;
                bool creating2 = 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:
                                if (event.key.code == sf::Keyboard::A)
                                {
                                        creating = true;
                                        break;
                                }
                                if (event.key.code == sf::Keyboard::B)
                                {
                                        creating2 = true;
                                        break;
                                }
            case sf::Event::MouseButtonPressed:
                                if (event.mouseButton.button == sf::Mouse::Right)
                                {
                                        rightclick = true;
                                        mousePos = sf::Vector2i (event.mouseButton.x, event.mouseButton.y);
                                        break;
                                }
                break;
            }
                }
        if (creating)
        {
            sf::Sprite sprite;
            mousePos = (mousePos == sf::Vector2i(0, 0) ? sf::Mouse::getPosition(mMainWindow) : mousePos);
                        sprite.setTexture(texture);

            sprite.setOrigin(static_cast<float>(sprite.getTextureRect().width) / 2, static_cast<float>(sprite.getTextureRect().height) / 2);
            sprite.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
            EnemyVector.push_back(sprite);
                        numberofredsquares++;
                        std::cout << "number of red squares: " << numberofredsquares << std::endl;
                }
                if (creating2)
        {
            sf::Sprite sprite2;
            mousePos = (mousePos == sf::Vector2i(0, 0) ? sf::Mouse::getPosition(mMainWindow) : mousePos);
                        sprite2.setTexture(texture2);

            sprite2.setOrigin(static_cast<float>(sprite2.getTextureRect().width) / 2, static_cast<float>(sprite2.getTextureRect().height) / 2);
            sprite2.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
            EnemyVector.push_back(sprite2);
                        numberofbluesquares++;
                        std::cout << "number of blue squares: " << numberofbluesquares << std::endl;
                }
                if (rightclick)
                {
                        for (auto& SpriteIt = EnemyVector.rbegin(); SpriteIt != EnemyVector.rend(); ++SpriteIt)
            {
                sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)));
                if (SpriteIt->getGlobalBounds().contains(mousecoords))
                                {
                                        EnemyVector.erase( std::next(SpriteIt).base() );
                                        numberofredsquares--;
                                       
                                        std::cout << "number of red squares: " << numberofredsquares << std::endl;
                                        break;
                                }
            }
        }

        mMainWindow.clear();
        for (auto& enemy = EnemyVector.begin(); enemy != EnemyVector.end(); ++enemy)
        {
            mMainWindow.draw(*enemy);
        }
        mMainWindow.display();
    }
    return 0;
}


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Counting sprites of specific type in vector
« Reply #8 on: March 01, 2015, 01:02:52 pm »
A few solutions, to apply directly or for inspiration:

1.
if (SpriteIt->getTexture() == &texture1)
    red;
else
    blue;

2. Store blue sprites and red sprites in two separate containers.

3. Wrap sf::Sprite in your own class which adds an attribute that allows you to directly query its color.
Laurent Gomila - SFML developer

 

anything