Creating a permanent game timer - SOLVED

Started by Kinoko, Wed 28/07/2004 15:34:10

Previous topic - Next topic

Kinoko

I'm trying to make a variable that will show the elapsed playing time in my game. I've made it into a GUI on screen for now just so I can see it's working. It isn't right now, and I'm a bit stumped. I know I'm doing something(s) wrong but I don't know what to change.

Code: ags

if (GetGlobalInt(4)==1) {
Ã,  SetTimer(1, 2400);
Ã,  }

if (IsTimerExpired(1)==1) {
Ã,  second+=1;
Ã,  SetTimer(1, 2400);
Ã,  }

if (second==60) {
Ã,  second=0;
Ã,  minute+=1;
Ã,  }
if (minute==60) {
Ã,  minute=0;
Ã,  hour+=1;
Ã,  }

StrFormat (timehour, "%s", hour);
StrFormat (timeminute, "%s", minute);
StrCopy (time, timehour);
StrCat (time, ":");
StrCat (time, timeminute);

SetLabelText (12, 0, time);


The label itself works, and when the timer is trigger in the game, it goes blank, and a few seconds later, reads as, "(NULL):(NULL)"... so, the format is working but the timer isn't.

I've tried putting the SetLabel line in repeatedly execute and various other things that produce the same result.

Radiant

Try %d (for digit) rather than %s (for string) ?

Moox

Have you considered the computer clock?

Jet Kobayashi Zala

#3
Yeah, using %d should do it. Likewise, you could combine the StrFormat ()'s to make your code a bit smaller:

Code: ags


StrFormat ( time, "%2d:%2d", hour, minute ); // Should give you 00:00 to start with



I'm not sure if the %2d is carried over from C, but if so, that'll save you a bit of code.

Edit:
I tried it out and the %2d doesn't work in AGS, though it might be a good feature to add in at a later version.Ã,  Regardless, that should speed your code up a little bit. As for the timer problem, I'll look into it more and see if I can help.

strazer

#4
QuoteI tried it out and the %2d doesn't work in AGS

Quote from: Scorpiorus
DisplaySpeech(JACK, "The new code is %04d", GetGlobalInt(99));
(...) will add leading zeros (up to 4) if necessary.

Try
  StrFormat (time, "%02d:%02d", hour, minute);

Jet Kobayashi Zala

#5
Ah, grooviness. Thanks, Strazer! Now to focus on the timing problem. *gets to work testing a few things out for Kinoko*

Kinoko

Thanks everyone. That cleans the code up a bit (I thought I had to convert the hour and minute ints into strings for some reason...).

The timer now displays as 00:00 but doesn't go past that.

Gilbert

I think the GlobalInt(4) is a bit suspicious, if that part of code you posted was in repeatedly execute and that GlobalInt(4) was indeeed set to 1, the timer will be restarted EVERY gameloop. So, to prevent this, try:

if (GetGlobalInt(4)==1) {
  SetTimer(1, 2400);
  SetGlobalInt(4,0);
  }

Also, try changing all those 2400 to 40. Under normal cases, 40 gameloops make 1 second (unless you changed it), so 2400 gameloops would be 60 seconds already (unless you really need to wait that long for second to advance by 1).

Kweepa

You should use GetGameSpeed() instead of 40 to be absolutely sure...
Still waiting for Purity of the Surf II

Jet Kobayashi Zala

Here's what I ended up with after everyone's suggestion and it worked for me:

Code: ags

in repeatedly_execute:

if ( GetGlobalInt (4) == 1 ) {Ã,  Ã,  Ã,  Ã,  Ã,  // Make sure timer is supposed to be running
Ã,  SetGlobalInt (4, 0);Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // Disable it so this doesn't keep getting called
Ã,  SetTimer (1, GetGameSpeed());Ã,  // Start the timer based on the game's speed so that time is measured correctly
}

if ( IsTimerExpired(1) ) {Ã,  // Once the timer has expired (one second)
Ã,  second++;Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // Increment seconds
Ã,  if ( second == 60 ) {Ã,  Ã,  Ã,  // Increment minutes and reset seconds if needed
Ã,  Ã,  second = 0;
Ã,  Ã,  minute++;
Ã,  }
Ã,  if ( minute == 60 ) {Ã,  Ã,  Ã,  // Increment hours and reset minutes if needed
Ã,  Ã,  minute = 0;
Ã,  Ã,  hour++;
Ã,  }
Ã,  SetGlobalInt (4, 1);Ã,  Ã,  Ã,  // Restart the timer
}

StrFormat (time, "%02d:%02d:%02d", hour, minute, second); // Format it!

SetLabelText (STATUSLINE, 0, time); // Print it!


And that worked fine for me Kinoko. Hope that helps you too.

Kinoko

Gil: Oops, the 2400 was supposed to calculate a minute, not a second. Again, put tht down to my brain being fried at the time.

Jet: Works beautifully, thanks! ^_^

