----------------------------------------------
I'm sure you often experienced the following problem : You are playing your favorite game when one of your friends calls you up and wants to chat. If your brain supports multi-tasking, you will be able to do both at a time without any performance loss. If not, you have to pause one of these tasks. For it might be hard to put your friend on "suspend" mode, we will try to pause the game. I don't have to go into detail any more, right ?
First, we somehow need to find out when to pause the application. The easiest way to do this, is to find out whether the window is the active one or not. Next thing to do is .... nothing ! Right! We have to stop rendering frames to the screen. When the user wants to continue playing, he or she re-actives the window and the application should continue rendering. Sounds easy, right ?
Well, there is one thing missing : every timer in the game will continue counting in pause mode. As mentioned in part 1 of this tutorial, the Irrlicht timer retrieves the number of milliseconds that have elapsed since the system was started. Of course, this is independent from whether the game is paused or not. So, if you pause the game and continue playing ten minutes later, the "in-game-time" will advance the full ten minutes. Thus, we need to measure the time we spent in "suspend mode" and subtract it from any future time measurement.
Let's start with the game loop :
Code: Select all
int main()
{
...
bool wasActive = true;
while (g_pDevice->run())
{
if (!g_pDevice->isWindowActive())
{
if (wasActive)
{
g_pTimer->Pause();
wasActive = false;
}
Sleep(100);
continue;
}
if (!wasActive)
{
g_pTimer->UnPause();
wasActive = true;
}
...
render
...
}
}
The bool wasActive keeps track of the state of the application. If the old state was active and the new one is inactive pause the game and vice versa. For the case that the game is inactive, we force the thread to sleep for some time and test again for activity. Keep in mind, that the rendering code is NOT executed. The sleeping time ( and thus the latency ) is comparativly high, because we want to gain as much CPU power as possible. A max. latency of 1/10 of a second when returning to the game does not matter really...
That's it ! Now we solely need to implement the Pause() and UnPause() functions in the CTimer class. As mentioned earlier we need to keep track of the time that passes while the game is paused. Thus, we add a member m_TotalPause to store the total amount of paused time and m_DeltaPause to keep track of the time passed since Pause(..) was called last.
Code: Select all
void Pause()
{
m_DeltaPause = g_pDevice->getTimer()->getTime();
}
void UnPause()
{
m_TotalPause += g_pDevice->getTimer()->getTime() - m_DeltaPause;
m_DeltaPause = 0;
}
With some small modifications to CalcDeltaTime() the m_Time member will be the same before and after pausing. A nice side effect is that m_Time is the time the window is active. So to speak m_Time gives the time the user has been playing your game.
Code: Select all
void CalcDeltaTime()
{
u32 old_time = m_Time;
m_Time = g_pDevice->getTimer()->getTime() - m_TotalPause;
m_DeltaTime = m_Time - old_time;
m_TimeFactor = m_DeltaTime * 0.001f;
}
http://eve-corp.com/Raptor/zip/timer.zip