Game Development Community

dev|Pro Game Development Curriculum

Pausing/Countdown Gui Clock

by Sebastien Bourgon · 12/26/2003 (9:42 am) · 17 comments

Since its easier to just copy & paste from here. setTime was changed so I included the "full" function. (It was a one liner previously)

The helper functions, setTime, setReverseTime, getReverseTime, pauseTime
and thier ConsoleMethod partners:
void GuiClockHud::setTime(F32 time)
{
   //These declarations were added to the original function
   mReversed = false;
   mTimePaused = false;
   // Set the current time in seconds.
   mTimeOffset = S32(time * 1000) - Platform::getVirtualMilliseconds();
}
void GuiClockHud::setReverseTime(F32 time)
{
   // Set the current time in seconds.
   mReversed = true;
   mTimePaused = false;
   mTimeOffset = S32(time * 1000) + Platform::getVirtualMilliseconds();
}

F32 GuiClockHud::getReverseTime()
{
   return F32(mTimeOffset - Platform::getVirtualMilliseconds()) / 1000;
}

void GuiClockHud::pauseTime(bool toggle)
{
   
   mTimePaused = toggle;
   if (mReversed)
   {
      if (!toggle)
         mTimeOffset = mTimeOffset + (S32(getReverseTime())+mPausedTime)*1000;
      else
         mPausedTime = S32(getReverseTime());
   }
   else
   {
      if (!toggle)
         mTimeOffset = mTimeOffset - (S32(getTime())-mPausedTime)*1000;
      else
         mPausedTime = S32(getTime());
   }
}

ConsoleMethod(GuiClockHud,pauseTime,void,3, 3,"(true/false) Pauses the current time")
{
   object->pauseTime(dAtof(argv[2]));
}

ConsoleMethod(GuiClockHud,setReverseTime, void, 3, 3,"(reverse count)Counts down from Time)")
{
   object->setReverseTime(dAtof(argv[2]));
}
ConsoleMethod(GuiClockHud,getReverseTime, F32, 2, 2,"()Returns current time in secs.")
{
   return object->getReverseTime();
}

Underneath S32 time = S32(getTime()); before S32 secs = time % 60;
Line 80 roughly
// Get Normal Time
   S32 time =  S32(getTime());
   // If reversed, get reverse time.
   if (mReversed)
      time = S32(getReverseTime());
   // If paused, get the paused time.
   if (mTimePaused)
      time = mPausedTime;

Line 50 roughly in GuiClockHud::GuiClockHud() block
mTimePaused = false;
   mTimeOffset = 0;
   mReversed = false;

Line 29 in class GuiClockHud
S32      mTimeOffset;
   bool     mTimePaused;
   S32      mPausedTime;
   bool     mReversed;

and

Line 40 in the public section of class GuiClockHud.
void setReverseTime(F32 newTime);
   F32  getReverseTime();
   void pauseTime(bool toggle);

How to use it:
Pretty simple I hope
setReverseTime(600); would get it counting down from 10 minutes.
pauseTime(true); would stop it from counting up or down. Just a static number
It unpauses if you set the time again, or if you call pauseTime(false);
Originally put in for my music player but I couldn't get the audio to pause quite as easily as the clock.

About the author

Former Indie Game Developer for Max Gaming Technologies. I then spent a couple years doing mobile work for Capcom Interactive Canada, the highlight being Mega Man II for iPhone. Now doing various mobile contract jobs (mostly iPhone)


#1
12/31/2003 (1:39 am)
Can you provide example how to use it (from script)
#2
12/31/2003 (5:44 am)
GuiClock.setReverseTime(600); Clock counts down from 10 minutes
GuiClock.getReverseTime(); Get current time

GuiClock.pauseTime(true); Pause Clock
GuiClock.pauseTime(false); Unpause Clock

GuiClock.setTime(600); Clock counts up from 10 minutes
GuiClock.getTime(); Get current time
#3
01/03/2004 (1:48 pm)
I have made some changes to Sebastien's code that will do the Tribes 2 countdown of milliseconds when there are only seconds left and also made it where once the countdown has reached zero it'll start counting up from one second. The changes are in bold.

void GuiClockHud::onRender(Point2I offset, const RectI &updateRect)
{
   // Background first
   if (mShowFill)
      dglDrawRectFill(updateRect, mFillColor);
   
   // Convert ms time into hours, minutes and seconds.
   //S32 time = S32(getTime());
   // Get Normal Time
   S32 time = S32(getTime());
   [b]S32 msecs = 0; F32 mtmp=0;[/b]
   // If reversed, get reverse time.
   if (mReversed)
   [b]{[/b]
      time = S32(getReverseTime());
	  [b]// Get the milliseconds  --Nathan M. (TRON)
	  mtmp = Platform::getVirtualMilliseconds();
	  msecs = S32( F32(mTimeOffset - mtmp) - (/**/ S32(F32(mTimeOffset - mtmp) / 1000) /**/ * 1000)) / 10;
   }[/b]
   // If paused, get the paused time.
   if (mTimePaused)
   {
      time = mPausedTime;
   }

   S32 secs = time % 60;
   S32 mins = (time % 3600) / 60;
   S32 hours = time / 3600;

   // Currently only displays min/sec
   char buf[256];

   [b]// Check to see if we only have seconds remaining
   if(hours == 0 & mins == 0 & mReversed) // If so let's pull a Tribes 2 secs and msec remaining countdown --Nathan M. (TRON)
      dSprintf(buf,sizeof(buf), "%02d.%02d",secs,msecs);
   else[/b]
      dSprintf(buf,sizeof(buf), "%02d:%02d",mins,secs);

   // Center the text
   offset.x += (mBounds.extent.x - mProfile->mFont->getStrWidth(buf)) / 2;
   offset.y += (mBounds.extent.y - mProfile->mFont->getHeight()) / 2;
   dglSetBitmapModulation(mTextColor);
   dglDrawText(mProfile->mFont, offset, buf);
   dglClearBitmapModulation();

   // Border last
   if (mShowFrame)
      dglDrawRect(updateRect, mFrameColor);


   [b]// Once countdown has reached complete zero start counting up from one second  --Nathan M. (TRON)
   if(!time & !(msecs / 10) & mReversed)
	   setTime(1);[/b]
}

There is currently one problem though, when you pause the clock the milliseconds will still countdown. I'll post an update of this comment later fixing that small problem. Enjoy! :)
#4
01/10/2004 (5:52 am)
I would like to display hundreds of seconds in Gui Clock.
I'm an artist and dont't know much programming - please help me.
#5
01/15/2004 (11:58 pm)
Ok, I found a solution!
Probably it no so well done, but it works.

//-----------------------------------------------------------------------------

void GuiClockHud::onRender(Point2I offset, const RectI &updateRect)
{
// Background first
if (mShowFill)
dglDrawRectFill(updateRect, mFillColor);

// Convert ms time into hours, minutes, seconds and hundreds of seconds.
// Get Normal Time
S32 time = S32(getTime());
// If reversed, get reverse time.
if (mReversed)
time = S32(getReverseTime());
// If paused, get the paused time.
if (mTimePaused)
time = mPausedTime;

S32 hundr = (time % 100);
S32 secs = (time % 6000) /100;
S32 mins = ((time % 36000) / 60) /100;
S32 hours = (time / 36000) / 100;

// Display time
char buf[256];
dSprintf(buf,sizeof(buf), "%02d:%02d:%02d",mins,secs,hundr);

// Center the text
offset.x += (mBounds.extent.x - mProfile->mFont->getStrWidth(buf)) / 2;
offset.y += (mBounds.extent.y - mProfile->mFont->getHeight()) / 2;
dglSetBitmapModulation(mTextColor);
dglDrawText(mProfile->mFont, offset, buf);
dglClearBitmapModulation();

// Border last
if (mShowFrame)
dglDrawRect(updateRect, mFrameColor);
}


//-----------------------------------------------------------------------------

void GuiClockHud::setTime(F32 time)
{
//These declarations were added to the original function
mReversed = false;
mTimePaused = false;
// Set the current time in hundreds of seconds.
mTimeOffset = S32(time * 10) - Platform::getVirtualMilliseconds();
}
void GuiClockHud::setReverseTime(F32 time)
{
// Set the current time in hundreds of seconds.
mReversed = true;
mTimePaused = false;
mTimeOffset = S32(time * 10) + Platform::getVirtualMilliseconds();
}

F32 GuiClockHud::getTime()
{
// Return elapsed time in hundreds of seconds.
return F32(mTimeOffset + Platform::getVirtualMilliseconds()) / 10;
}


