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?
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.
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".
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?
Thanks Khris. Worked perfectly.
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?
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:
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
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...:
//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
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.
Thanks a lot to both of you!
I appreciate your explanations of how the codes actually work. helps me a lot!
:)
By the way:
here's the code I am using now:
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!
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:
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!
(laugh)
ok, thank you for your feedback! Glad I can profit from experienced coders' knowledge on this forum.