2

I have a container of objects:

std::vector<sf::Drawable> gameObjects;

My goal is to iterate through these objects and draw them:

for (auto it : gameObjects)
{
     window.draw(*it);
}

You can assume these methods are already implemented. What I mean by 'animate': I want these objects drawn one at a time, rather than all at once immediately.

void Run::render()
{
    window.clear(colorWindow);

    for (auto it : gameObjects)
    {
         window.draw(*it);
    }

    window.display();    
}

That is, have every render() draw an additional object in the container. Do you know how I can go about doing this? Thank you in advance.


edit: I've tried something unconventional - I dont think it's good practice, but it works:

int count = 0;
int countReset = 1;

...

while (countReset > count)
{
    objects.at(count++).draw(window);

}
countReset++;
count = 0;
onesiumus
  • 279
  • 6
  • 26

2 Answers2

2

You should never make decisions about your game in your rendering. You should have an update method somewhere, that makes decisions on how input and time passed affect your game world. Rendering should only do one thing: rendering. No decision making, no data manipulation.

You could for example use a compound class to indicate which object should be drawn or you could derive your own base class from sf::Drawable and implement a bool IsVisible() const; method. Either way, the decision if it's drawn is made elsewhere, the rendering is only executing commands what to render specifically:

struct MaybeDrawn
{
   bool IsVisible;
   sf::Drawable Object;      
};

...

std::vector<MaybeDrawn> gameObjects;

...

void Run::render()
{
    window.clear(colorWindow);

    for (auto it : gameObjects)
    {
         if(it->IsVisible)
         {
             window.draw(it->Object);
         }
    }

    window.display();    
}

Your decision, how and when to set the bool to true should happen in your Update/ChangeWorld method. Maybe you want to have a look here for a general description on how to structure a game and how to build a timer.

Alternatively, you could leave your program as it is and insert and/or delete from your vector in your decision making method.

Community
  • 1
  • 1
nvoigt
  • 75,013
  • 26
  • 93
  • 142
1

Use a static counter for your index in list of objects. Measure time and incremente the counter if a time period has elapsed. So next time is drawn next object in list.

#include <chrono>

void Run::render()
{
    // actual time
    std::chrono::high_resolution_clock::time_point actTime = std::chrono::high_resolution_clock::now();

    // remember time
    static bool init = false;
    std::chrono::high_resolution_clock::time_point lastTime;
    if ( !init )
    {
        lastTime = actTime;
        init = true;
    }

    // delta time
    long microseconds = std::chrono::duration_cast<std::chrono::duration<long, std::micro> >( actTime - lastTime ).count();
    double deltaTms = ((double)microseconds) / 1000.0;

    window.clear(colorWindow);

    static size_t actObjInx = 0;
    window.draw(gameObjects[actObjInx]);

    // increment object index if time period has elapsed
    if ( deltaTms > 100.0 ) // 0.1 seconds
    {
        lastTime = actTime;

        actObjInx ++;
        if ( actObjInx == gameObjects.size() )
            actObjInx = 0;
    }

    window.display();
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • This will animate faster, the faster my CPU/GPU can render... on modern CPUs, it will just be a wild flickering. – nvoigt Dec 20 '15 at 09:39
  • @nvoigt Youe have to measue elapsed time since last call of Run::render. Only increment `actObjInx` if time threshold reached. On moment i'll give you an example. – Rabbid76 Dec 20 '15 at 09:50