4
\$\begingroup\$

I had some input problems which can be partially solved by unlocking game update rate. Now the input updates as fast as possible, but the game also calls the main Draw method a lot too. I believe there are some calls that may be omitted without causing any noticeable problems, and I'd like to know how I can do it.

I tried using code similar to frame rate counter code, but it just doesn't work. It either doesn't skip frames, or skips them all. Here it is:

double time = 0;
protected override void Draw(GameTime gameTime)
{
    double frameRate = 1.0 / 60;
    time += gameTime.ElapsedGameTime.TotalSeconds;
    if (time > frameRate)
    {
        time = time % frameRate;
    // the rest of the draw call

When the game window is active, only dark purple color is visible I guess that's application's default background color when nothing is being drawn. When the game window is not active, frame rate drops from infinity (though I get about 4000 fps) to around 50 (which is unusual, since the default frame rate is 60, but it's not an issue).

If I set frameRate value to lower than 1/50 (like 1/10) it becomes obvious that draw calls are skipped and the dark purple background is visible (and resources are being saved), but only when the window is inactive. So the game behaves as expected, but only when it is not in focus, which is not the way it is supposed to be played :)

How do I fix this?

I'd like to extend this to work on heavy logic updates, so they too are not done more than enough times per second. The game should only update input as fast as possible, and I believe, reducing the number of logic update and draw calls frees up resources for input update to use, increasing their frequency.


This is how I ended up doing this:

double interval = 1d / 60; // draw and do heavy updates only 60 frames per second
double time;

protected override void Update(GameTime gameTime)
{
    LightUpdate(gameTime);

    time += gameTime.ElapsedGameTime.TotalSeconds;

    if (time > interval)
        time = time % interval; // or while (time > interval) time -= interval;
    else
    {
        SuppressDraw();
        base.Update(gameTime);
        return;
    }

    HeavyUpdate(gameTime);
}

Saves frames, light update rate rose from 2k to 110k @100Hz which is a tremendous success!

\$\endgroup\$
8
  • \$\begingroup\$ What is the underlying issue you're trying to solve? What causes input to not work when updates and draws run at the same frame rate? Tinkering with XNA's internal timing might cause unforseen issues. Edit: also is base.Draw() inside the if statement in the code you posted? \$\endgroup\$
    – Roy T.
    Feb 24, 2013 at 18:12
  • \$\begingroup\$ The issue is too broad to fit in one question and partially unsolvable, but part of it is, by increasing input polling rate, which I am trying to do in this question. If you know a better way to poll input devices as fast as the OS does, please let me know. There is no base.Draw() inside the Draw method, as it doesn't appear necessary in any of my game projects. \$\endgroup\$ Feb 24, 2013 at 18:24
  • \$\begingroup\$ I think that I have never seen game that would need faster input updates then 60 times per second. Are you sure you are not trying to do something like inputing text based on keyboard states (instead of from winapi message loop)? \$\endgroup\$
    – Kikaimaru
    Feb 24, 2013 at 19:30
  • 1
    \$\begingroup\$ It's worth pointing out, for the sake of completeness, that input must be done on the main thread. \$\endgroup\$ Feb 25, 2013 at 6:15
  • 1
    \$\begingroup\$ This answer on SO gives some more details about what's going on. Dadoo Games has posted the correct answer here. \$\endgroup\$ Feb 25, 2013 at 6:20

2 Answers 2

6
\$\begingroup\$

If you know in your Update method that you don't need or want to render anything simply call SupressDraw() on your game object (http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.suppressdraw.aspx). You don't need to add any additional logic into your Draw method to handle this, and your frame skipping logic can be moved into your Update call.

\$\endgroup\$
1
  • \$\begingroup\$ This solved one part of my problem, the other I will post in my question. \$\endgroup\$ Feb 25, 2013 at 14:11
-3
\$\begingroup\$

For one I would not be using doubles in a modulus operation because 1/60th can't be represented exactly in a double variable and neither will the time accumulation so you will be getting a fair bit of round off error and due to that, some interesting results.

What I would do, if you simply have to do this, is to calculate your 1/60th constant outside of this loop, assign your time variable to that value initially, and then decrement it by elapsedTime in each draw call. When the time variable is equal to or below zero then do your draw and then add the 1/60th time to it. You will still get a minor amount of round off/up error but that should balance out between draw calls.

\$\endgroup\$
11
  • \$\begingroup\$ I put it inside a frequently called method for easy debugging. Didn't think it could cause bugs on its own. \$\endgroup\$ Feb 24, 2013 at 19:40
  • \$\begingroup\$ Well that would be my first suspicion. Its not the assignment of the 1/60th that is the problem(I just wouldnt put calculation of constants into the draw loop) rather that modulus that I am more skeptical of. You may want to explore exactly what elapsedTime values you are getting. \$\endgroup\$
    – RobCurr
    Feb 24, 2013 at 19:49
  • \$\begingroup\$ It doesn't seem to work unless the game window is inactive. I wonder which variables change when the window activates. \$\endgroup\$ Feb 24, 2013 at 20:01
  • 1
    \$\begingroup\$ -1 it is unlikely that this is a precision/round off error and he is already comparing using '>' so a slight error is not a problem. The worst case is that the average FPS for this game would be slightly less than the target FPS but we're talking a differences of a few hundredths of a millisecond here which is precision which is already impossible in a non-realtime environment. \$\endgroup\$
    – Roy T.
    Feb 24, 2013 at 21:41
  • 1
    \$\begingroup\$ @RobCurr for that we have comments, answers are supposed to answer the question \$\endgroup\$ Feb 26, 2013 at 19:08

You must log in to answer this question.

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