So I guess the thing that really has me scratching my head... is how do i calculate my total frame time. What is a good benchmark to judge how the application is running as a whole? What frame rate am I calculating?
Use QueryPerformanceFrequency() and QueryPerformanceCounter() to create a timer class that can represent time in microseconds. Time must be maintained in integer form, not floating-point.
At the start of every frame you update the timer, which itself keeps track of the previous time it had along with the new time. The amount of time between updates can be calculated easily.
If you update once per frame you can use this information to keep track of how much time has passed since the last frame.
My first thought was to just calculate the time between game loop iterations:
///FPS Calculations
float FrameRateList[FPS_CALC_BUFFER]; //Container holds previous FrameRates
for (int x = 0; x < FPS_CALC_BUFFER; x++) FrameRateList[x] = 0; //zero out buffer
float PrevFrameTime = 0; //Time of last frame
float FrameRate = 0; //Current FrameRate
int ListIndex = 0; //Frame rate buffer index (increments every frame)
///Game Loop
while (SimTimer.GetElapsedTime() < RUN_TIME){
//FPS Calculation
FrameRate = 1/(SimTimer.GetElapsedTime() - PrevFrameTime); //calculate this frames rate
PrevFrameTime = SimTimer.GetElapsedTime(); //save this frames timestamp for next frame
FrameRateList[ListIndex] = FrameRate; //add framerate to list
if (++ListIndex == FPS_CALC_BUFFER) ListIndex = 0; //increment list index (start at beginning if we've hit the limit)
//physics
if (PhysicsTimer.GetElapsedTime() >= (1/PHYSICS_RATE)){
mWorld.Step(1/PHYSICS_RATE,6,2); //step the world
PhysicsTimer.Reset();
}
//Render
if (RenderTimer.GetElapsedTime() >= (1/RENDER_RATE)){
mWindow.Clear(sf::Color::White);
//draw some stuff
mWindow.Display();
RenderTimer.Reset();
}
//debug
if (DebugTimer.GetElapsedTime() >= (1/DEBUG_RATE)){
//Calculate the average of all the framerates in the buffer
//... and output to console
DebugTimer.Reset();
}
}//... end loop
Your logic is flawed.
Let’s assume logical updates (which include physics) happen every 30 milliseconds.
You keep track of the time of the last update, and each frame you check to see if 30 milliseconds have passed, after which you perform a logical update.
What happens if 70 milliseconds have passed?
You will perform one update instead of the necessary 2.
int logicalUpdatesNeededThisTick = (currentTime - lastUpdateTime) / logicalUpdateInterval; // logicalUpdateInterval = 30.
while ( logicalUpdatesNeededThisTick-- ) {
// Advance logical timer by a fixed amount.
m_logicTimer.UpdateBy( logicalUpdateInterval * 1000ULL ); // 30 microseconds.
TickLogic(); // Handles physics and all logical updating.
}
Another flaw in your logic is that you are simply setting the last update time to whatever the current time is.
Going back to my example, let’s say for the sake of simplicity that we start at t = 0, and the first frame took 70 milliseconds.
Using my above fix you will update twice, which is correct.
But then you set the last update time to the current time, which is 70. That means your next logical update will happen at t = 100, when it should be at t = 90. You have lost 10 milliseconds.
Each time you update the logic, increase the “last logical update time” by the amount that each logical update represents. That would be 30 in my example case.
After your 2 updates, the last logical update time will be 60, and you will then correctly update at t = 90.
And finally, remove the limiter from your render function. Renders are always, logical updates are sometimes.
In some physics heavy AAA titles, physics will actually be updated many more times per frame than a render or other update. This done gain a better approximation of the curves objects trace as they interact; Forza 3 I believe runs a physics update at 300hz, render at 60 hz to match the display refresh. There are many methods of maintaining numerical stability in a physics simulation; small time steps can help.
I do not believe this is accurate. There may be a few special-case objects or subsystems that update faster than the render, but the rule of thumb is to keep the major logical update (which also consumes the task of physics) as slow as possible without causing problems to your simulation.
Contrary to common belief, running physics at smaller time steps decreases the accuracy of the simulation, because every tiny calculation incurs some degree of floating-point imprecision, and these small errors are cumulative throughout the life of the simulation.
Not only will the physics be more accurate at around 30 milliseconds, it will cost less to the CPU and the game will run more smoothly.
Supreme Commander on the other hand only updates it's simulation at 10 hz. Changes to the state of the world, (unit orders, etc.) are actually only updated 10 times a second; units are updated once per frame to interpolate between simulation updates, so they appear to move smoothly through the environment. Supreme Commander does this to make it possible to synchronize the thousands of entities that can exist in a multiplayer game across the network; without the long intervals it would not be possible to keep all clients in sync. (and even then it can break down sometimes).
Again, this is not likely to be accurate. This update speed is typically too low for a stable physics implementation.
Some subsystems may run at this speed, such as the sound engine, but probably not physics.
L. Spiro