So the timer works just the way I was after, except that I don't need it printed, I just need the game keeping track of the time variable internally so I'll get rid of that line. A new problem is that the game is keeping track of time constantly and now I can't move my character (keyboard controlled movement based around code contained in repeatedly_execute as well).

Should I put the time code into repeatedly_execute_always or something?

Gilbert

Quote from: Kinoko on Thu 29/07/2004 07:41:57
A new problem is that the game is keeping track of time constantly and now I can't move my character (keyboard controlled movement based around code contained in repeatedly_execute as well).
Why not? you can always do more than one thing in a function, eg.

function repeatedly_execute() {
  //stuff1 bla bla bla
  //stuff2 blah bla
}

Quote
Should I put the time code into repeatedly_execute_always or something?
It wouldn't make "much" difference according to how that code was scripted, except that putting it in "always" may make it a bit more accurate (for example, if the timer expires when a blocking script is being executed, second wouldn't advance until the script was finished if you didn't put it in "always").

Kinoko

I don't know why it isn't working. Idle animation still works, other key functions that bring up GUIs and so forth still work, but not the character movement. Here's my entire repeatedly_execute script, just in case you can see anything obvious:

Code: ags

#sectionstart repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE
function repeatedly_execute() 
  {

//////////////////////////////////TIME////////////////
if ( GetGlobalInt (4) == 1 ) {          // Make sure timer is supposed to be running
  SetGlobalInt (4, 0);                     // Disable it so this doesn't keep getting called
  SetTimer (1, GetGameSpeed());  // Start the timer based on the game's speed so that time is measured correctly
}

if ( IsTimerExpired(1) ) {  // Once the timer has expired (one second)
  second++;                     // Increment seconds
  if ( second == 60 ) {      // Increment minutes and reset seconds if needed
    second = 0;
    minute++;
  }
  if ( minute == 60 ) {      // Increment hours and reset minutes if needed
    minute = 0;
    hour++;
  }
  SetGlobalInt (4, 1);      // Restart the timer
}

StrFormat (time, "%02d:%02d:%02d", hour, minute, second); // Format it!

//SetLabelText (12, 0, time); // Print it!

//////////////////////////////////////////////////////

if (IsGamePaused()==0) {
	// --- keyboard control ---
	int CharId, Direction, dx, dy;
	// neue Richtung ermitteln
	if ((IsKeyPressed (371) > 0) || (IsKeyPressed (55) > 0) || ((IsKeyPressed (372) > 0) && (IsKeyPressed (375) > 0))) Direction = DIR_UP_LEFT;
	else if ((IsKeyPressed (373) > 0) || (IsKeyPressed (57) > 0) || ((IsKeyPressed (372) > 0) && (IsKeyPressed (377) > 0))) Direction = DIR_UP_RIGHT; 
	else if ((IsKeyPressed (379) > 0) || (IsKeyPressed (49) > 0) || ((IsKeyPressed (380) > 0) && (IsKeyPressed (375) > 0))) Direction = DIR_DOWN_LEFT;
	else if ((IsKeyPressed (381) > 0) || (IsKeyPressed (51) > 0) || ((IsKeyPressed (380) > 0) && (IsKeyPressed (377) > 0))) Direction =DIR_DOWN_RIGHT;
	else if ((IsKeyPressed (372) > 0) || (IsKeyPressed (56) > 0)) Direction = DIR_UP; 
	else if ((IsKeyPressed (375) > 0) || (IsKeyPressed (52) > 0)) Direction = DIR_LEFT; 
	else if ((IsKeyPressed (376) > 0) || (IsKeyPressed (53) > 0)) Direction = DIR_STOP; 
	else if ((IsKeyPressed (377) > 0) || (IsKeyPressed (54) > 0)) Direction = DIR_RIGHT; 
	else if ((IsKeyPressed (380) > 0) || (IsKeyPressed (50) > 0)) Direction = DIR_DOWN; 
	else Direction = DIR_STOP;
	
	if (IsKeyPressed(65)==1) { //RUNNING - 'A' button held down
	
	   if (isRunning==0) {
	      StopMoving(GetPlayerCharacter());
	      SetCharacterSpeed(GetPlayerCharacter(), 12);
	      isRunning = 1;
	      Direction = DIR_STOP;
	   }
	
	} else {
	
	   if (isRunning==1) {
	      StopMoving(GetPlayerCharacter());
	      SetCharacterSpeed(GetPlayerCharacter(), 7);
	      isRunning = 0;
	      Direction = DIR_STOP;
	   }
	}
	
	// Vergleich mit aktueller Richtung
	if (PrevDirection != Direction)
	{
	PrevDirection = Direction;
	CharId = GetPlayerCharacter ();
	if (Direction == DIR_STOP) { StopMoving (CharId); } // 5 Stop (numeric pad)
	else
	{
	if (Direction == DIR_UP_LEFT) { dx = -DIR_DISTANCE; dy = -DIR_DISTANCE; } // 7 Home (numeric pad)
	else if (Direction == DIR_UP) { dx = 0; dy = -DIR_DISTANCE; } // 8 Up arrow
	else if (Direction == DIR_UP_RIGHT) { dx = DIR_DISTANCE; dy = -DIR_DISTANCE; } // 9 PgUp (numeric pad)
	else if (Direction == DIR_LEFT) { dx = -DIR_DISTANCE; dy = 0; } // 4 Left arrow
	else if (Direction == DIR_RIGHT) { dx = DIR_DISTANCE; dy = 0; } // 6 Right arrow
	else if (Direction == DIR_DOWN_LEFT) { dx = -DIR_DISTANCE; dy = DIR_DISTANCE; } // 1 End (numeric pad)
	else if (Direction == DIR_DOWN) { dx = 0; dy = DIR_DISTANCE; } // 2 Down arrow
	else if (Direction == DIR_DOWN_RIGHT) { dx = DIR_DISTANCE; dy = DIR_DISTANCE; } // 3 PgDn (numeric pad)
	MoveCharacterStraight (CharId, character [CharId].x + dx, character [CharId].y + dy);
	}
	}
}	   
}

