Timing system. It's about my code!
This post responds to my previous post about timing system in game, and issues I met during testing.
I mentioned in that post about the issue of tearing / unsynced / jittering of the result graphics I met whenever running in full screen mode of GLFW application. In fact, the problem lies inside my timing system.
The root cause is that in fixed mode, I sent in a wrong elapsed time into update() and render() function. So they all behave in unstable way. The correct value should be fixed elapsed time says 16.67 ms for 60 fps instead I sent in a value in the same way of non-fixed mode.
Another cause that might hurt it more is about burst elapsed time in startup. The way I hooked up and initialized time (or clock) in my system needed to be in concern. The start time is initialized outside working loop and before the window is created or showed up. Thus the starting gap produces large elapsed time that will hurt the internal timing system at the end, and make it to behave wrongly.
Let see the code of my fixed and working game's timing system.
/* ============ Haxek::mainLoop ============ */ void Haxek::mainLoop() { // Timing clock_t cur_clock = clock(); m_diffClock = cur_clock; m_diffClock = m_diffClock - m_frameClock; // Update frame clock m_frameClock = cur_clock; // Set time to elapsedTime float diff_secs = m_diffClock * 1.0f / CLOCKS_PER_SEC; m_elapsedTime.secs = diff_secs; m_elapsedTime.ms = diff_secs * 1000.0f; m_fps.update(m_elapsedTime); if(!m_isFixedTimestepMode) { update(m_elapsedTime); if(m_elapsedTime.ms > m_target_fixed_timestep_ms) { m_isGameRunningSlowly = true; m_droppedFrames++; // Catch up update(m_elapsedTime); } else { m_isGameRunningSlowly = false; render(m_elapsedTime); postRender(m_elapsedTime); m_fps.incrementFrame(); } } else { if(m_elapsedTime.ms > m_target_fixed_timestep_ms) { m_isGameRunningSlowly = true; m_droppedFrames++; // Catch up ElapsedTime fixedElapsedTime; fixedElapsedTime.secs = m_target_fixed_timestep_ms / 1000.0f; fixedElapsedTime.ms = m_target_fixed_timestep_ms; update(fixedElapsedTime); } else { m_isGameRunningSlowly = false; m_countingUpdateTime_ms += m_elapsedTime.ms; if(m_countingUpdateTime_ms > m_target_fixed_timestep_ms) { m_countingUpdateTime_ms -= m_target_fixed_timestep_ms; // fixed: major ElapsedTime fixedElapsedTime; fixedElapsedTime.secs = m_target_fixed_timestep_ms / 1000.0f; fixedElapsedTime.ms = m_target_fixed_timestep_ms; update(fixedElapsedTime); render(fixedElapsedTime); postRender(fixedElapsedTime); m_fps.incrementFrame(); } } } // Post postMainLoop(); }
I designed it to be portable and be able to easily and flexibly integrate with many of open source windowing library out there. At the current stage, it works with GLUT, FreeGlut, and GLFW. Anyhow, the code above should be independent of any libraries we decide to use as it's one of cores to game application.
In code
I will base the precision and granularity from clock() function. It returns ticks, and we need to convert it back to seconds, and millisecond as if we need to. In the process, we need at least 3 clocks to make fixed/non-fixed mode happen.
As well, I already mentioned that this inspired me much that let me keep what I'm doing here. I added a flag to indicate whether the game is running slowly as well as the amount of dropped frame for performance monitoring purpose. If the game is running slowly, we will drop a call to render() and catch it up by calling update(). In fact, we could do it even better by setting a maximum amount of dropped frame to be accepted. So if it exceeds the limit, we can then take some responding actions or warn users.
Note the code section at "// fixed: major" as well. That's a piece that I missed it at the first go, so it produces unstable of rendering result.
A couple of places found in the code is a placeholder (function) for specifying callback function in the wrapper class or inherited class. So this function is as part of a core class.









