When creating a looping timer for something like a game with an "update" function that's called repeatedly at intervals, there's several ways to represent this, including:
Option A: Incrementing timer values and resetting to 0:
- Represent the current timer value and add to it the delta time.
- When the timer value exceeds the timer maximum, set the timer value to 0
Option A presents the issue of timers not actually being once every N seconds, since it's possible for the timer value to exceed the maximum between checks and therefore it'll pretty much always be slightly more than the intended time. If such precision isn't needed, for example if doing something expensive every few seconds instead of every update, this method is acceptable.
Option B: Same as A, except reduce by the timer maximum whenever the timer exceeds the maximum. This solves the issue of A, ensuring that the timer is triggering almost exactly on its intended timing. It present a new issue though - if the timer value ever exceeds the maximum by a factor of more than 2, such as if there's ever an update that "hangs" for a while and the delta time becomes larger than the twice timer maximum, then the timer value will be decremented to a value larger than the maximum, causing it to trigger in the next update (as many times in a row as the value is multiples of the maximum, e.g. 8x the maximum = triggers for the next 8 loops).
This could be useful if you want to guarantee that over a very large time frame an action will be performed a certain number of times.
Option C: Same as B, except the timer reduction/reset is encapsulate in a while loop:
while(timerValue > timerMaximum) {
timerValue -= timerMaximum;
}
Which resolves option B's issue, but would be inefficient if the timer value exceeds the maximum by a huge factor.
Option D: Instead of decrementing the value when it exceeds the maximum, do the following:
timerValue = ((timerValue / timerMax) % 1) * timerMax;
This finds the timer's value as a proportion of the timer maximum, and sets it to the fractional part of that proportion multiplied by the maximum, achieving a nearly identical result as option C, but without using any loops.
Since all of these methods could be useful for different applications, depending on the acceptable precision and desired behaviour, how do the performances of each of these methods compare?