See the forum topic I created here: http://community.monogame.net/t/calling-draw-more-frequently-than-update/8328
I think it can be useful for many games if the Draw() method can be called more than once per Update(). Think of games that don't depend on fast user input like slower strategy or puzzle games. You might want to update the game logic only, say, 30 times a second, while still synchronizing the draw calls to the display's refresh rate of 60 or 120 Hz. During the remaining draw calls, you could interpolate animations or physics to provide players using a display with a refresh rate higher than the frequency of the core game loop with a smoother visual appearance.
Currently, it seems like Draw() will only ever be called at maximum once for every Update(). I would like to be able to decouple Draw() from Update(), so that the framework tries to call Draw()
This could be implemented via some additional property in the Game class in order to keep compatibility with XNA and the current defaults.
Maybe add a property bool IsFixedUpdate to Game and continue to drawing if IsFixedTimeStep is not set instead of sleeping the thread. It would require maintaining a second accumulator TimeSpan for Update separate from Draw.
Just a bool would not be sufficient, how does it decide whether to call Draw a second time or a third time or only once?
The most flexible way to expose this would be a Game.SuppressUpdate() which would work the same way as the existing Game.SuppressDraw().
If your game is within its Update() and your code determines it wants to do a second Update() rather than the normally subsequent Draw(), it calls SuppressDraw().
If your game is within Draw() and your code determines it wants to do a second Draw() rather than the normally subsequent Update(), it calls SuppressUpdate().
There is already the TargetElapsedTime TimeSpan which would suit. It only comes into play when IsFixedTimeStep is set, so if IsFixedUpdate && !IsFixedTimeStep then it can be used for this purpose.
I'd follow @jamesford42 suggestion. This kind of problem is typically something that developers will want to have full control over, and suppressing calls is the best way to do it IMO.
I don't see MG having yet another switch and task scheduler for that, it's a tricky problem and too few devs would make a use of it, hence I believe that leaving call suppression up to the dev is the most practical way to allow this.
I think talking about "supressing" Update() is fundamentally different from what I imagined. Let me make my idea more clear. Think of this fixed time-step game loop:
while (!quit) {
acc += now - last;
last = now;
while (acc >= 1 / UPDATE_FREQ) {
update();
acc -= 1 / UPDATE_FREQ;
}
draw();
}
Update() is called in a fixed time-step, whenever enough time has passed since the last time it was called. Draw() is completely unaltered by that. Whether update() is called or not, it doesn't care. It is always called at the end of the loop and blocks on vsync when enabled. This code does not instruct update() to be supressed or anything like that. The two don't interact with each other.
I don't want to supress Update() in favor of Draw() in certain conditions, I simply want Draw() to be generally called even if Update() wasn't. I can achieve this now by implementing my own fixed time-step on top of the variable time-step MonoGame provides me, for example with the code Jjagg posted in the discussion:
c#
_timeSinceUpdate += gameTime.ElapsedGameTime.TotalSeconds;
while (_timeSinceUpdate > 1f / UpdateRate) {
_timeSinceUpdate -= 1f / UpdateRate;
DoGameLogic();
}
This works and I can use it like that. I was just wondering if it might be useful to incorporate an option to do this automatically in the framework, especially since MonoGame already offers an option to use a fixed time-step.
Most helpful comment
I think talking about "supressing" Update() is fundamentally different from what I imagined. Let me make my idea more clear. Think of this fixed time-step game loop:
Update() is called in a fixed time-step, whenever enough time has passed since the last time it was called. Draw() is completely unaltered by that. Whether update() is called or not, it doesn't care. It is always called at the end of the loop and blocks on vsync when enabled. This code does not instruct update() to be supressed or anything like that. The two don't interact with each other.
I don't want to supress Update() in favor of Draw() in certain conditions, I simply want Draw() to be generally called even if Update() wasn't. I can achieve this now by implementing my own fixed time-step on top of the variable time-step MonoGame provides me, for example with the code Jjagg posted in the discussion:
c# _timeSinceUpdate += gameTime.ElapsedGameTime.TotalSeconds; while (_timeSinceUpdate > 1f / UpdateRate) { _timeSinceUpdate -= 1f / UpdateRate; DoGameLogic(); }This works and I can use it like that. I was just wondering if it might be useful to incorporate an option to do this automatically in the framework, especially since MonoGame already offers an option to use a fixed time-step.