Solved: Character in hot pursuit of another

Started by johanvepa, Sat 23/03/2013 00:22:50

Previous topic - Next topic

johanvepa

I want my character to be pursued by a monster across the screen. Part of the puzzle is to figure out how to get around the monster.
I made the monster a character, gamewise.

Anyway, to have the monster pursue the character, I'm trying with this code:

Code: AGS

function room_RepExec()
{
cMonster.FollowCharacter(cEgo);
}


It works, but the monster reacts very slowly indeed, and only changes direction towards the character at long intervals, making it much too easy for the character to walk away and around the monster.

I also tried this:

Code: AGS

function room_AfterFadeIn()
{
cMonster.FollowCharacter(cEgo);
}


but that made the monster's response time even worse.

Any suggestions as to how I can make the character "cMonster" more effective in pursuing the player character?

Ghost

#1
Character.FollowCharacter(Character* chartofollow, optional int dist, optional int eagerness)

The optional parameters are what you want: dist is the distance the following char will try to "hold", a low value means "closer to the followed". Eagerness is how frequently the follower will update its position; again, a low value means "more frenzied chase".
If you enter 0 for dist AND eagerness, the follower will always, instantly, forever, stand where the followed character stands. This is most likely NOT something you want, so take care!  :P

The command belongs to after_fadein, not repeatedly_execute, by the way- you only need to call it once (or again when the behaviour must change), so there is no need to call it over and over in rep_exe.

johanvepa

Quote from: Ghost on Sat 23/03/2013 01:23:57
Character.FollowCharacter(Character* chartofollow, optional int dist, optional int eagerness)

The optional parameters are what you want: dist is the distance the following char will try to "hold", a low value means "closer to the followed". Eagerness is how frequently the follower will update its position; again, a low value means "more frenzied chase".
If you enter 0 for dist AND eagerness, the follower will always, instantly, forever, stand where the followed character stands. This is most likely NOT something you want, so take care!  :P

The command belongs to after_fadein, not repeatedly_execute, by the way- you only need to call it once (or again when the behaviour must change), so there is no need to call it over and over in rep_exe.

It's that simple! I should have figured that out myself. Thank you for your time and sorry for taking it for something so trivial. I take it the pursuing character's speed still has something to say, yes? Even with dist 0 and eagerness 0, if the player controlled character is faster than the computer controlled character, the player will still outrun the monster when going in a straight line, yes?

I'll take it to the test as soon as I can. Thank you again   :)

Ghost

Speed is NOT a factor once you set dist and eagerness to 0, that is a special case where you have both characters always set at the same coordinates. Imagine you make a t-shirt as a character; with the "null settings" you can have it so that the shirt is always drawn on top of the player sprite.
1 is the lowest setting you can enter without triggering the special case, and then, walking speed is accounted for.

You can also press F1 in AGS to open the manual, and type the name of any command there to have a full description, together with example code. Sometimes it is hard to figure out what AGS *can* do, but the manual is a good help and a nice read on a sunday afternoon  ;-D

johanvepa

Quote from: Ghost on Sat 23/03/2013 17:47:56
Speed is NOT a factor once you set dist and eagerness to 0, that is a special case where you have both characters always set at the same coordinates. Imagine you make a t-shirt as a character; with the "null settings" you can have it so that the shirt is always drawn on top of the player sprite.
1 is the lowest setting you can enter without triggering the special case, and then, walking speed is accounted for.

You can also press F1 in AGS to open the manual, and type the name of any command there to have a full description, together with example code. Sometimes it is hard to figure out what AGS *can* do, but the manual is a good help and a nice read on a sunday afternoon  ;-D

Usually, I do read the manual before posting a question here. I guess I got a bit over-excited.

.M.M.

Actually, it works differently:
Quote(AGS manual)
The default values are DIST=10 and EAGERNESS=97.

As a special case, setting DIST=0 and EAGERNESS=0 makes CHARID behave as if it is chasing CHARTOFOLLOW - it will try and get there as quickly as possible. Setting EAGERNESS=0 also tells the character not to stop when they reach CHARTOFOLLOW, but instead to randomly wander around the character - useful perhaps for a very energetic dog or something.

There is also another special use for this command. You can pass the special value FOLLOW_EXACTLY as the DIST parameter rather than passing a number. If you do this, then CHARID will always remain at exactly the same X and Y co-ordinates as CHARTOFOLLOW. This might be useful for effects such as a temporary halo over the character and so forth.

If you use FOLLOW_EXACTLY, then EAGERNESS has another meaning. If you pass 0, CHARID will be drawn in front of CHARTOFOLLOW; if you pass 1, it will be drawn behind.

So, you can pass 0 and 0, the monster then walks around the character even if it reaches him.

johanvepa

Wait, something's wrong here.

I do exactly (I think) as you and the manual tells me, yet the following character takes a VERY long time to react, and when he does, he walks across the entire screen before checking to see if he needs to turn direction again.

