Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Hobo Joe on Mon 05/01/2009 13:30:27

Title: Random movement within a set area?
Post by: Hobo Joe on Mon 05/01/2009 13:30:27
I'm trying to get a character to move around at random, but I only want him to move around within a certain area/set of coordinates. How would I go about doing this?
Title: Re: Random movement within a set area?
Post by: Matti on Mon 05/01/2009 14:31:49
If the area ist rectangular it's not too complicated. Let's say the area should reach from x=100 and y=100 to x=200 and y=150 then you could do the following:



// top of the room's script:

int aim_x=100+random(100);
int aim_y=100+random(50);


// repeatedly execute:

if (Character.GetAtScreenXY(aim_x, aim_y) == cWalkingGuy) { // checks if the character has reached his temporary goal
  aim_x=100+random(100);                                    // if so, new coordinates are set
  aim_y=100+random(50);
}

cWalkingGuy.Walk(aim_x, aim_y, eNoBlock);



I haven't tested this though, but it should work that way.
Title: Re: Random movement within a set area?
Post by: Khris on Mon 05/01/2009 15:03:34
Character.GetAtScreenXY won't check just the character's feet but the whole sprite.

I'd draw a Region that covers the area they're supposed to roam, then use:

// room's rep_ex
  bool found;
  int x,y;
  if (!cGuy.Moving) {
    while(!found) {
      x = Random(Room.Width);
      y = Random(Room.Height);
      if (Region.GetAtRoomXY(x, y) == region[1]) found = true;
    }
    cGuy.Walk(x, y);
  }


In theory, you could draw a few, say, 5x5 pixel sized dots instead of one filled area and the character will walk randomly between those "way points".
Title: Re: Random movement within a set area?
Post by: Matti on Mon 05/01/2009 16:01:49
Quote from: KhrisMUC on Mon 05/01/2009 15:03:34
Character.GetAtScreenXY won't check just the character's feet but the whole sprite.

Ah, right. Sorry.

Btw: Why isn't there a character.xy command for NPCs?
Title: Re: Random movement within a set area?
Post by: Hobo Joe on Mon 05/01/2009 16:18:15
Thanks Khris. Worked perfectly.
Title: Re: Random movement within a set area?
Post by: Khris on Mon 05/01/2009 17:21:19
You're welcome ;)

Quote from: matti on Mon 05/01/2009 16:01:49
Btw: Why isn't there a character.xy command for NPCs?

Do you mean cNpc.x / cNpc.y?
Title: Re: Random movement within a set area?
Post by: Matti on Mon 05/01/2009 17:40:44
Quote from: KhrisMUC on Mon 05/01/2009 17:21:19
Do you mean cNpc.x / cNpc.y?

Exactly.
Title: Re: Random movement within a set area?
Post by: lucasio6 on Tue 27/10/2015 20:28:31
Hello there.

I tried out some of the code in this topic:

I want a NPC (a chicken) to randomly walk around on a defined region and occasionally interrupt walking around and do a different animation.

Here's what I have come up with:
Code (ags) Select

function room_RepExec()
{

intChickenRun = Random(2);
   
  if (intChickenRun !=0) {
 
  bool found;
  int x,y;
  if (!cChicken.Moving) {
    while(!found) {
      x = Random(Room.Width);
      y = Random(Room.Height);
      if (Region.GetAtRoomXY(x, y) == region[1]) found = true;
                  }
    cChicken.Walk(x, y);
  }
  }
 
  else if (intChickenRun ==0)
  {
    cChicken.LockView(25);
      cChicken.Animate(Random(3), 5, eOnce); //chicken has 3 animations to chose from: picking a corn to the left or to the right or just standing still)
      cChicken.UnlockView();
  }         
                       
}


However, I have two problems with this code:
1. the script does not wait until the chicken has finished walking so it is constantly executing 'cChicken.Animate(Random(3), 5, eOnce)'
2. My script blocks the gui so the player character can not do anything while the chicken walks around.

As I am new to scripting, I would appreciate some suggestions..

Thanks in advance!

Lucasio6
Title: Re: Random movement within a set area?
Post by: Kumpel on Tue 27/10/2015 23:29:03
This chickenwalk has to happen in repeatedly_execute_always if you want to do it in the background and therefore you have to write it only non blocking (so no wait-commands).

Here is how I made a similar thing with an NPC walking to a random waypoint x from x= 350 till x=410 , doing something and walking to the next random waypoint x2 to do something and so on...:

Code (ags) Select


//room header
int ranx;
bool start = false;

//Called by setting a SetTimer(6,1); and start = true

