Random, Non-Game-Pausing Background Animations? [SOLVED]

Started by Play_Pretend, Sun 30/09/2007 14:19:20

Previous topic - Next topic

Play_Pretend

Heyo all!  I'm trying to use a three-frame background animation to show lightning striking outside a window at random intervals.  (No lightning, one bolt, two bolts, basically.)  But instead of using the constant speed of AGS's background animation, is there any way to set it so every few random number of seconds, it'll show a randomly chosen combination of one or both lightning screens?  (i.e. One bolt, nothing, five seconds later, two bolts, one bolt, nothing, 10 second later, two bolts, nothing, so on.)

I tried using SetBackgroundFrame and Wait commands in the room's Repeatedly Execute code, but of course this just paused my game in between waiting for each new animation.  Is there a way to make it happen so the game will continue on while the randomly timed, randomly chosen background animations continue?  Or even if it's not random at all, but goes through a series of different wait times before the next animation?  Thanks!

Ashen

#1
Use Timers or variables in place of the Wait command. If the code you're using works, other than being blocking, it shouldn't be too much work to substitute one of those in instead.
I know what you're thinking ... Don't think that.

Play_Pretend

Thanks for the reply!  I think I've almost got the code sorted out, I've made it so it randomly chooses between 5 and 10 seconds before it makes the lightning flash.  (I think.)

The only problem now is, I think it's cycling through the frames so fast it doesn't even show up, it just stays on the no-lightning screen.  Here's the code I have in First Time Player Enters Room, to establish the timers:

Quote
SetBackgroundFrame(0); //no lightning

SetTimer(1, 200);
SetTimer(2, 40);

And in the Repeatedly Execute section:

Quote
int when=Random(400); //time between lightning appearing, up to 10 seconds
int flash=Random(80);    //time lightning stays on screen before disappearing
int light=Random(1);      //2 different lightning bolt backgrounds

if (when < 200) { //Reset timer if less than 5 seconds between lightning appearing,
                            //I don't want a strobe effect.
  SetTimer(1, when);
}

if (IsTimerExpired(1) == 1) {

  if (light==0) {
    SetBackgroundFrame(1);
    SetBackgroundFrame(0);
    SetTimer(1, when);
  }
 
  else if (light==1) {
    SetBackgroundFrame(2);
    SetBackgroundFrame(0);
    SetTimer(1, when);
  } 



I know the time-between-lightning-appearing interval works, because if I insert a Wait command between the SetBackgroundFrame commands, the lightning appears.  I created the "flash" int to try to make Timer 2 go between the actual frames of the background, so sometimes it would pause longer before making the lightning disappear.  But when I tried this:

Quote
  else if (light==1) {
    SetBackgroundFrame(2);
        if (IsTimerExpired(2) == 1) {
        SetBackgroundFrame(0);
        SetTimer(2, flash);
        }
    SetTimer(1, when);
  }

Nothing happens.  I know that last code doesn't look right to me, but I'm not sure why.  How would I insert a second timer to make the lightning show up randomly 1-2 seconds before it disappears again?

I guess I could just script the lightning to appear at certain times in certain ways, since this is for a cutscene anyways.  Or I could just make the window it's showing out of into a character, and make a lightning-flash idle view so long it seems random.  But I'd really like to get this timer thing figured out, I need to know it anyways. :)

Also, with SetTimer, is the timer value the same as game loop time, where putting in 40 will equal one second? 

Thank you so much for your help!

Halgwet

Hey. I took a look at your code and fixed up a few things in repeatedly execute. You need to split up the checks for timer 1 and timer 2.

Code: ags

if (IsTimerExpired(1) == 1)  //Start lightning
{
  int light=Random(1);

  if (light==0) 
  {
    SetBackgroundFrame(1);
    SetTimer(2, Random(80));
  }
 
  else if (light==1) 
  {
    SetBackgroundFrame(2);
    SetTimer(2, Random(80));
  } 

}

if (IsTimerExpired(2) == 1) //Stop lightning
{
  SetBackgroundFrame(0);
  SetTimer(1, Random(200) + 200);
}


First if case: If the timer 1 is expired a lightning background frame is set and timer 2 is started with a random number between 0 and 80.

Second if case: If timer 2 is expired the background is changed back and timer 1 is once again started with a random number between 200 and 400. The process repeats.

You could do it with just one timer, but it's easier to see what's going on this way.

That should probably work.
*sigh*

Ashen

#4
Bah, beaten to it by Halgwet, but I'll post anyway:

I'll answer the last question first, because it's easiest. It's right there in the manual:
Quote
SetTimer (int timer_id, int timeout)

Starts timer TIMER_ID ticking - it will tick once every game loop (normally 40 times per second), until TIMEOUT loops, after which it will stop.


So yes, SetTimer(1, 40); will give a one second delay, assuming the game is running at the default 40 fps. More accurate would be to use GetGameSpeed(), e.g. SetTimer(1, 5*GetGameSpeed()) for a 5 second timer.)


Moving backwards in your questions:
Quote
I know that last code doesn't look right to me, but I'm not sure why.  How would I insert a second timer to make the lightning show up randomly 1-2 seconds before it disappears again?

You're checking if Timer 2 is expired inside the Timer 1 check - remember that IsTimerExpired only returns true for one loop, so Timer 2 would have to expire at the same time as Timer 1 for that code to work. And - since you set Timer 2 at the same time as Timer 1, but to run for a much shorter time - that ain't gonna happen. (That's a lot of 'time's in one sentence...) As Halgwet said, place the IsTimerExpired(2) condition outside of the Timer 1 check to get it working.

There's a few things I think could stand improving in you code, so here's my attempt.
Top of Room script:
Code: ags

int when;
int flash;
int light;
  // 'when' = delay between flashes; 'flash' = time flash stays on screen; 'light' = flash to show (background frame).


Player enter Room interaction (any one of them):
Code: ags

SetBackgroundFrame(0); // Stop lightning from animating until you want it to
when = 5*GetGameSpeed() + Random(5*GetGameSpeed()); // Random 5 - 10 second delay between flashes.

SetTimer (1, when); // Set first lightning delay.  


Repeatedly_execute:
Code: ags

if (IsTimerExpired(1)) {
  // Make lightning 'flash on'  
  light = 1 + Random(1); // Random lightning frame 1 or 2 shown.
  SetBackgroundFrame(light); // Show the random frame
  flash = 20 + Random(GetGameSpeed()); // Random .5 - 1.5 second delay before flash clears.
     // Gave a minimum of 0.5s to prevent 'strobing', and allow the lightning frame to be seen.
  SetTimer(2,  flash);
}

if (IsTimerExpired(2)) {
  //make lightning 'flash off'
  SetBackgroundFrame(0); // Back to no lightning frame
  when = 5*GetGameSpeed() + Random(5*GetGameSpeed()); // A new 5-10 second delay
  SetTimer(1, when);
}


Seems to work in my test, let me know how it turns out in the real thing... (If you use it - Halgwet's code is pretty solid, too.)
I know what you're thinking ... Don't think that.

Play_Pretend

Woohoo!  I get it now.  I *thought* that was what looked funny about my code, with the improperly nested second timer.

And I read through your cleaned-up, improved code, and I totally get that too, and I learned several things from it that solved other concerns I had (like making sure Random didn't go too low and cause a strobe).

Thank you both so much, consider my problem solved!  ;D

SMF spam blocked by CleanTalk