DWORD UTimer::Run(LPVOID)
{
while(m_bIsRunning)
{
m_TimeEnd = timeGetTime() - m_TimeStart;
m_Time += m_TimeEnd - m_TimeStart;
m_TempInterval += m_TimeEnd - m_TimeStart;
m_TimeStart = m_TimeEnd;
if(m_TempInterval >= interval)
{
m_TempInterval = 0;
timer_func(m_pData);
}
m_TimeLeft = interval - m_TempInterval;
Sleep(20);
}
return GetLastError();
}
🔒 Locked
Timers
Advertisement
Original Post
Hi gamedev, I haven't been around in a while and I am getting motivated to pick up my old game and start working on it again. I haven't worked on it in about 6 months and I am very condfused about what I am doing. It is programmed in c++, win32, gdi. I have a Timer class that uses a thread and every interval it calls a function that I give it. It seems like it calls the function ok but I want to know how many milliseconds or seconds are left until it calls the function. I added the line m_TimeLeft = interval - m_TempInterval; above the sleep function in order to accomplish this but it gives my unexpected results. The m_TempInterval variables sometimes comes up with negative numbers that throws the calculation off by a ton. I am thinking it has something to do with the timeGetTime() or something. Anyway sometimes it works and comes out with the correct number and it seems to have the timing down perfect, but the m_TimeLeft variable comes up with what I don't want. Has anyone else tried this? Any help would greatly be appreciated. Thanks.
It probably is more effort than it is. What I am trying to do is to have an effect in my game sort of like a power up that lasts for so long. On the screen it will have a display saying how many seconds are left on the power up. I am not sure how to achieve this as I don't know all what I really need to do. I just took the idea behind a Timer object in VB and said why don't I give that a try. I guess I could just put the time code in the main loop. Then do that QueryPerformaceCounter thing.
Here's how I implemented timers.
Now, to implement powerups, you create a powerup class with a member variable for the seconds it lasts. This powerup will also have a timer as a member variable; when a powerup is picked up, reset the timer, get the elapsed time in seconds, and either 1)subtract the elapsed seconds from the time remaining or 2) when the elapsed time modulus 1 is 0 (to be accurate, probably elapsed time modulus 1 equaling between, say, 0.990 and 1.001 [only example]) subtract 1 from the time remaining.
Note that this is a rough throw-together for a small game, and there could be many member functions added to make it more usable. I also realize that creating a timer for each powerup is probably a terribly inefficient design; it would probably be better to add a member function in the timer to get current time that could be recorded as a member variable in the powerup class and add to that the amount of time the powerup lasts to determine endtime, and keep a single timer as a static to be shared amongst all the powerup classes.
Hope that helps,
Aviosity
PS - this is based off of some code in an article on gamedev(I believe)...if I find it I'll post a link.
//HEADER FILEclass Win32Timer {private: __int64 startTime; //Time that timer started at __int64 rate; //Frequency clock operates at GLdouble rateInverse; //Calculate the rate inverse for speed, to multiply instead of divide public: Win32Timer (GLvoid); GLint initTimer (GLvoid); GLint resetTimer (GLvoid); GLdouble getElapsedTimeSeconds (GLvoid);};//_______________________________//CPP FILEWin32Timer::Win32Timer (GLvoid){ initTimer();}GLint Win32Timer::initTimer (GLvoid){ if(!QueryPerformanceFrequency((LARGE_INTEGER*) &rate)) return -1; if(!rate) return -1; rateInverse = (GLdouble)(1.0/(GLdouble)rate); if(!QueryPerformanceCounter((LARGE_INTEGER*)&startTime)) return -1; return 1;}GLint Win32Timer::resetTimer (GLvoid){ if(!initTimer()) return -1; else return 1;}GLdouble Win32Timer::getElapsedTimeSeconds (GLvoid){ __int64 endTime; GLdouble retval; QueryPerformanceCounter((LARGE_INTEGER*) &endTime); retval = (GLdouble)((GLdouble)(endTime - startTime)*rateInverse); return retval;}Now, to implement powerups, you create a powerup class with a member variable for the seconds it lasts. This powerup will also have a timer as a member variable; when a powerup is picked up, reset the timer, get the elapsed time in seconds, and either 1)subtract the elapsed seconds from the time remaining or 2) when the elapsed time modulus 1 is 0 (to be accurate, probably elapsed time modulus 1 equaling between, say, 0.990 and 1.001 [only example]) subtract 1 from the time remaining.
Note that this is a rough throw-together for a small game, and there could be many member functions added to make it more usable. I also realize that creating a timer for each powerup is probably a terribly inefficient design; it would probably be better to add a member function in the timer to get current time that could be recorded as a member variable in the powerup class and add to that the amount of time the powerup lasts to determine endtime, and keep a single timer as a static to be shared amongst all the powerup classes.
Hope that helps,
Aviosity
PS - this is based off of some code in an article on gamedev(I believe)...if I find it I'll post a link.
Here are a few things to consider.
- By default, the time returned by timeGetTime() is not updated every millisecond. On my system it updates only every 16 or 17 milliseconds. If that is a problem, use QPC (as demonstrated by aviosity).
- Sleep( x ) waits for at least x milliseconds, so your intervals will be close to 20 ms but usually longer.
- It looks like some of the logic is broken.
DWORD UTimer::Run(LPVOID) { while(m_bIsRunning) { m_Time = timeGetTime(); while ( int( m_Time - m_TimeStart ) >= interval ) { timer_func(m_pData); m_TimeStart += interval; } m_TimeLeft = interval - ( m_Time - m_TimeStart ); Sleep(20); } return GetLastError(); }
I have always wondered if using Sleep is worth it... I used Sleep(0) because passing 0 means that the thread is giving up it's remaining CPU time whereas passing a number other than 0 will do above plus wait for that amount of time but it is interesting to note that I once passed Sleep(1) in an empty game loop thinking it would wait around 1-2ms however, I noticed the frame rate drop from 798fps right down to 58fps so I figured it must have been waiting a little longer than 1-2ms
I am considering dropping Sleep(0) from anything I ever create - I believe when your writing a game you want every available CPU cycle you can get you hands on.
I am considering dropping Sleep(0) from anything I ever create - I believe when your writing a game you want every available CPU cycle you can get you hands on.
Also, since your code is running in a separate thread, you need to use thread synchronization functions (mutexs, semaphores, etc.) to prevent one thread from accessing a value in the middle of being changed by another thread.
Quote:SwitchToThread is better than Sleep(0) since it's designed for that purpose. Also, most games do not need all the CPU, as long as they get a good share. A person running a top of the line system shouldn't be penalized for it - if all your game does is go from 200 frames per second to 1000, you really shouldn't be hogging the CPU since it's highly unlikely that the player has a display capable of displaying even 200 frames per second.
Original post by Adam Hamilton
[...]I am considering dropping Sleep(0) from anything I ever create - I believe when your writing a game you want every available CPU cycle you can get you hands on.
As far as the OP, why not use SetTimer (or timeSetEvent if you really care about precision) and let windows call your function every ~20ms instead of doing it yourself? At the very least, use CreateWaitableTimer to wait for the time to change.
You could always sacrifice fps for more physics calculations for example.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement