Framerate logic

Blitz3D Forums/Blitz3D Programming/Framerate logic

Kiyoshi(Posted 2012) [#1]
This is a code snippet from IDEal's, well, snippets.



I know what this is, and what it does. However, I don't exactly know how it all works. I understand that it'll update the program more if it starts getting framerate issues, but thats all.

Knowing how to do something like this would be useful knowledge. I know I could very well just plug this into one of my programs, but I prefer using my own code -- and I can't code it until I understand it.

So would someone kindly break this down for me, and explain to me how each part works? I'd greatly appreciate it, all that math is getting jumbled in my head. :)


Yasha(Posted 2012) [#2]
I was never able to comprehend that one for some reason. Something about it makes it really difficult for me to track what's going on (even though I know what's going on!). I ended up writing my own version for the same reasons as you. Take a look, if you like:



I assume it's inferior to the "official" version by Mark above, but it's been good enough for commercial production code so far (!).

The outer loop runs at not more than the desired framerate described by DrawRate. RenderTime contains the maximum amount of time in milliseconds that the outer loop can take without slowing this framerate down. RenderTime is used with cTime (when the current iteration began) to determine how much time is "spare" at the end of the loop and free it with Delay (note: this step is not part of the theory: it's just because Blitz3D will hog CPU time unless it's freed explicitly, which will heat up and slow down your PC).

The inner "update" loop is asked to run at the framerate described by UpdateRate. This means that there should be updateTime milliseconds between each start of the inner loop. The accumulator "accum" is filled with the time taken by the outer loop as it begins, and can then be tested by the inner loop to see if enough time has passed that it should iterate again. Because updateTime and the rendering time aren't quite the same, accum will fluctuate; sometimes it won't be a whole updateTime, in which case the update is skipped that frame; or it might be more than one, in which case multiple updates will happen. This will ensure that the average framerate of the inner loop over time stays at UpdateRate, but note that some of the updates may be happening in bursts with little breaks between them. This is normal and OK as long as it doesn't affect the visual experience (it's the average update rate that affects input smoothness).

However, because of these "bursts", some render iterations will contain more update iterations than others and therefore objects will appear to move shakily onscreen. The render tweening exists solely to correct this effect (the fixed separate update rates are entirely handled without tweening).

After the update loop, it sees how much is left in the accumulator and considers this "progress towards the next update". Therefore, instead of rendering the scene where it actually is as of the last update, it can change the rendering position so that the objects appeared to move smoothly based on how much time since that update has elapsed.

(As a minor consequence, it's actually also positioning them one frame behind: between the previous two updates; but this is good as it means they won't be tweened into positions they shouldn't have been able to reach.)


Kiyoshi(Posted 2012) [#3]
Thanks Yasha. This helps me a lot; I'm already working on my own version of this now. And imo, yours is easier to understand as well (Not to say either version is superior to the other, I honestly wouldn't know).

Many thanks!