The interpolation value is because if you are drawing at say, 60 FPS and only updating at 30 hz, you're drawing every ~16.6 ms and only moving things every ~33.3 ms. The point is to conceptually think of real time and game time as separate.
When comparing to the DeWitters game loop, I can see they both use an interpolation value to render in-between the actual physics states, but the main difference is the introduction of the constant dt value which is independent from the actual time between updates, that being represented by frameTime.
If I understand this correctly then the end result is that:
- Updates will happen exactly every dt mlliseconds (assuming we're using milliseconds) on average, with updates only taking place for every whole multiple of dt milliseconds. Though the real time between updates will still presumably fluctuate.
- Unexpectedly long times between frames will result in skipping render frames to catch up with more update frames, with the simulation progress between update frames being capped at a certain level, resulting in the simulation actually slowing down.
- Due to the update frequency fluctuating, interpolation is used to smooth rendering between updates (which come dt milliseconds apart on average, but aren't consistent).
When you're using variable time you're literally injecting the time that passed since the last frame into the game update(at least as accurately as we can measure it.) If it took 9.12 ms then we will be telling game objects to update by that much. With a fixed time step its more like you collect time in an accumulator and the simulation consumes it when it needs to advance, if it took us 90 ms to draw then the update loop will run once, subtract the time spent(~33.3 ms) ~56.7, run the loop again, ~23.4 ms. Now we have run two simulation loops in a very small window of time but the game code jumps ahead as if it were simulating fixed sets of time.
The interpolation value comes into play because when you aren't updating, nothing in your game will move, you'll literally be drawing the same scene redundantly. In that case you might as well have the FPS locked to whatever the update rate is. We get around that problem by using interpolation, we take the previous and current position of objects and draw states inbetween, to give the illusion the game is in motion still, even though it isn't actually updating. This all happens in a millisecond window, so it is hard if not impossible for the viewer to actually understand we are a frame behind, but the smooth motion makes a very noticable impact.
He passes dt into integrate because integrate is basically pseudocode for "do a bunch of physics simulation" even if your timestep is fixed you probably want to pass time to the simulation, because if you don't then all of your code will be relying on how many times it is called rather than a value passed in, if you decide to adjust the fixed update rate of the game, suddenly everything is moving at a completely different speed or your debuff timers are counting down faster or slower than they should, quite awkward!
I also notice the integrate() function... that's not relevant for the general case of a game loop is it? It looks to me like it's just a continuation of his article on integration that he links to at the top of the page. Considering dt is constant and he passes dt into integrate(), I assume it's just for the specific example...
Passing in time is a sensible way to make it so you can change the top level code without any of the lower down code having to worry about -how- you get that time value, simply that you are getting it.
In a purist sense? A 64 bit unsigned integer would probably give you the most accurate results. In practice you could use something like a double because of the extreme precision, but ideally you always want to keep your time values as accurate as you can until you use them. I.e. if you want to interpolate between two positions don't turn that time into a float value until you actually divide the two times, then you only lose precision at -one- point. Integers in general will always be superior to floating point in terms of accuracy, unless your clock is giving a float value an int value will always retain perfect accuracy, even if it doesn't match up ideally to real time.
What kind of data type would be appropriate for keeping time?