[SOLVED] Coding a simple speech-based countdown timer

Started by RootBound, Fri 13/01/2023 15:39:53

Previous topic - Next topic

RootBound

Hi scripters,

I know there are modules for countdown timers out there, but I wanted to see if I could script my own based on the background speech of an invisible character rather than a GUI. It seemed simpler, but evidently is not.

The problem is this: I can't get the countdown to update - it will display the initial value of the min and sec variables but never change. I've read the "string formatting" and "string.format" sections of the manual several times, and my "repeatedly_execute_always" function is running other things like looping animations perfectly well.

I have tried reordering the lines of code several different ways, and changing the frequency of updates to the timer (for example, updating only every 3 seconds), as well as substituting "if" statements for "while" statements. Nothing changes. I feel like I must be missing something obvious but cannot figure out what it is.

Any help would be hugely appreciated. Relevant code is below (I haven't coded what to do at 0 yet because this problem has gotten in the way):

Code: ags

int min;
int sec;
String TimerText;

function room_Load()
{
  min = 2;
  sec = 60;
  TimerText = String.Format("%d : %d", min,  sec);
  SetGameSpeed(40);        //40 loops = 1 second
  SetTimer(1, 2400);       //2400 = 40*60 = 60 seconds
  SetTimer(2, 40);         // 40 = 1 second
}

function repeatedly_execute_always()
{
  if (IsTimerExpired(1))
  {
    min -=1;
    SetTimer(1,  2400);
  }
  if (IsTimerExpired(2))
  {
    sec -=1;
    cTimer.SayBackground(TimerText);
    SetTimer(2,  40);
  }
}

J. They/them. Here are my most recent games:

Matti

Well, TimerText never updates, because it's in room_load.

Just put TimerText = String.Format("%d : %d", min,  sec); in repeatedly_execute_always() before cTimer.SayBackground(TimerText);

Khris

Exactly, an assignment statement like
Code: ags
  variable = value;
does not magically extend into the future; when this line is executed, the current value on the right is written into memory and that's it.
If the value changes, you also need to run the statement again or the variable simply keeps its old value.

RootBound

Matti, thanks very much--I knew it must be something simple like that, and your fix worked perfectly.

And Khris, I appreciate the explanation--it's helpful to understand not just the structure of the code but what's going on "under the hood."

Thank you both for answering! Much gratitude.
J. They/them. Here are my most recent games:

Khris

Btw, you can slightly improve the code by 1) not using a minute variable 2) not hard-coding 40 FPS

Code: ags
int secs = 180; // 3 minutes

// room_Load
  SetTimer(1, GetGameSpeed()); // one second

// rep_ex_always
  if (IsTimerExpired(1)) {
    secs--;
    TimerText = String.Format("%d : %02d", secs / 60,  secs % 60); // force two digit seconds
    if (secs == 0) { ... }
    else SetTimer(1, GetGameSpeed()); // one second
  }

RootBound

Hey Khris, I didn't see this before now. Thanks for the simplified code! It's great to have more experienced people to help make me a better coder. Much appreciated.
J. They/them. Here are my most recent games:

SMF spam blocked by CleanTalk