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.
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.
Try %d (for digit) rather than %s (for string) ?
Have you considered the computer clock?
Yeah, using %d should do it. Likewise, you could combine the StrFormat ()'s to make your code a bit smaller:
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.
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);
Ah, grooviness. Thanks, Strazer! Now to focus on the timing problem. *gets to work testing a few things out for 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.
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).
You should use GetGameSpeed() instead of 40 to be absolutely sure...
Here's what I ended up with after everyone's suggestion and it worked for me:
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.
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?
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").
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:
#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
Strange, works for me.
No, you're right, it's fine. Something else was the problem, and it's fixed now.
Anyway, thanks everyone! ^_^
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:
// main global script file
int second;
int minute;
int hour;
and in repeatedly execute i have that:
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
}
Move the code to repeatedly_execute_always and it will carry on through everything except dialog option chooosing
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
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:
// 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:
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--;
yeah! it works perfectly ;D
thanks!