function repeatedly_execute_always()
{
   if (IsTimerExpired(6))
  {
    cGerald.UnlockView();
    if (start == true)
     {
     ran = Random(60);
     ranx = ran + 350;
     cGerald.Walk(ranx, 160, eNoBlock, eWalkableAreas);
     cGerald.AddWaypoint(ranx, 159);
     SetTimer(6, 200);
     start = false;
     }
   
    if (cGerald.x == ranx)
     {
     start = true;
     cGerald.LockView(22);
     cGerald.Animate(0, 13, eOnce, eNoBlock); // here you can put your random choice of animations
     SetTimer(6, 400); //this countdown must have at least the lenght of your animation to play so that the NPC walks on after it's done with it.
     }
    }
   }
}


I think you could easily add a random y-coordinate.

Hope that helps

Cheers
Kumpel
Title: Re: Random movement within a set area?
Post by: Snarky on Tue 27/10/2015 23:50:33
Quote from: Kumpel on Tue 27/10/2015 23:29:03
This chickenwalk has to happen in repeatedly_execute_always if you want to do it in the background

That's not quite accurate. The reason for lucasio6's problem #2 (player can't do anything) is that he's always calling cChicken.Walk() or cChicken.Animate(), which are both blocking by default. If he just made them non-blocking (like you have), that problem would go away. (His first problem is due to logic problems in the code, which can be handled in various ways: either with timers like you have done, or just by directly checking whether the chicken is currently walking or animating before telling it to do something else.)

You could equally well make this work in repeatedly_execute(); the only difference is that whenever some other process is blocking the game (e.g. the player walking), the chicken wouldn't be getting new instructions, so it would just wait around after completing its current animation or movement. It's not a big deal either way: repeatedly_execute() vs. repeatedly_execute_always() is not the issue here.
Title: Re: Random movement within a set area?
Post by: lucasio6 on Wed 28/10/2015 06:27:27
Thanks a lot to both of you!
I appreciate your explanations of how the codes actually work. helps me a lot!
:)

Title: Re: Random movement within a set area?
Post by: lucasio6 on Thu 29/10/2015 20:29:58
By the way:
here's the code I am using now:

Code (ags) Select

function room_Load()
{
SetTimer(1, 1);
}

function room_RepExec()

intChickenRun = Random(2);
     
if (IsTimerExpired(1)){
if (intChickenRun !=0) {
SetTimer(1, 45);   
bool found;
int x,y;
cChicken.UnlockView();
if (!cChicken.Moving) {
while(!found) {
x = Random(Room.Width);
y = Random(Room.Height);
if (Region.GetAtRoomXY(x, y) == region[1]) found = true;
}
cChicken.Walk(x, y, eNoBlock);     
                    }
 
        }
    else if (intChickenRun ==0) {
SetTimer(1,38);         
cChicken.LockView(25);
cChicken.Animate(Random(3), 4, eOnce, eNoBlock);
     }
}         

}


It works fine for me. You can adjust the SetTimer() functions to the animation length. I have a feeling that it is rather complicated for what it does though. However, I think I will leave it at that for now.. Thanks again to Snarky and Kumpel for the help!
Title: Re: Random movement within a set area?
Post by: Snarky on Thu 29/10/2015 22:04:29
Holy indent, Batman!

Glad you've got it working, but for your own good and/or the love of God, fix the indentation, man!

The current formatting is extremely confusing and misleading. It's impossible to tell at a glance which opening bracket each closing bracket goes with, and how each block of code relates to any other. You have three levels of ifs, and then an else-if: which if is it an alternative to? Impossible to say, because it doesn't line up with any of them! At first, I couldn't even tell that this was legal code, since it looked like the if(!cChicken.Moving) block was never closed.

Sanified:

Code (ags) Select

function room_Load()
{
  SetTimer(1, 1);
}

function room_RepExec()

  intChickenRun = Random(2);
  if (IsTimerExpired(1)) {
    if (intChickenRun !=0) {
      SetTimer(1, 45);
      bool found;
      int x,y;
      cChicken.UnlockView();
      if (!cChicken.Moving) {
        while(!found) {
          x = Random(Room.Width);
          y = Random(Room.Height);
          if (Region.GetAtRoomXY(x, y) == region[1]) found = true;  // Personally I don't like same-line if-commands, but I'll defer on that
        }
        cChicken.Walk(x, y, eNoBlock);     
      }
    }
    else if (intChickenRun ==0) {    // Now that we've reformatted, it becomes clear that this could just be a simple "else"
      SetTimer(1,38);
      cChicken.LockView(25);
      cChicken.Animate(Random(3), 4, eOnce, eNoBlock);
    }
  }         
}


You can use tabs or spaces for the indent (AGS has a setting), and as many spaces as you like, but maintain some consistency!
Title: Re: Random movement within a set area?
Post by: lucasio6 on Fri 30/10/2015 07:49:27
(laugh)
ok, thank you for your feedback! Glad I can profit from experienced coders' knowledge on this forum.