Separating update rate from render rate

Apprentice
Posts: 16
Joined: 2009.01
Post: #1
I want my game's logic update rate to be independent from it's frame rate, mostly because the frame rate is managed by a core video display link.

I've figured the way to do this is have a GameLoop object that uses an NSTimer to call its own update method at some rate, while my graphical view can call my GameLoop's draw method when it's time to render. Is this the proper way to do this?
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #2
Yeah, you can do it that way, but you'll have to have a separate thread for your update. Works absolutely great for me, but be warned that multithreaded programming does introduce some extra complication into the mix. If you haven't done it before, I wouldn't recommend it for your first project.

An easier way to do this is to call your update method from inside your draw method the correct amount of times per draw to keep a constant and decoupled update. See ThemsAllTook's excellent tutorial on this subject. It is very hard to grasp the first few times through, so be sure to read it very carefully.

[adding] runGame, in his tutorial would be your timer callback (display link callback in your case).
Quote this message in a reply
Apprentice
Posts: 16
Joined: 2009.01
Post: #3
AnotherJake Wrote:An easier way to do this is to call your update method from inside your draw method the correct amount of times per draw to keep a constant and decoupled update.
I can see how that works, though it still feels like the update rate is determined by the frame rate, since it's sort of driven by Core Video and the screen's refresh rate. I think making the game updated by a controller instead of a graphics view is the "proper" way to do thing anyway.

On the other hand, if I use multithreading, does that mean I'll have to "double buffer" my game state in case my graphical view tries to draw when the game is in the middle of an update? As in, the game's update writes to one buffer while the render uses the second buffer which has the state from the last update.

On a similar note, would it be worth "double buffering" my input, so that the game doesn't have to worry about any important pressed keys getting released in the middle of an update?
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #4
On the input: I take whatever input comes normally and save it in a few variables. Then at the end of each update I clear the non-persistent variables, like touches down. If that update didn't consume them then they weren't needed. No need for double-buffering input.

You don't need to double-buffer your game state either. I've done that with the multi-threaded approach but still don't think it's totally necessary there either. Basically the draw is just taking a "snapshot" of what your game state happens to be at the instant it draws. It has worked out smoothly and naturally for me all this time. [let me know if you ever see any weird effects without double-buffering in a threaded approach because I have yet to actually see that happen, although I expect it is entirely possible]

And as for being weird that it still seems tied to the draw, it's most definitely not tied to the draw. I know it seems strange, but it is completely decoupled. I've used it a lot. It works great. I get whatever FPS I can get, variably, but my tick rate is always rock-solid at whatever rate I choose. It is a genius technique, you should try it!
Quote this message in a reply
Apprentice
Posts: 16
Joined: 2009.01
Post: #5
AnotherJake Wrote:You don't need to double-buffer your game state either. I've done that with the multi-threaded approach but still don't think it's totally necessary there either. Basically the draw is just taking a "snapshot" of what your game state happens to be at the instant it draws. It has worked out smoothly and naturally for me all this time. [let me know if you ever see any weird effects without double-buffering in a threaded approach because I have yet to actually see that happen, although I expect it is entirely possible]
Well, the thing is that I intend on using an external physics library, and I'm not entirely sure how thread safe the libraries I've found are. And there's the possibility that either I or the libraries I'm using may set variable that are used in drawing to certain temporary values which would not be a good idea to use for drawing.

I actually got idea of state buffering from this article for XNA games.

Quote:And as for being weird that it still seems tied to the draw, it's most definitely not tied to the draw. I know it seems strange, but it is completely decoupled. I've used it a lot. It works great. I get whatever FPS I can get, variably, but my tick rate is always rock-solid at whatever rate I choose. It is a genius technique, you should try it!
OK, though I'm still not sure I like it because the graphical view should probably not have to know about the update process, especially if I want to reuse it. For example, I'm building a few tools to use with my game, including a model viewer. There's no game state at all in the model viewer, so I wouldn't want it's graphical view to possibly send an "update game" message to some game object every frame. It's more complicated than that since I still have to keep track of the model and allow the view to be moved and rotated, but hopefully you see my point.
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #6
Yes, I see your point. You'd still use update to control the rotation and position of your model in your model viewing tool. I make tools using this technique all the time. Honestly, it took me a long time (maybe a few weeks of experimenting) to mentally put together how it all works best, so don't feel bad at all if it doesn't come together for you immediately.

Here's a little shadow-mapping demo I put together last spring, which uses the same decoupled update technique, alongside Cocoa UI: http://www.anotherjake.com/AnotherJake/S...pping.html

That looks like a nice article, I bookmarked it, thanks! I learned to update my game separately from drawing back before I started playing with XNA, but after my experience with XNA, that solidified it for me. Unfortunately, I haven't had any time to play with XNA since a few months after it went public. Sweet stuff though!

As far as physics libs, I've used Newton both with the multi-threaded approach and with the update wrapped up inside the draw, with both approaches using a constant tick rate of 110 Hz (don't know why that seems smoothest for me, but I know 60 Hz is minimum for Newton). Worked fantastic. I don't know about other physics libs though, but they all require a constant tick rate as far as I've ever heard, so yes, that's another prime reason for a decoupled update.

Here's a very rudimentary example of one way to wrap up the update in the draw, in post #5: http://www.idevgames.com/forum/showthread.php?t=15317

The render timer is just a plain ol' 1k timer, but works the same as a display link when VBL synch is enabled. In fact, trying it both ways I've never seen any difference in performance, although I think the display link is theoretically the best approach.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Separating data, scene & rendering from user interface (preferably using bindings?) arrelid 6 3,007 Sep 19, 2006 02:26 PM
Last Post: arrelid
  Separating Axis Collision Detection Joseph Duchesne 4 3,886 Dec 22, 2005 10:18 AM
Last Post: Leisure Suit Lurie
  Resolution, Depth, & Refresh Rate nabobnick 1 2,245 Mar 9, 2005 01:40 PM
Last Post: arekkusu
  refresh rate on LCDs? kelvin 5 3,971 Jul 7, 2004 10:31 AM
Last Post: kelvin
  variable frame rate animation in Cocoa Damian 3 3,496 Jul 16, 2003 06:00 PM
Last Post: macboy