0
\$\begingroup\$

I know the following line of code has the effect of moving 3 units per milliseconds independent of framerate, but my sucky mathematical intuition is unable to understand WHY this works

translation *= 3 * (float)gameTime.ElapsedGameTime.TotalMilliSeconds

Could someone please explain why this works?

Are there any other common techniques / variations of framerate independent implementations operations like this?

\$\endgroup\$
3
  • \$\begingroup\$ A past answer of mine should explain what's going on. \$\endgroup\$ Jul 13, 2012 at 4:07
  • 2
    \$\begingroup\$ I assume the *= should be +=? \$\endgroup\$ Jul 13, 2012 at 4:28
  • \$\begingroup\$ Note: there is a major difference between a variable timestep (multiplying by the time elapsed since the last update), and a fixed timestep (multiplying always by the same amount, e.g. 1/60th of a second, regardless of actual time elapsed). A fixed timestep is often preferred - being deterministic, it offers advantages like letting you recreate and replay a buggy scenario over and over to work out what's happening, making debugging (and your life by extension) easier. Variable timesteps don't go so easy on you: they're non-deterministic and your scenario could play out differently each time. \$\endgroup\$ Jul 13, 2012 at 6:44

1 Answer 1

7
\$\begingroup\$

Let's say, for the sake of argument, that every frame takes the same amount of time: \$\Delta t\$. So if you say that \$t\$ milliseconds have elapsed since you started your game, you could also say that (\$n \cdot \Delta t\$) milliseconds have passed (\$n\$ frames that each took \$\Delta t\$ milliseconds).

You're applying the change to the translation variable every frame, which you can mathematically think of as multiplying by the number of frames that have passed so far. And using the fact that we already know the units of the number "3" (they are "units per millisecond"), we can put together an equation for the current translation, complete with units:

$$ \text{translation} = (\text{initial translation}) + n\text{ frames} \cdot \left( 3 \frac {\text{units}} {\text{millisecond}} \cdot \Delta t \frac {\text{milliseconds}} {\text{frame}} \right) $$

Let's cancel a few of the units: $$ \require{cancel} \text{translation} = (\text{initial translation}) + n\text{ } \cancel{\text{frames}} \cdot \left( 3 \frac {\text{units}} {\cancel{\text{millisecond}}} \cdot \Delta t \frac {\cancel{\text{milliseconds}}} {\cancel{\text{frame}}} \right) $$

What do we have now?

$$ \begin{align} \text{translation} &= (\text{initial translation}) + (3 \cdot n \cdot \Delta t)\text{ units} \\ &= (\text{initial translation}) + (3 \cdot t)\text{ units} \end{align} $$

Remember that \$t\$ is the number of milliseconds that have elapsed since you started your game. That's simple enough! Every time your t goes up by one, your translation increases by 3 units. That's the exactly what "3 units per millisecond" means. And that's why it works.

This works even when your velocity (the "3") changes frame-by-frame, as well as when the length of a frame changes. Explaining that properly requires calculus and an explanation of numerical integration. But it basically boils down to this same logic.


There are variations of this, yes, but this is by far the most common; it works pretty much anywhere you're adding some value to a variable every frame.

\$\endgroup\$
2
  • \$\begingroup\$ If it's indeed the number of milliseconds since the game started, then it should be: translation = 3 * totalTime, usually you'll get the time elapsed since the last frame, then you would use translation += 3 * deltaTime. \$\endgroup\$
    – bummzack
    Jul 13, 2012 at 6:24
  • \$\begingroup\$ t is my imaginary variable for the time since the beginning of the game. XNA's ElapsedGameTime, as used in the code in the question, is the delta time. \$\endgroup\$ Jul 13, 2012 at 14:43

You must log in to answer this question.

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