#sectionend repeatedly_execute  // DO NOT EDIT OR REMOVE THIS LINE

Gilbert


Kinoko

No, you're right, it's fine. Something else was the problem, and it's fixed now.

Anyway, thanks everyone! ^_^

Mel_O_Die

#15
i reply here with a new question because i don't want to create a new topic about timers but i have a little problem with that code

it works fine (with some modifications for AGS 2.72 script) but this timer pauses automatically when character's speaking or player browses inventory

how can i do to get this timer works in these cases?

(but i want it paused when the game is "officially" paused like in menu or save/load windows

thanks!

PS: here's my code for 2.72
in top of global script i declare these variables:
Code: ags

// main global script file
int second;
int minute;
int hour;

and in repeatedly execute i have that:
Code: ags

function repeatedly_execute() {
//////////////////////////////////TIME////////////////
if ( GetGlobalInt (4) == 1 ) {Ã,  Ã,  Ã,  Ã,  Ã,  // Make sure timer is supposed to be running
Ã,  SetGlobalInt (4, 0);Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // Disable it so this doesn't keep getting called
Ã,  SetTimer (1, GetGameSpeed());Ã,  // Start the timer based on the game's speed so that time is measured correctly
}

if ( IsTimerExpired(1) ) {Ã,  // Once the timer has expired (one second)
Ã,  second++;Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // Increment seconds
Ã,  if ( second == 60 ) {Ã,  Ã,  Ã,  // Increment minutes and reset seconds if needed
Ã,  Ã,  second = 0;
Ã,  Ã,  minute++;
Ã,  }
Ã,  if ( minute == 60 ) {Ã,  Ã,  Ã,  // Increment hours and reset minutes if needed
Ã,  Ã,  minute = 0;
Ã,  Ã,  hour++;
}
Ã,  SetGlobalInt (4, 1);Ã,  Ã,  Ã,  // Restart the timer
Ã,  
}
Ã,  
counter.Text = String.Format("%02d:%02d:%02d", hour, minute, second); // "counter" is my label's name
}
----( )----
Click to see "In Production" Topic!
[/color][/b][/url]

SSH

Move the code to repeatedly_execute_always and it will carry on through everything except dialog option chooosing
12

Mel_O_Die

i've tried that but it doesn't works, nothing is written in the label

maybe i must change a thing in the code but i don't know what to do and where
----( )----
Click to see "In Production" Topic!
[/color][/b][/url]

Gilbert

That means, your inventory window is a popup modal which will pause the game.
I'm not sure, but I think timer won't decrement when a popup modal GUI's on.

You may either change the invertory GUI to other non-blocking mode, or, don't use the times, use a variable instead:

in top of global script i declare these variables:
Code: ags

// main global script file
int second;
int minute;
int hour;
int timecoutn=1; //set to 1 to guarantee it to work for the first time and the rest

and in repeatedly execute:
Code: ags

function repeatedly_execute() {
//////////////////////////////////TIME////////////////

timecoutn--;
if ( timecoutn==0 ) {Ã,  // Once the timer has expired (one second)
Ã,  second++;Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // Increment seconds
Ã,  if ( second == 60 ) {Ã,  Ã,  Ã,  // Increment minutes and reset seconds if needed
Ã,  Ã,  second = 0;
Ã,  Ã,  minute++;
Ã,  }
Ã,  if ( minute == 60 ) {Ã,  Ã,  Ã,  // Increment hours and reset minutes if needed
Ã,  Ã,  minute = 0;
Ã,  Ã,  hour++;
}
Ã,  timecoutn=GetGameSpeed();Ã,  Ã,  Ã,  // Restart the timer
Ã,  
}
Ã,  
counter.Text = String.Format("%02d:%02d:%02d", hour, minute, second); // "counter" is my label's name
}


If you don't want the time to count when some certain GUIs are on, just change the timecoutn--; line to something like:

if (!gSave.Visible||!gLoad.Visible) timecoutn--;

Mel_O_Die

----( )----
Click to see "In Production" Topic!
[/color][/b][/url]

SMF spam blocked by CleanTalk