0
\$\begingroup\$

I came across the blog post Understanding GameTime, and after lots of reading on fixed time steps in game loops this is the approach I would like to take. In summary, this is the logic from the post:

  1. Set the desired time spent in Update + Draw as 1/60 of a second (fixed 60 fps).
  2. If time elapsed since last Update + Draw is exactly 1/60 of a second:

    • Call Update
    • Call Draw
    • Tick (Game loops.)
  3. If time elapsed since last Update + Draw takes less than 1/60 of a second:

    • Call Update
    • Call Draw
    • Look at the Clock (Time left over? Wait.)
    • Tick (Game loops.)
  4. If time elapsed since last Update + Draw takes more than 1/60 of a second?

    • Call Update (Until we catch up.)
    • Call Draw
    • Tick (Game loops.)

I guess the two parts I'm having trouble understanding is in #3, how would the waiting be accomplished since thread sleeps are often not accurate enough, and what does it mean in #4 to call update until we catch up? Catch up to what since the time elapsed is already greater than our target 60 fps?

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I guess the two parts I'm having trouble understanding is in #3, how would the waiting be accomplished since thread sleeps are often not accurate enough?

Can't answer this for sure as I haven't seen the XNA source code.

MonoGame uses thread.sleep

// NOTE: While sleep can be inaccurate in general it is 
// accurate enough for frame limiting purposes if some
// fluctuation is an acceptable result

From my understanding System.Diagnostics.Stopwatch is likely the highest resolution timekeeping utility you have access to as a part of .net.

What does it mean in #4 to call update until we catch up? Catch up to what since the time elapsed is already greater than our target 60 fps?

Lets say each |----| is a 60hz tick. * is when update is actually called. For some reason a first update took way to long (perhaps it loaded a bunch of new stuff). Basically all 4 is saying is its going to call update as fast as possible with no waiting until the number of times update has been called has caught up to the number of times it ought to have been called optimally .

*       *    *    *    *   *   *   *<---- Caught up here
|----|----|----|----|----|----|----|
0    1    2    3    4    5    6    7
\$\endgroup\$
3
  • \$\begingroup\$ "...until the number of times update has been called has caught up to the number of times it ought to have been called optimally" Does that mean keeping track of how many ticks have occurred for comparison against how many ticks should have occurred? If not, what would be the appropriate comparison? On the XNA blog post I mentioned he did say at some point they give up if it gets too far behind, which confused me further. \$\endgroup\$
    – user6214
    Jul 21, 2014 at 12:22
  • \$\begingroup\$ "Does that mean keeping track of how many ticks have occurred for comparison against how many ticks should have occurred?" Yes. "On the XNA blog post I mentioned he did say at some point they give up if it gets too far behind, which confused me further." Basically if takes too long to catch up it is best to revert back to running at regular intervals. If you can't even do that it degrades into just running as quickly as possible. I know my language is vague but without having seen exactly how XNA implements the looping broad strokes is the best I can do. \$\endgroup\$ Jul 21, 2014 at 14:22
  • \$\begingroup\$ That's okay, even with a little vagueness it does clarify things for me so I don't head down the wrong path. Thanks. \$\endgroup\$
    – user6214
    Jul 21, 2014 at 14:50

You must log in to answer this question.