optimizing loop

Started by miguel, Tue 15/01/2013 10:10:29

Previous topic - Next topic

miguel

Quoteif you're talking about calling several functions in rep_exe
- yes that's what I meant.
About the speed, I wonder if anybody can back this behaviour with similar experiences.

But, you're saying that in a big if with several if's, when return (with no return value, thanks for the tutorial :smiley:) is called, it exits the if condition but stays on the one where it was first included?
Like (not real code):

Code: AGS
if (a > b) {
  if (b==3) {...code
    if (d==b) {...code...; return;
    }
  }
  if (b==4) {...code
  }
}


When return is called the code goes back to if (b==3) {...code?
-------------------------------------------------------------------------------

Crimson, I was about to post this when I noticed your post, this is becoming interesting!
Working on a RON game!!!!!

Crimson Wizard

Miguel, the return statement exits the current function right away. It has nothing to do with ifs / elses / loops. Just function.

miguel

Okay, I understand that,
but when a function is inside a if?
Working on a RON game!!!!!

Crimson Wizard

#23
The return statement moves the execution out of the current function to the line of code after function call.
It does not matter where function call was.

Each function has an "invisible" return in the end anyway, so makign a return from the middle of the function will continue program exactly as if the function returned "normally". It does not matter if there was if/else/loop etc.

Code: ags

if (....)
{
   my_func(); // <---- calling the function
   some other code // <---- this is where program continues after return from function, in ANY way.
}



//-------------
EDIT:
Wait, do you mean, if there's an if INSIDE the function?
In this case, it will just return as always.
Code: ags

function my_func()
{
   if (a)
   {
      if (b)
      {
         return; // exits the function right away, no more code from this function is executed
      }
      return; // same
   }

  // hidden "return" here, exits the function
}

miguel

Thanks, now I understand it.
It turns out I did the mistake of using return where it should not be used, a old and bad habit of wrapping things up with return...
This "lessons" were most helpful to me.
Working on a RON game!!!!!

Khris

Quote from: Crimson Wizard on Thu 17/01/2013 21:49:58There's a code style that suggests using early 'return' instead of taking a different execution branch(es) into 'if' block
Good or bad, I use that a lot :P.
Me too :)

miguel

Back again!

I decided to change the behaviour of my enemies when chasing the player. I was using follow character before.
After the change, enemies "walk" without leaving the spot.
Here is the code, you can see where I changed:

Code: AGS
function enemydetection() {
  int closestEnemy = -1;
  int maxRange = 700;
  int xDiff; int yDiff; int enemyDistance;
  int i=1;
  while (i< 7) {
  xDiff = stHero.Char.x - stbandit[i].Char.x;
  yDiff = stHero.Char.y - stbandit[i].Char.y;
  enemyDistance = xDiff*xDiff + yDiff*yDiff;
  if (enemyDistance < maxRange) {
    if (stbandit[i].health > 0) {
      mood=ataking;
//    stbandit[i].Char.FollowCharacter(stHero.Char, 0, 0);
    stbandit[i].Char.Walk(stHero.Char.x, stHero.Char.y, eNoBlock, eWalkableAreas);
    closestenemy=i;
//    return;
    }
  }
  else if (enemyDistance > maxRange) {
    mood=free;
    closestenemy=0;
//    stbandit[i].Char.FollowCharacter(null);
    stbandit[i].Char.StopMoving();
  }
i++;
  }
}


mood set to attacking runs a collision function, and set to free runs the function above;
Working on a RON game!!!!!

Khris

Calling Character.FollowCharacter() changes the character's follow data, and that data is used by AGS to control the character, independently of how often it changes.
Character.Walk on the other hand is an "active" command which does something to the character directly.

While calling the first one 40 times per second works fine, calling .Walk every frame doesn't give the character any chance to actually start walking.
The solution is to add a check for Character.Moving:
Code: ags

  if (!stbandit[i].Char.Moving) stbandit[i].Char.Walk(...);


The problem with this method: the character won't actually follow the player, they'll just move wherever the player used to be. If you want to stick to this method, you might want to call the .Walk command every few seconds.
I'd add a timer int to the bandit struct and count it down, then call .Walk again.

miguel

Code: AGS
if (!stbandit[i].Char.Moving) stbandit[i].Char.Walk(...);


I should have known this bit by now. Crimson advice was the same when he told me about checking if a character was animating and so on.
Enemies not following the player is not really a problem as long as they meet him and collide. The problem I'm facing now is that when the fight occurs it gets engaged super fast. I tried to counter this with a function that "pushed" character away a few pixels if they are hit:

Code: AGS
function bpushed() {
  int i=closestenemy;
  stbandit[i].Char.FollowCharacter(null);
  if (stbandit[i].name=="Bandit") {
  if (stbandit[i].Char.x > stHero.Char.x) {
    if (!stbandit[i].Char.Moving) {
    stbandit[i].Char.Move(stbandit[i].Char.x + 8, stbandit[i].Char.y, eNoBlock, eWalkableAreas);  
    AudioChannel* bhurt = abandit_hurt.Play();
    }
  }
  if (stbandit[i].Char.x < stHero.Char.x) {
    if (!stbandit[i].Char.Moving) {
    stbandit[i].Char.Move(stbandit[i].Char.x + 8, stbandit[i].Char.y, eNoBlock, eWalkableAreas);  
    AudioChannel* bhurt = abandit_hurt.Play();
    }
  }
  }
  if (stbandit[i].name=="Rat") {
    if (stbandit[i].Char.x > stHero.Char.x) {
    if (!stbandit[i].Char.Moving) {
    stbandit[i].Char.Move(stbandit[i].Char.x + 8, stbandit[i].Char.y, eNoBlock, eWalkableAreas);  
    AudioChannel* rpain = arat_pain.Play();
    }
  }
  if (stbandit[i].Char.x < stHero.Char.x) {
    if (!stbandit[i].Char.Moving) {
    stbandit[i].Char.Move(stbandit[i].Char.x + 8, stbandit[i].Char.y, eNoBlock, eWalkableAreas);  
    AudioChannel* rpain = arat_pain.Play();
    }
  }
  }
  mood=death;
}


My goal was to prevent characters from always colliding and it worked fine (not 100%) when I was using followcharacter; now the fights run super fast even if the "push" functions are being called.
Is the answer adding more checks to slow things down?
Working on a RON game!!!!!

Khris

#29
First of all, the only thing that changes in that code is the sound.
Also, you're adding 8 to the character's x in both cases.

Code: ags
function bpushed() {
    int i=closestenemy;
    Character* c = stbandit[i].Char;
    c.FollowCharacter(null);

    AudioClip* hurt;
    if (stbandit[i].name == "Bandit") hurt = abandit_hurt;
    if (stbandit[i].name == "Rat") hurt = arat_pain;

    int dx;
    if (c.x > stHero.Char.x) dx = 8;
    else dx = -8;

    if (!c.Moving) {
        c.Move(c.x + dx, c.y, eNoBlock, eWalkableAreas);
        hurt.Play();
    }
    mood=death;
}

miguel

Wow! Take that Miguel! :) 
Strange that it kind of worked with followcharacter instead of enemies walking to player.x and y. Must be related to what you said about followcharacter.
Thanks for the help Khris, I guess I've got a lot to clean up in my code.
Working on a RON game!!!!!

SMF spam blocked by CleanTalk