The simple fact is that since most monitors have a 60Hz refresh rate anything beyond that is wasted – then again maybe not. Recently I was trying to scroll a 2D image from left to right in one of my windows C#/XNA application. Oh wait, the other way around. In any case the direction was not the problem. The problem was that the scrolling was not exactly smooth. The sprite seemed to slow down and accelerate at various points during the animation. That was particularly visible when displaying the game in windowed mode. Now I know that I am a master in the art of writing code with features – what most people refer to as bugs these days. It keeps my users occupied and hopefully has successfully motivated a few of them to get into programming in order to solve the problems themselves. This time however it was not my fault. I hate it when development tools cause problems like that. How dare they torture my victims?
I think the problem relates to the time measurements used internally by XNA not been accurate enough. XNA calls the update and draw method at every tick, where a tick is a fraction of a second dependant on the frame rate. If that is set to 60 frames per second then a tick should be exactly 1/60 seconds long. This is not as easy to achieve as it sound in the context of a multitasking operating system. If the timing is wrong then update and draw would be called a bit sooner or a bit later which is what I think is causing the animation in the scenario discussed above not been as smooth as it should had been. Certainly disabling the frame rate limit (see code below) seemed to fix the problem:
graphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
game.IsFixedTimeStep = false;
graphicsDeviceManager.ApplyChanges();
All of the sudden the animation was super smooth which was not surprising considering I had around 9000 frames per second shown, or at least calculated (plenty of calls to the draw and update methods to compensate for any timing errors). Thus I solved the problem by introducing a new one – that of overheating my monstrous graphics card. Some sceptics might argue that this solution is a tiny bit extreme considering 9000 frames per second mean 8940 frames more than what most monitors can display and most humans can see. For my next magic trick I had to conjure a trick that would allow enough extra frames to be displayed but would not actually put my graphics card out of commission. As it turns out XNA allows modifying the time that a tick takes. That can be used to set the frame rate to a preset level. The following function does just that:
public void SetFrameRate(
GraphicsDeviceManager manager, int frames)
{
double dt = (double)1000 / (double)frames;
manager.SynchronizeWithVerticalRetrace = false;
game.TargetElapsedTime = TimeSpan.FromMilliseconds(dt);
manager.ApplyChanges();
}
The frames parameter passed to this method specifies the target frames per second we want to achieve. As it turns out that magic number was around 250 (around 4 times higher than the default 60 fps). That solution too can be seen as wasteful but so far I have been unable to produce another. Let me know if you have any ideas.