Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does XNA timing work?

Tags:

c#

xna

How does XNA maintain a consistent and precise 60 FPS frame rate? Additionally, how does it maintain such precise timing without pegging the CPU at 100%?

like image 818
redman Avatar asked May 08 '10 21:05

redman


2 Answers

While luke’s code above is theoretical right the used methods and properties are not the best choices:

  • As the precision of DateTime.Now is only about 30ms (see C# DateTime.Now precision and give or take 20ms) its use for high performance timing is not advisable (60 FPS are 16ms). System.Diagnostics.Stopwatch is the timer of choice for real time .NET
  • Thread.Sleep suffers the same precision/resolution problem and is not guaranteed to sleep for the specified time only

The current XNA FX seems to hook into the Windows message loop and execute its internal pre-update each step and calling Game.Update only if it the elapsed time since the last update matches the specified framerate (e.g. each 16ms for the default settings). If you want to really know how the XNA FX does the job Reflector is your friend :)

Random tidbit: Back in the XNA GameStudio 1.0 Alpha/Beta time frame there were quite a few blog posts about the “perfect WinForms game loop”, albeit I fail to find them now…

like image 162
Björn Avatar answered Oct 21 '22 03:10

Björn


I don't know specifically how XNA does it but when playing around with OpenGL a few years ago I accomplished the same thing using some very simple code.

at the core of it i assume XNA has some sort of rendering loop, it may or may not be integrated with a standard even processing loop but for the sake of example lets assume it isn't. in this case you could write it some thing like this.

TimeSpan FrameInterval =  TimeSpan.FromMillis(1000.0/60.0);
DateTime PrevFrameTime = DateTime.MinValue;
while(true)
{
    DateTime CurrentFrameTime = DateTime.Now;
    TimeSpan diff = DateTime.Now - PrevFrameTime;
    if(diff < FrameInterval)
    {
        DrawScene();
        PrevFrameTime = CurrentFrameTime;
    }
    else
    {
        Thread.Sleep(FrameInterval - diff);
    }
}

In reality you would probably use something like Environment.Ticks instead of DateTimes (it would be more accurate), but i think that this illustrates the point. This should only call drawScene about 60 times a second, and the rest of the time the thread will be sleeping so it will not incur any CPU time.

like image 41
luke Avatar answered Oct 21 '22 02:10

luke