Random movement within a set area?

Started by Hobo Joe, Mon 05/01/2009 13:30:27

Previous topic - Next topic

Hobo Joe

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?
Yay, I'm Hobo..... Joe...

Matti

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:

Code: ags


// 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.

Khris

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:

Code: ags
// 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".

Matti

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?

Hobo Joe

Yay, I'm Hobo..... Joe...

Khris

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?


lucasio6

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

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

Kumpel

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


//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

Snarky

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.

lucasio6

Thanks a lot to both of you!
I appreciate your explanations of how the codes actually work. helps me a lot!
:)


lucasio6

By the way:
here's the code I am using now:

Code: ags

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!

Snarky

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

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!

lucasio6

(laugh)
ok, thank you for your feedback! Glad I can profit from experienced coders' knowledge on this forum.

SMF spam blocked by CleanTalk