F32 GuiClockHud::getReverseTime()
{
return F32(mTimeOffset - Platform::getVirtualMilliseconds()) / 10;
}

void GuiClockHud::pauseTime(bool toggle)
{

mTimePaused = toggle;
if (mReversed)
{
if (!toggle)
mTimeOffset = mTimeOffset + (S32(getReverseTime())+mPausedTime)*10;
else
mPausedTime = S32(getReverseTime());
}
else
{
if (!toggle)
mTimeOffset = mTimeOffset - (S32(getTime())-mPausedTime)*10;
else
mPausedTime = S32(getTime());
}
}

//-----------------------------------------------------------------------------
#6
07/01/2004 (2:34 pm)
Do you have an example script how I can use the setTime. I can't set the clock.
Please help.
#7
07/01/2004 (10:14 pm)
YourClockNameFromGui.SetTime(0)
YourClockNameFromGui.GetTime()

YourClockNameFromGui.SetReverseTime(600)
YourClockNameFromGui.GetReverseTime()

YourClockNameFromGui.PauseTime(true)
YourClockNameFromGui.PauseTime(false)
#8
07/02/2004 (2:19 pm)
Thanks a lot Mitja,

Maybe you can help me with the following?

I want a highscore list. When a player reached a top ten time, I want the game to asked for a name and then save the highscore list.
I hope hat you can give me some tips.
#9
08/11/2004 (5:33 am)
Kees, u can set up a gui script that will do what you want. Just store a temp variable and have each click on a letter (all depends on your design), add that character to that temp variable.

In my case I had a wheel controller only so I whipped up a gui for use with the wheel only. You turn the wheel it selects a letter, when one presses the gas, it would advance to the next letter and store the last one in a variable. It's actually a lot easier than one would expect :)
#10
10/02/2005 (7:29 pm)
I put it under the playguihud thing like this
new GuiClockHud(clock) {
Profile = "GuiDefaultProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "72 320";
Extent = "52 51";
MinExtent = "8 2";
Visible = "1";
showFill = "1";
showFrame = "1";
fillColor = "0 0 0 0.5";
frameColor = "0 1 0 1";
textColor = "0 1 0 1";
};
};
//--- OBJECT WRITE END ---
function clock::onWake(%this){
%this.SetReverseTime(6000*2);
}

but the only way to set the time was to do the onwake thing. 6000 is 1 minute apperently.
#11
11/03/2005 (8:11 am)
I've got the countdown working all ok... but how would I make it so that when the time hits 0 the game will jump to a different screen??

i.e. unlucky try again screen
#12
05/13/2006 (9:13 pm)
I just got this to run a function when it hits zero, quite simple.

at the end of

void GuiClockHud::onRender(Point2I offset, const RectI &updateRect)

add
if(!time & !(msecs / 10) & mReversed & !mTimePaused){
	   pauseTime(1);
	   Con::executef(1,"onZeroReached");
   }
if you have the count up once reached zero code in this will go in on top of that. then you make a function somewhere called onZeroReached.
#13
08/09/2006 (8:23 am)
AWESOME stuff! :) Went in very easily to 1.4 .. the only heads up I can give is that you *need* to use the syntax pointed out by Mitja to set the clock in your GUI script ... on my first attempt, I tried to use the GUI script's onwake and set it with clock.setReverseTime ... didn't seem to work that way, so ... use Mitja's little func...

//--- OBJECT WRITE END ---
function clock::onWake(%this){
%this.SetReverseTime(6000*2);
}

I also added Master Treb's code to void GuiClockHud ...

It works like a charm!

Thanks, guys!
#14
07/28/2008 (5:49 am)
sorry to open up this thread again, but is this clocked synced on the server or only client side?
#15
03/19/2009 (11:31 am)
A small bug fix-

This line:
mTimeOffset = mTimeOffset + (S32(getReverseTime())+mPausedTime)*1000;

Should be changed to:
mTimeOffset = mTimeOffset - (S32(getReverseTime())-mPausedTime)*1000;
#16
11/14/2009 (10:41 am)
Where do I paste the code from Sebastien and Mitja. Do I create a new .cs file and paste their code in it. Does it go in game.cs? I just want to know where to put it.


#17
04/17/2011 (4:52 am)
Where do I put this code in Torque 3D? Can it be used?