I use this code:
Code: AGS

function room_AfterFadeIn()
{
Display("Watch out for that guy!");
cMonster.FollowCharacter(cEgo, 1, 1);
}


This should make cMonster follow cEgo closely around, running at his speed setting towards cEgo and checking very often to alter direction towards cEgo.
Right?
Any ideas as to why cMonster takes so long to try and intercept cEgo?

Khris

#7
Did you remove the line in Room_RepExec?

Did you try 0, 0?

I did a few tests and 0,0 0,1 and 1,1 all worked fine for chasing the player.


johanvepa

Quote from: Khris on Sun 24/03/2013 20:35:43


Did you try 0, 0?

I did a few tests and 0,0 0,1 and 1,1 all worked fine for chasing the player.


Yup, did those, too.
No effect. The monster is lagging behind helplessly, walking across the entire screen length before stopping to think about changing direction. What am I doing wrong?

johanvepa

Oh, and the room isn't cluttered by code, it's a new room. In fact, ALL the code in the room is this:



Code: AGS

function region1_WalksOnto()//exit room
{
cEgo.ChangeRoom(10, 308, 155);
}

function room_AfterFadeIn() //pursued when entering room
{
Display("You better watch out for this guy");
cMonster.FollowCharacter(cEgo, 1, 1);
}

Khris

For testing purposes I filled the entire room with walkable area 1.
What's your setup?

johanvepa

Quote from: Khris on Sun 24/03/2013 22:57:40
For testing purposes I filled the entire room with walkable area 1.
What's your setup?

There is one walkable area, walkable area 1. It fills about half the room. I have not yet defined the walk-behinds.
I'm not sure I understand what you mean with setup.

Khris

I was just asking about your walkable area, like, is it winding and narrow and stuff like that.
Seems it isn't.
Well, I'm at a loss; without looking at your source files I'm not going to be able to help you.

Cerno

I guess that's pretty old news, but in these cases it might help to start a new game, recreate your problem room and see if the problem persists.
If everything works, you can try to hunt for the differences between the two games.

This can be quite tedious though.
Posting code or your whole game here for the experts to analyze might be your better bet ;)
123  Currently working on: Sibun - Shadow of the Septemplicon

johanvepa

The walkable area is quite unobstruced and large.

I'll try to recreate the room in another new game as soon as I can and see what happens.

I'll also gladly upload my source files, but perhaps I'll waste less of your time by trying out some things by myself first.
Is there anything in the global scripts that might cause these problems?

Am I correct in assuming that the best thing to do codewise is have the monster be a character, not an animated object?

Khris

There's no Object.FollowCharacter() command, so yes :)

Another alternative is coding your own follow behavior. Something like this:

Code: ags
// above Room's rep_exec
int chase_timer;

// in Room's rep_exec
  if (monster_chases_player) {   // create this bool, set it to true
    if (chase_timer < GetGameSpeed() * 2) chase_timer++;
    else {
      chase_timer = 0;
      if (cMonster.Moving) cMonster.AddWaypoint(player.x, player.y);
      else cMonster.Walk(player.x, player.y);
    }
  }

Although this might result in an error like "too many waypoints" or something. Not tested.

johanvepa

Thank you Khris. As always, your codings are a little over the top of my abilities, but they inspire me to make something that works for me nonetheless. And I think this one really does.

The reaction time of the monster is exactly the same when I start a new game. No difference there.

I've noticed this: The monster's speed settings have a lot to say. It doesn't actually alter what happens, but it makes things LOOK very differently. With high speed settings, the monster will still walk across the entire screen before turning to cEgo, but it takes much less time, so it's less noticeable. With low speed settings (it is a huge, bulky monster, not a sprinter), it takes forever to get there, thus its reaction time also becomes slower. Ergo: In the FollowCharacter mode, the follower reacts again after reaching the spot where the followed character stood, not after a certain wait measured in seconds.

Anyway, on to the code (tested and working):

Code: AGS


bool Monsterisalive;

function room_FirstLoad()
{
Monsterisalive = true;
Display("Watch out!");
}

int Monsterchase;

function room_RepExec()
{
  if (Monsterisalive)
    {
    if (cMonster.IsCollidingWithChar(cEgo))
      {
      Display("It's no use trying to run.");
      //Fight initiating. Animation of monster dying
      Display("After a nasty, brutish and short fight, you slay the Monster to the ground.");
      Monsterisalive = false;
      }
    else 
      {
      Monsterchase ++;
      if (Monsterchase > 80)
        {
        Monsterchase = 0;
        cMonster.Walk(player.x, player.y, eNoBlock, eWalkableAreas);
        }
      }
    }
}



This way, the monster checks every game round if the chase timer has reached 80. If not, then add 1. If so, then null the timer and alter direction towards player. And since there are 40 game rounds on a second, the monster changes direction every 2 seconds.

And it works!

I also added a bit about being caught up by the monster.

SMF spam blocked by CleanTalk