RPGDXThe center of Indie-RPG gaming
Not logged in. [log in] [register]
 
 
Post new topic Reply to topic  
View previous topic - View next topic  
Author Message
RuneLancer
Mage


Joined: 17 Jun 2005
Posts: 441

PostPosted: Wed Feb 15, 2006 1:11 am    Post subject: In-game timer [quote]

I've been working on something for a friend who needed a timer with alterable speeds for his tabletop RP games. Works like a charm.

I figure I'll recycle the code in Endless Saga and use it to make an in-game timer à-la status screen timer. And though I'm not an advocate of open-source (not by a bloody long shot!! :) ) I thought I'd share my technique with aspiring young developers eager to do the same.

First, you need to declare a few values.

Code:
int currentH = 0;              // The current hour.
int currentM = 0;              // The current minute.
int currentS = 0;              // The current second.
int lastTick = GetTickCount(); // Used to sync time properly.
int timeUnit = 1000;           // This basically affects the number of milliseconds in a second;
                               // make a constant out of this unless you plan on varying the timer's speed.

What we're going to do is update our timer every "second." A "second" is defined by timeUnit, which in this example is 1000ms. You can make time travel twice as fast by making this 500, twice as slow by making it 2000, so forth. Like the comment says, you should make a constant out of this, not a variable, unless you plan on making it vary in-game. It's cleaner that way. ;)

What "lastTick" does is keep track of when the time was last updated. However, we're not going to use getTickCount anymore to maintain this because there's a slight delay in processing things and you'll get slightly skewed results that may cause it to skip a second every few minute or so. Instead, we're going to assume the time really is being updated exactly every timeUnit millisecond even though we know it won't be handled as such until a few milliseconds later.

Every loop through your game loop, the timer should be checked for update.

Code:
if((GetTickCount() - lastTick) >= timeUnit)
{


We check if AT LEAST timeUnit milliseconds have elapsed. I put emphasis on "at least" because we can be sure getTickCount's resolution and other bits of overhead will screw up our timing.

Code:
         lastTick += timeUnit;


Now we update our lastTick tracking variable. This is I meant earlier about not using GetTickCount to manage this. Our timer will always be precise even though it might take, say, 1015ms to handle the timer. If we used GetTickCount, this extra overhead would factor into our timer and make it totally inaccurate.

Note that this solution assumes you can update the timer at least once a second; if your game loop takes more than a second to complete, your timer will run behind somewhat. You can remedy this situation easily enough with a while() loop but I'm going to assume you won't consider releasing a game that runs at less than 1 FPS. ;)

Code:
         currentS++;
         if(currentS == 60) { currentM++; currentS = 0; }
         if(currentM == 60) { currentH++; currentM = 0; }
         if(currentH == 24)          currentH = 0;
}


Finally, we update the timer itself. Every 60 seconds, we reset the seconds counter and increment the minutes. Every 60 minutes, we reset the minutes counter and increment the hours. And ever 24 hours, well, we start over at 0.

This last bit is terribly easy to alter. Want to add days? No problem, just add an extra variable (currentD?) You could easily count the number of millenia with this, if you wanted to. Need shorter days? No problem there either, just make it reset earlier! Want the day to begin at 8 am and end at 22 pm? Reset hours to 8 when they hit 22.

All's you need to do now is display or use it somehow in your code. For my friend's app, I made it simply send a WM_SETTEXT message to a label after building a string out of it. For a game, the hours could map out to the illumination intensity on your map (something like 12 - abs(12 - currentH)...)
_________________
Endless Saga
An OpenGL RPG in the making. Now with new hosting!



Last edited by RuneLancer on Wed Feb 15, 2006 6:09 am; edited 1 time in total
Back to top  
zenogais
Slightly Deformed Faerie Princess


Joined: 10 Jan 2006
Posts: 34

PostPosted: Wed Feb 15, 2006 1:18 am    Post subject: [quote]

Nice technique, I think I'm going to use it :). Just wanted to add that there is a much more accurate timer in the win32 SDK called timeGetTime(). I'm not sure if you're aware of it, seems like you are from the post, but GetTickCount is fairly inaccurate. It is supposed to have a 1ms resolution, but I've personally done some tests (checking CPU speed using timers), and GetTickCount gave some awful results (though strangely not as bad as QueryPerformanceCounter), while timeGetTime was highly accurate. timeGetTime is pretty much the de facto standard anymore I though, although you would need to link with winmm.lib. Anyway, just a thought I had once I saw you were using GetTickCount.
Back to top  
RuneLancer
Mage


Joined: 17 Jun 2005
Posts: 441

PostPosted: Wed Feb 15, 2006 1:48 am    Post subject: [quote]

Yeah, you're free to use anything you want, really. :P I'm using GetTickCount as a bad habit from my earlier programming days, though a game would be better off with something more accurate. I wrote this for a simple Win32 app, really. ;)

QPC, IIRC, is a very accurate timer but returns a nearly useless value (the number of cycles elapsed; kinda hard to map out to a second with any precision.) I can't say I've ever seen anyone use it but I'm pretty sure it would be wonderful for synchronizing things together accurately. :o
_________________
Endless Saga
An OpenGL RPG in the making. Now with new hosting!

Back to top  
Adam
Mage


Joined: 30 Dec 2002
Posts: 416
Location: Australia

PostPosted: Wed Feb 15, 2006 4:28 am    Post subject: [quote]

Perhaps i'm wrong but I don't really think you need a better accuracy than 1ms in a game that runs at 60fps.
_________________
https://numbatlogic.com
Back to top  
RuneLancer
Mage


Joined: 17 Jun 2005
Posts: 441

PostPosted: Wed Feb 15, 2006 4:44 am    Post subject: [quote]

Adam wrote:
Perhaps i'm wrong but I don't really think you need a better accuracy than 1ms in a game that runs at 60fps.

Naw. The only part you're wrong about is the 60 fps one (the game I intend to use this in is hardly a simple 2D SDL RPG ;P 60 fps would be considered pretty bad performance, right now.).

Admittedly, it's easy to become obsessed with precision. But I don't think a player will notice even a 50ms inaccuracy unless it's to sync up stuff in the game.
_________________
Endless Saga
An OpenGL RPG in the making. Now with new hosting!

Back to top  
zenogais
Slightly Deformed Faerie Princess


Joined: 10 Jan 2006
Posts: 34

PostPosted: Wed Feb 15, 2006 4:55 am    Post subject: [quote]

I actually wrote a timer using QPC which you can find here. You sort of have to establish a baseline before you can use it.

Adam: Certainly there's no reason to haggle over extra accuracy, but if it's trivial to gain the extra accuracy I don't see why you shouldn't.
Back to top  
tunginobi
Wandering Minstrel


Joined: 13 Dec 2005
Posts: 91

PostPosted: Wed Feb 15, 2006 6:48 am    Post subject: [quote]

The accuracy only comes into play if you expect the player to play for hours on end... and even then, a few discrepant seconds aren't going to trigger any heart attacks.

Or if your clock is really wonky.
Back to top  
Post new topic Reply to topic Page 1 of 1 All times are GMT
 



Display posts from previous:   
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum