NPC Animation Sequence Issue

Started by Terminator2, Wed 08/02/2023 00:43:26

Previous topic - Next topic

Terminator2

Hello everyone,

I need some help resolving an issue with the following code. Now what I want is to have my NPC (the librarian) randomly walk to various locations and then when he gets to the spot, he needs to perform an animation. I can get it working for the most part but the animation doesn't work when I use the eNoBlock parameter. In other words, the librarian just stands there. Here's the code in the room repeat function:

 
Code: ags

if (TimerStart == true) {
    location = Random(0); // Randomize 9 numbers
    TimerStart = false; // Stop timer from randomizing
  }
  
  if (TimerStart == false) { // If timer is paused then send librarian to location
    if (cLibrarian.Moving) {
      // If librarian is moving do nothing
    } else {
      if (location == 0) {
        if (Walked == false) {
          cLibrarian.Walk(444, 229, eNoBlock, eWalkableAreas);
        }
          if (cLibrarian.Moving == true) {
            return;
          } else {
            Walked = true;
            cLibrarian.FaceDirection(eDirectionRight);
            cLibrarian.LockView(39);
            cLibrarian.Animate(2, 5, eOnce, eNoBlock, eForwards);
            if (cLibrarian.Animating == true) {
              return;
            } else {
              cLibrarian.UnlockView();
              Walked = false;
              TimerStart = true;
            }
          }
      }
	}
  }


There are normally 9 locations but for testing purposes, I just have it as 0.
When I do debug and the engine gets to the Animate command it goes and loops around through the GlobalScript repeatable
and doesn't come back to the room repeatable.

If I do the eBlock parameter it works but I can't control Ego.

Thanks.

Khris

I'm relatively sure that .Moving an/or .Animating might not immediately become true, they might only be true in the next frame.

You can try rewriting the code like this:
Code: ags
  if (cLibrarian.Moving || cLibrarian.Animating) return;

  if (TimerStart) {
    location = Random(0); // Randomize 9 numbers
    TimerStart = false; // Stop timer from randomizing
    Walked = false;
    return;
  }

  if (location == 0) {
    if (cLibrarian.x == 444 && cLibrarian.y == 229) Walked = true;
    if (!Walked) {
      cLibrarian.Walk(444, 229, eNoBlock, eWalkableAreas);
      return;
    }
    cLibrarian.FaceDirection(eDirectionRight);
    cLibrarian.LockView(39);
    cLibrarian.Animate(2, 5, eOnce, eNoBlock, eForwards);
    return;
  }
  
  cLibrarian.UnlockView();
  Walked = false;
  TimerStart = true;

The main difference is basically that the else branch will only run during the next frame since the code keeps exiting the function using "return;".
Untested!

Terminator2

I tried the code that you suggested Khris but it still isn't working. However, if I remove the return; from the if(!walked) statement the librarian performs the animation but on the starting point. If I remove the return; from below the animation statement the librarian only walks to the designated location.

So basically, I'm getting either one but not both as I wanted. I also tried a while loop to see if I can get the result but still nothing.

Any ideas, anyone?

Snarky

Are you sure you included line 1 of Khris's code? What you describe would be the expected behavior, I think, without that line, because you would be restarting the walk or animation every frame, which would block it from ever progressing.

Crimson Wizard

Quote from: Khris on Wed 08/02/2023 09:01:45I'm relatively sure that .Moving an/or .Animating might not immediately become true, they might only be true in the next frame.

No, they immediately tell the current state, otherwise you won't be able to write a code like:
Code: ags
player.Animate(... ,eNoBlock);
while (player.Animating)
    Wait(1);

Terminator2

I entered the code like this:
Code: ags

  if (cLibrarian.Moving || cLibrarian.Animating) {
    return;
  }

  if (TimerStart == true) {
    location = Random(0); // Randomize 9 numbers
    TimerStart = false; // Stop timer from randomizing
    Walked = false;
    return;
  }

  if (location == 0) {
    if (cLibrarian.x == 444 && cLibrarian.y == 229) {
      Walked = true;
      cLibrarian.FaceDirection(eDirectionRight);
    cLibrarian.LockView(39);
    cLibrarian.Animate(2, 5, eOnce, eNoBlock, eForwards);
    return;
    }
    if (!Walked) {
      cLibrarian.Walk(444, 229, eNoBlock, eWalkableAreas);
      return;
    } 
  }
  
  cLibrarian.UnlockView();
  Walked = false;
  TimerStart = true;

If I remove the first line then the librarian just walks in the initial spot forever.

Matti

#6
Quote from: Terminator2 on Wed 08/02/2023 00:43:26I can get it working for the most part but the animation doesn't work when I use the eNoBlock parameter. In other words, the librarian just stands there.

That's because you're calling the animate command over and over again, 40 times a second. In your code you don't check if the librarian's animation already started.

I came back to your first code and tried to change it to make it work. Aside from checking the animation I also got rid of the walked variable and tried to make the code shorter. It's untested though and I'm not sure if it (immediately) works.

Code: ags
if (TimerStart == true && !cLibrarian.Animating) { // only called after the librarian's animation stopped
    cLibrarian.UnlockView();
    location = Random(0); // Randomize 9 numbers
    TimerStart = false; // Stop timer from randomizing
  }
  
if (TimerStart == false) { // If timer is paused then send librarian to location
  if (!cLibrarian.Moving) {
    if (location == 0) {
      if (cLibrarian.x != 444 || cLibrarian.y != 229) { // send librarian to location
        cLibrarian.Walk(444, 229, eNoBlock, eWalkableAreas);
      }
      if (!cLibrarian.Moving && !cLibrarian.Animating) { // if he's not moving (anymore) and not animating (yet), animate him
        cLibrarian.FaceDirection(eDirectionRight);
        cLibrarian.LockView(39);
        cLibrarian.Animate(2, 5, eOnce, eNoBlock, eForwards);        
        TimerStart = true;
      }
    }
  }
}

Terminator2

Thank you so much, Matti. I tried your code and it works. I also want to thank you, Khris, as you did give me a better understanding of coding for other parts of my game. Thanks, everyone.

SMF spam blocked by CleanTalk