4
\$\begingroup\$

Most of the posts on fixed time steps say something like this:

State previous;
State current;

while ( !quit )
{
     double newTime = time();
     double frameTime = newTime - currentTime;
     if ( frameTime > 0.25 )
          frameTime = 0.25;   // note: max frame time to avoid spiral of death
     currentTime = newTime;

     accumulator += frameTime;

     while ( accumulator >= dt )
     {
          previousState = currentState;
          integrate( currentState, t, dt );
          t += dt;
          accumulator -= dt;
     }

     const double alpha = accumulator / dt;

     State state = currentState*alpha + previousState * ( 1.0 - alpha );

     render( state );

How do they calculate and save a State snapshot of the whole world? do they just make memcpy's or something? I'm working in Flash and don't have that kind of cloning capability.

\$\endgroup\$
4
  • \$\begingroup\$ If it wasn't for that last comment, your code could be from ANY language haha. \$\endgroup\$ Jul 6, 2011 at 3:59
  • \$\begingroup\$ previous = current + 0 ? previous = current + ZERO (ZERO being the empty state)? previous = current * 1? how this linear operations works on your State object? \$\endgroup\$
    – FxIII
    Jul 6, 2011 at 8:00
  • 1
    \$\begingroup\$ @Daniel Well, it's obvious not Brainf**k. \$\endgroup\$ Jul 6, 2011 at 13:43
  • \$\begingroup\$ It's not Actionscript either.. \$\endgroup\$
    – bummzack
    Jul 6, 2011 at 17:50

2 Answers 2

2
\$\begingroup\$

Generally speaking I would read this pseudocode as a rough overview, and break each bit down into handling all the relevant state piece by piece.

For example:

previousState = currentState

might become:

for each object in world:
    object.previousState = copyOf(object.CurrentState)

And:

state = currentState*alpha + previousState * ( 1.0 - alpha );

would become:

for each object in world:
    renderableState = object.currentState*alpha + object.previousState * ( 1.0 - alpha );

...and so on.

Once you're down to the level of an individual object there is usually very little state that you actually need to be able to clone. In a simple game it might just be the position, for example. If your position is a Point, you can clone() it to get a copy. Or you might just have the value types which you can copy trivially. Either way, when you dig down into the specific state, you usually end up with small pieces that are easy to copy.

\$\endgroup\$
2
  • \$\begingroup\$ +1 nice answer, clear and simple. Just one thing to add: Not all states must be linear interpolated, some must be spherical interpolated (Slerp) like quaternions or direction vectors etc \$\endgroup\$ Jul 6, 2011 at 19:10
  • \$\begingroup\$ Yeah, or transform the data to a form that can be linearly interpolated (eg. polar coordinates), but that's not always practical. \$\endgroup\$
    – Kylotan
    Jul 7, 2011 at 0:20
0
\$\begingroup\$

If you have problems with deep copy, you can store the reference of the current state in previousState, and delegate the creation of a new state in the integration step. This implies that you have the responsibility to destroy the previousState before updating ( you can delegate this to your garbage collector if there is one)

Pseudocode:

StateRef previous;
StateRef current;
[...]
current = initState(genericStateSource);
[...]
    free(previous);
    previous = current;
    current = integrate(current,t,dt);

Evolution:

+-----+-----+-----+-----+
| n+1 | n+2 | n+3 | n+4 |  loop start
+-----+-----+-----+-----+
              ^-p   ^-c

+-----+-----+-----+-----+
| n+1 | n+2 | n+3 | n+4 | free n+3; advance p
+-----+-----+-----+-----+
                   ^-p,c

+-----+-----+-----+-----+-----+
| n+1 | n+2 | n+3 | n+4 | n+5 | integration step
+-----+-----+-----+-----+-----+
                    ^-p   ^-c

About your code there are some problems:

First you do not have to store the previous state in each iteration (particularly if it is is expensive): you know exactly how much iterations you will do as soon as you compute accumulator.

There is an error to the while loop: basically you integrate each in each step using a black-box integrator then you do a linear interpolation between last and current state. To make sure that this makes sense the the interpolation has to be done between the last state before and the first state AFTER the point of interest.

You did:

|-----|-----|-----|-----|---- |
                  p   ^ c

But you should do:

|-----|-----|-----|-----|---- |
                        p   ^ c

I.e. you have to integrate another step over the end if you have to interpolate: again, you know if is the case as soon as you compute accumulator

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .