Should I be using the Wait function or timers?

Started by MaximusDecimus, Mon 17/10/2011 05:29:19

Previous topic - Next topic

MaximusDecimus

I'm making a RPG battle simulation game (it has a battle system similar to Quest for Glory II). I've set the opponent to attack repeatedly using the repeatedly execute function in the global script. But, if I want the opponent to attack the player every X game loops, I have to either use timers or the Wait function. With timers, it's overly complicated and I can't get everything to work properly, but if I use the Wait function, it also freezes all other scritps!! It be so much simpler if AGS had a delay function or something: wait X game loops, then proceed to the next line while not pausing all the scripts.   :-\

Specifically, when the opponent starts an attack, the function needs to wait 4 game loops before playing the attack sound. Then, after 10 game loops, it has to play the hit sound and subtract some hit points, after 80 loops the opponent can attack again ... How to do these simple delays? Please help because I'm kind of stuck.  

Gilbert

Or, try the third option. Use a variable as your own timer/counter.

You set a variable to a certain value at the beginning and then decrement it every game loop. You can use if{}else{} statements to trap the variable and do whatever you want when the counter reaches a certain value. Something like:
First declare the variable on top of the room script:
Code: ags
int attcoutn;

When entering a room:
Code: ags
attcoutn=80;

Then in repeatedly_execute():
Code: ags

attcoutn--;
if (attcoutn==76){ //after 4 loops
  //play attack sound
} else if (attcoutn==66) {//10 more loops
  //play hit sound
  //subtract hit point
} else if (attcoutn==0){
  attcoutn=80;
}

MaximusDecimus

Thanks for the fast reply! I'll try it out.

Khris

Quote from: MaximusDecimus on Mon 17/10/2011 05:29:19With timers, it's overly complicated and I can't get everything to work properly, but if I use the Wait function, it also freezes all other scritps!! It be so much simpler if AGS had a delay function or something: wait X game loops, then proceed to the next line while not pausing all the scripts.   :-\

You're funny.

Snarky

I don't think it's at all an unreasonable thing to wish for. So instead of something like:

Code: ags

function foo()
{
  // script part 1
  SetTimer(1,40);
}

function bar()
{
  // script part 2
}

function repeatedly_execute()
{
  if(IsTimerExpired(1) == 1)
    bar();
}


You'd get something like:

Code: ags

function foo_bar()
{
  // script part 1
  WaitNonBlocking(40);
  // script part 2
}


That would obviously be much more straightforward to code and read (especially for newbies), and since in my experience this is often the effect you're trying to create, it would be nice if AGS streamlined it more.

Of course, I can see how it opens up a lot of other issues, like storing/restoring the stack (i.e. the expectation would now be that local variables could still be referenced after the pause), figuring out the order of execution, and dealing with all the fun new ways people could shoot themselves in the foot.

Khris

I guess purely from a technical standpoint it would be possible to have a keyword that gets the function to run in its own thread so one could actually use Wait().

What I meant by my comment is that while the request does sound reasonable, it's a SMOP.
The way I see it, being able to deal with this limitation is simply a required skill.

Snarky

Well, a more reasonable solution, and what you'd do in many languages (such as Javascript, IIRC), is to call a timer with an event handler that you provide as an in-line anonymous function. Something along the lines of (in pseudo-script):

Code: ags

function foo_bar()
{
  // script part 1
  SetTimer(40, new function()
  {
    // script part 2
  });
}


Not denying that it'd be a lot of work to add function pointers to AGS script, mind.

Calin Leafshade

I dont think function pointers (which is essentially what youre talking about) would actually be that much work to implement.

AGS obviously already links functions and stuff. You just need to save the pointer and run it at the right time. its just a variable really and AGS already runs script functions from their pointer.

Teaching the compiler to behave as Snarky describes is more difficult but something like this is more likely:

Code: ags

function foo() {
 //lol
}

function bar() {
  DoShit(foo);
  //or possibly without altering the compiler
  DoShit("foo");
}

Calin Leafshade

BAM!

http://www.thethoughtradar.com/AGS/AGSDelegates.zip

Delegates for ags. Used like this (obviously this is a silly example but delegates can be used as variables in functions like snarky suggested above):

Code: ags

Delegate *del;
int counter = -1;

// put here anything you want to happen every game cycle, even when the game is blocked
function repeatedly_execute_always() 
{

  if (counter > 0) counter --;
  if (counter == 0 && del != null)
  {
    del.Run(); 
    counter = -1;
  }
}

function theCallback() 
{
  Display("A ha!");
}

// called when a key is pressed. keycode holds the key's ASCII code
function on_key_press(eKeyCode keycode) 
{
  if (IsGamePaused()) keycode = 0; // game paused, so don't react to keypresses
  if (keycode == eKey0) 
  {
      counter = 100;
      del = Delegate.Create("theCallback");
  }

}


the delegated function must be in the global script but i guess i could set a switch so you can use it in rooms too.

I know no one will use this but it was a nice proof of concept.

monkey0506

Calin, I'm sure you're already aware of this, but dynamic delegates also would allow run-time scripting to take place...that is pretty nifty I think, and it was listed as one of the selling points of both the C# Runner and the Lua plugins. Neither were, to my knowledge, raging successes that took the AGS world by storm, but still cool nonetheless.

Code: ags
void RunScriptFunction(String name)
{
  Delegate *func = Delegate.Create(name);
  func.Run();
}

function txtFunction_Activate()
{
  RunScriptFunction(txtFunction.Text);
}

MaximusDecimus

Ok thanks for all the replies, I got it working now.

Monsieur OUXX

Hey, I hope Calin's delegates will go STRAIGHT to the modules forum, as it's a major hack to AGS' script limitations. All existing modules could potentially take advantage of this (not necessarily from a performance perspective, but from a usability perspective).

Also, how the beep did you do this so quickly and in such a clean manner, the grammar parser is such a mess (that's a rethorical question).

 

SMF spam blocked by CleanTalk