Advertisement

managing game time on a real-time game server

Started by February 19, 2004 11:04 AM
3 comments, last by TekBoy 20 years, 11 months ago
Hello, in my game server for a game which is real-time based (not turn based) I must somehow keep track of the game time. I could simply have an integer variable which is incremented by a timer event which triggers every few milliseconds, i.e. make my game turn-based, where every turn is a few milliseconds long. However, this would cause a lot of wasted CPU time when the server is idle. This is not desirable, since I must share the game server with other people. For this reason, I would prefer some asychronous system, which only uses up CPU time when some client actually connects to the game server and performs some action. But this raises the problem of how my game server should calculate game time. I could simply use the system clock to calculate the current game time. But this system clock is not linear, because it resychronizes itself with a time server every few days. Therefore, my game would go nuts when the system clock suddenly goes back a few seconds and therefore game time is suddenly less than it was before. Another option would be not to use the system clock, but instead use the CPU's internal time, which is not influenced by a resynchronization of the system clock. For example, the Win32 API function GetTickCount returns the number of milliseconds passed since the last reboot. However, this function returns this value as a 32-bit DWORD value. This means that it "wraps" every 50 days. This raises the problem that if nobody connects to my game server for several months, my game server cannot tell from the return value of GetTickCount exacltly how many months have passed. I could of course try to use the system clock to determine how many times GetTickCount() wrapped, but is there no easier solution to this simple problem? I'd appreciate any advice you may have in this matter. Thanks. [edited by - TekBoy on February 19, 2004 12:15:49 PM]
All clocks are inexact, and subject to warping. GetTickCount() is very inaccurate (it''s updated 10-50 times a second by an interrupt, no more). timeGetTime() will slip backwards under high bus load. QueryPerformanceCounter() will jump forward under high bus load. RDTSC will vary in speed depending on power management.

Use system time, and deal with the fact that it warps sometimes. You can deal by running the game half speed for 4 seconds if it warps 2 seconds, for example.

enum Bool { True, False, FileNotFound };
Advertisement
Thanks for your reply.

I do not mind if the clocks are inaccurate, as long as they always are greater than or equal to a previous call. The only thing my game can''t handle is if the time jumps backwards, for example when the system clock resynchronizes itself with a time server. Is this what you mean by "warping"?

Yes, that''s what I mean by "warp".

You can very easily create a clock class which always advances. Here''s a sketch:

class Clock {public:  Clock() : lastTime_(0), offset_(0) {}  double currentTime() {    struct timeval tv;    gettimeofday(&tv);    double now = tv.tv_sec + 1.0e-6 * tv.tv_usec + offset_;    if( now < lastTime_ ) {      // warp detected!      offset_ += lastTime_ = now;      now = lastTime_;    }    lastTime_ = now;    return now;  }private:  double lastTime_, offset_;}; 


This class will never go backwards (although it may stand still) and uses UNIX gettimeofday() as its underlying timer. It is NOT thread safe -- if you call it once per round/simulation then adding a lock is no problem; if you call it very often, you don''t want to pay for locking, so you should use one clock per thread. Or just don''t use threading.
enum Bool { True, False, FileNotFound };
Thank you very much for your help! I have now implemented a gametime clock similar to your suggestion.

This topic is closed to new replies.

Advertisement