I'm interested in your code in: Re: SDL alternative to glutIdleFunc()?

Stoned koala bears drooled eucalyptus spit in awe as
benang at cs.its.ac.id said:

Hi there, I’ve looked at your reply in SDL maillist and it got my
attention. I’m interested in the code below. It’s pretty much the same
with mine except I don’t use openGL and I called SDL_GetTicks in all the
objects (not only once like you did). I have 2 questions regarding this.

  1. How do you send the notification of the elapsed time to all the objects?

I have an interface called Thinker which has a single abstract method:
virtual void think(float dt) =0;
Classes that need to observe time passing extend this class and provide
a think() method that can be called when time has passed.

I then declare myself a set of Thinker*:

typedef std::set<Thinker *> thinkerset;
typedef thinkerset::iterator thinksi;
thinkerset thinkers;

And when time has elapsed (once each frame), I tell all the thinkers:

for(thinksi i=thinkers.begin();i!=thinkers.end();++i)
(*i)->think(dt);

(or be clever and use for_each, bind2nd and something like mem_fun.
whatever)

Objects that are Thinkers register themselves with a thinker set in
their constructor and remove themselves from the set in their
destructor. Asking for the global clock once per frame is a good idea
since it ensures that a whole frame is generated for one instant in
time; you don’t have different things rendered at different virtual
times in the same frame.

Variable and type names changed to protect the guilty.

  1. And if the elapsed time is not enough for the object to change it
    state, won’t it be always unchanged because the delta will be reseted in
    the next loop? Well it is only my assumption because you didn’t fully

With float time and simulating continuous motion, there’s no such thing
as no motion, things just move a very small distance. If you’re using
SDL ticks (millisecond precision), then yes, sometimes it could tell
you that no time has elapsed, in which case nothing happens.

If you want something to change in discrete and fixed steps (“enough
for the object to change its state”), you want to use a time
accumulator. When you receive a think event, add the dt to the
accumulator; while the contents of the accumulator are large enough,
consume some time like this (code not tested!):

class FiniteThinker : public Thinker {
public:

FiniteThinker(float step) : timestep(step), timeaccum(0.0f) {}

virtual void think(float dt)
{
	timeaccum+=dt;
	while(timeaccum >= timestep){
		fixedthink(timestep);
		timeaccum-=timestep;
	}
}

virtual void fixedthink(float dt) =0;

private:

float timestep;
float timeaccum;

}

Then in a subclass, provide fixedthink() which will be called always
with the same dt. If a big realtime step occurs, you get lots of
fixedthink() calls; if a small realtime step occurs, you may get no
fixedthink() calls.

That approach is useful for systems that require a guaranteed small
timestep, e.g. spring simulations. It’s useful also for making time
move in big chunks so that something occurs only occasionally.

If you have a search of the sdl mailing list archive there have been a
number of excellent discussions on this including links to a couple of
decent howtos.–
William Brodie-Tyrrell

Carpe Diem - fish of the day.

<@William_Brodie-Tyrre>
http://www.brodie-tyrrell.org/