Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Hopping creature

Catfart Grayson
Registered User
Join date: 16 May 2004
Posts: 264
06-13-2007 23:45
These two scripts create a small physics enabled creature that moves around in a series of small jumps. It attempts to stay on your land, not always successfully. If it detects an avatar on your land, it moves towards it and sits at the avatars feet looking cute, or evil depending on what you put it in.

Drop the two scripts in a small, under 10 mass units, object. It will travel in the direction of the x-axis of the object.

A working, editable version of this code can be found at http://slurl.com/secondlife/olivia/17/95/21/ . Look for the small castle.

The code is open and free for you to use as you want. You may use the code in your own commercial products, but may not sell the creature as it stands.

Permission is given to anyone who wants to copy this code to the Wiki.

Put this code in a script called Brain.
CODE

key current_target;
vector current_target_pos;
float heartbeat = 5;

vector select_new_pos()
{
integer good_pos = FALSE;
while(good_pos == FALSE)
{
float xoffset = llFrand(20) - 10;
float yoffset = llFrand(20) - 10;

if(llGround(<xoffset,yoffset,0>) > llWater(<xoffset,yoffset,0>))
{
if((llGetLandOwnerAt(llGetPos() + <xoffset,yoffset,0>)) == llGetOwner())
{
good_pos = TRUE;
vector current_pos = llGetPos();
float new_x = current_pos.x + xoffset;
float new_y = current_pos.y + yoffset;
return <new_x,new_y,llGround(<xoffset,yoffset,0>)>;
}
}
}
//Shouldnt actually ever get to this line
return llGetPos();

}

default
{
state_entry()
{
llWhisper(0,"pop");
state search_for_avatar;
}
}
state search_for_avatar
{
state_entry()
{

list command=["MOVE",select_new_pos(),1];
llMessageLinked( LINK_SET, 150, llDumpList2String(command, "-=-"), "" );
llSetTimerEvent(30);

}
timer()
{
llSensor("","",AGENT,30,2 * PI);
}
sensor(integer num)
{
integer x = 0;
for(x;x < num;x = x +1)
{
if((llGetLandOwnerAt(llDetectedPos(x))) == llGetOwner())
{
current_target = llDetectedKey(0);
current_target_pos = llDetectedPos(0);
//fund an avatar, move to it
// llWhisper(0,"found target");
state aquired_avatar;
}
list command=["MOVE",select_new_pos(),1];
llMessageLinked( LINK_SET, 150, llDumpList2String(command, "-=-"), "" );
}
}
no_sensor()
{
list command=["MOVE",select_new_pos(),1];
llMessageLinked( LINK_SET, 150, llDumpList2String(command, "-=-"), "" );
}
link_message(integer sender,integer num, string data, key id)
{
if(num == 150)
{
list Arguments = llParseStringKeepNulls( data, ["-=-"], [] );
string Command = llList2String( Arguments, 0 );
if( Command == "ATPOS" )
{
llSensor("","",AGENT,30,2 * PI);
}
}
}
}
state aquired_avatar
{
state_entry()
{
llSensorRepeat("",current_target,AGENT,20,2 * PI, 1);
}
sensor(integer num)
{
current_target_pos = llDetectedPos(0);
if(llGetLandOwnerAt(current_target_pos) == llGetOwner())
{
list command=["MOVE",current_target_pos,2];
llMessageLinked( LINK_SET, 150, llDumpList2String(command, "-=-"), "" );
}
else
{
state search_for_avatar;
}
}
no_sensor()
{
//gone
state search_for_avatar;
}
link_message(integer sender,integer num,string data,key id)
{
if(num == 150)
{
list Arguments = llParseStringKeepNulls( data, ["-=-"], [] );
string Command = llList2String( Arguments, 0 );
if( Command == "ATPOS" )
{
//reached avatar!!
state reached_avatar;
}
}

}
}
state reached_avatar
{
state_entry()
{
// llWhisper(0,"reached target");
llSensorRepeat("",current_target,AGENT,4,2 * PI, 3);
}
sensor(integer blah)
{
}
no_sensor()
{
// llWhisper(0,"lost target");
state search_for_avatar;
}
}


==================
Put the following code in a script called movement

CODE


integer reached_target = TRUE;
vector jump_force = <1,0,2.5>;
vector target_position;
integer target_id;

pop()
{
if(reached_target == FALSE)
{
llRotLookAt(getRotToPointAxisAt(AXIS_FWD , target_position), 10, 0.5);
llApplyImpulse(jump_force * llGetMass(),TRUE);
llPlaySound("pop",1);
// llWhisper(0,"pop");
}
}

vector AXIS_UP = <0,0,1>;
vector AXIS_LEFT = <0,1,0>;
vector AXIS_FWD = <1,0,0>;
// getRotToPointAxisAt()
// Gets the rotation to point the specified axis at the specified position.
// @param axis The axis to point. Easiest to just use an AXIS_* constant.
// @param target The target, in region-local coordinates, to point the axis at.
// @return The rotation necessary to point axis at target.
// Created by Ope Rand, modifyed by Christopher Omega rotation
rotation getRotToPointAxisAt(vector axis, vector target)
{
return llGetRot() * llRotBetween(axis * llGetRot(), target - llGetPos());
}


default
{
state_entry()
{
llWhisper(0,"movement reset");
llSetStatus(STATUS_PHYSICS,TRUE);
llSetStatus(STATUS_ROTATE_X,FALSE);
llSetStatus(STATUS_ROTATE_Y,FALSE);
state move;
}
}
state move
{
state_entry()
{
}
not_at_target()
{
llRotLookAt(getRotToPointAxisAt(AXIS_FWD , target_position), 2, 0.5);
}
link_message(integer sender, integer num,string data, key id)
{
if(num == 150)
{
list Arguments = llParseStringKeepNulls( data, ["-=-"], [] );
string Command = llList2String( Arguments, 0 );
if( Command == "MOVE" )
{
// llWhisper(0,"move");
llTargetRemove(target_id);
target_id = llTarget((vector)llList2String( Arguments, 1 ),2);
target_position = (vector)llList2String( Arguments, 1 );
reached_target = FALSE;
pop();
}
}
}
at_target(integer tnum,vector targetpos,vector ourpos)
{
reached_target =TRUE;
llMessageLinked(LINK_SET,150,"ATPOS","");
}
collision_start(integer num)
{
pop();
}
land_collision_start(vector pos)
{
pop();
}
}
_____________________
Cat
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Original Thread
06-17-2007 07:04
/15/0e/190698/1.html
_____________________
i've got nothing. ;)
Zoa Hax
Registered User
Join date: 2 Feb 2007
Posts: 2
Am i doin it wrong?
06-17-2007 17:44
I cant seem to get it to work.. i went to the slurl thing too and could not find the the free object to edit. i saw all the lil guys bouncing around and stuff but not the free one.. Do you need to own the land you put them down on?
Catfart Grayson
Registered User
Join date: 16 May 2004
Posts: 264
06-17-2007 22:54
Zoa,

The poppers come from the small castle. Take a copy of that.

Yes, you do need to own the land you put them on. Although it is reasonsbly simple to remove this test from the scripts.
_____________________
Cat
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
06-17-2007 23:02
good work :) I'm always looking for new ways to locomate various A-life in my on-going ecosystem, and I'm probably going to base the movement for one of my newer creatures off your script :)
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
06-18-2007 09:57
a quick critique; why not use a sensor repeat instead of the sensor in the timer event?


also, due to the collision nature of moving, it doesn't do too well indoors, so I had to add a basic "turn right" algorithm when it collided with something that wasn't below it (i.e. floor) so that it wouldn't perpeptually throw itself high into the air as it bounced from the ground to the wall, and then hits the ceiling and throws itself up against the ceiling again etc.

also, I've tweaked the Brain script quite a bit so that it only pings for an avatar to follow every 5 seconds, this makes it's "stalking" of avatars seem less active, but it will still stay in the general area of what it's following.

I'll post my stripped down code later once I finish working out some new bugs I've introduced.
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Catfart Grayson
Registered User
Join date: 16 May 2004
Posts: 264
06-18-2007 10:10
From: Senuka Harbinger
a quick critique; why not use a sensor repeat instead of the sensor in the timer event?


also, due to the collision nature of moving, it doesn't do too well indoors, so I had to add a basic "turn right" algorithm when it collided with something that wasn't below it (i.e. floor) so that it wouldn't perpeptually throw itself high into the air as it bounced from the ground to the wall, and then hits the ceiling and throws itself up against the ceiling again etc.

also, I've tweaked the Brain script quite a bit so that it only pings for an avatar to follow every 5 seconds, this makes it's "stalking" of avatars seem less active, but it will still stay in the general area of what it's following.

I'll post my stripped down code later once I finish working out some new bugs I've introduced.


Senuka,

This is pretty old code, I'll try and remember why I did things :)

Why no sensor repeat? Good question, its certainly not the way I would do it now. I suspect I may have thought there wa an issue with having an extra sensor command in the link_message event.

Re inside use: Does it go mad? LOL. Not sure I've ever tried my creatures inside somewhere. In general I tend to use vehicle code now. Physical objects with applied forces and impulses are fun, but not controllable enough.
_____________________
Cat
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
06-18-2007 13:19
From: Catfart Grayson
Physical objects with applied forces and impulses are fun, but not controllable enough.


but that's why they make for the most fun toys to play with :D


here's my greatly reduced code. I consolidated the two scripts into something that for now allows my object to orbit around an avatar standing still, and if the avatar is moving for a while it will follow in it's general direction. I suppose if I really wanted to I could set some kind of a target for it to try and center around if it can't find any avatars and use the at_target and not_at_target events in conjunction with detected positions to cause the hopper to come to a halt when it gets near an avatar instead of merely when it collides with it.

CODE

vector target;

pop()//need to add in sound effects here.
{
llApplyImpulse(<.025,0,.25>,TRUE);//adjust the x and z value to give it more of a forward push (x) or more of a hop (z)
}


default
{
state_entry()
{
llSetText("",<1,1,1>,1);
llSensorRepeat("",NULL_KEY,AGENT,10,PI,1.5);
llSetStatus(STATUS_PHYSICS,TRUE);
llSetStatus(STATUS_ROTATE_X|STATUS_ROTATE_Y,FALSE);
}

sensor(integer num)//buggered up checking if the people it's trying to follow are on my land.
{
//if(llGetLandOwnerAt(llDetectedPos(0))==llGetOwner())
//{
target=llDetectedPos(0);
//}
//else
//{
// target=<0,0,0>;
//}
}

no_sensor()//didn't find anything so lets set our target to ZERO_VECTOR
{
target=<0,0,0>;
}

land_collision_start(vector pos)
{
pop();
}

collision_start(integer num)//we hit something!
{
//llSay(0,(string)llDetectedType(0));
if(llDetectedType(0)!=AGENT)//we didn't hit an avatar
{
//llSetText((string)target,<1,1,1>,1);//debugging shiz.
vector mypos=llGetPos();
vector col_pos=llDetectedPos(0);
if(col_pos.z < mypos.z)//if the height of the center of what we hit was below us (such as a floor)
{
if (target !=<0,0,0>)//if we have a target defined to move to, look towards that target
{
llRotLookAt( llGetRot() * llRotBetween(<1,0,0>*llGetRot(),target-mypos),2,.5);
}
}
else//We hit something and it's higher than us so it must be a wall. lets turn to the left a little bit so our next hop (hopefully) won't hit the wall again.
{
llRotLookAt(llGetRot() * llRotBetween(<1,0,0>* llGetRot(),<0,1,0>*llGetRot()),2,.5);
}
pop();
}
else//we hit an avatare. lets take a break for a few seconds.
{
llSleep(3);
pop();
}
}

}
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Catfart Grayson
Registered User
Join date: 16 May 2004
Posts: 264
06-18-2007 15:15
Interesting variation.

I'm not able to get into SL at the moment to check, but i think your version only works inside, or when it collides with something that is not land.

Your code to turn is inside the the collision_start event. What if it's in the open and only collides with the ground? The sensor event will change the target vector, but the code to change its direction only fires when it collides with another object.
_____________________
Cat
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
06-18-2007 21:49
From: Catfart Grayson
What if it's in the open and only collides with the ground? The sensor event will change the target vector, but the code to change its direction only fires when it collides with another object.


If it collides with the land, it should keep going in it's direction, if it collides with an object (say it hopped, and hit a wall) it will turn while in the air before hopping again. this means that at ground level it will bounce into a wall, turn slightly, bounce on the new vector and may or may not collide with the wall again.

I see what you mean about the direction change only firing with colliding on another object, so I added in the clause for hitting the ground too :)


right now I've got a nasty bug where putting a sleep in the at_target() event causes it to appear to "sleep" all the time, even if the at_target event isn't firing, so I'm not quite sure what's going on there.


once I figure out how I broke the "am I on the owner's land?" part, I'm going to add in a random "walk" to the hopper so that it's not quite so predictable.
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Catfart Grayson
Registered User
Join date: 16 May 2004
Posts: 264
06-19-2007 13:53
From: Senuka Harbinger
If it collides with the land, it should keep going in it's direction, if it collides with an object (say it hopped, and hit a wall) it will turn while in the air before hopping again. this means that at ground level it will bounce into a wall, turn slightly, bounce on the new vector and may or may not collide with the wall again.

I see what you mean about the direction change only firing with colliding on another object, so I added in the clause for hitting the ground too :)


right now I've got a nasty bug where putting a sleep in the at_target() event causes it to appear to "sleep" all the time, even if the at_target event isn't firing, so I'm not quite sure what's going on there.


once I figure out how I broke the "am I on the owner's land?" part, I'm going to add in a random "walk" to the hopper so that it's not quite so predictable.


Fraid, I cant see anything wrong with the llGetLandOwnerAt line. Looks likes its in the right place. If you cant get the llSleep to work inside an at-target event, you could always try having a separate state.

If you adding in more behaviours, even something as simple as a random wander, you might want to take a look at steering behaviours . http://www.red3d.com/cwr/steer/
_____________________
Cat
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
06-20-2007 00:07
From: Catfart Grayson
Fraid, I cant see anything wrong with the llGetLandOwnerAt line. Looks likes its in the right place. If you cant get the llSleep to work inside an at-target event, you could always try having a separate state.

If you adding in more behaviours, even something as simple as a random wander, you might want to take a look at steering behaviours . http://www.red3d.com/cwr/steer/



thanks for the link :D I had been using some of those principles in my A-life fish that I had to stumble onto by myself. the collision avoidance thing makes me wonder if it would be possible to create an object that could successfully navigate a maze using llVolumeDetect on an invisible outer sphere to tell if it was going to hit an object or not.
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Carina Catteneo
Registered User
Join date: 20 Apr 2007
Posts: 7
Help
08-12-2007 14:20
Can anyone help me make this script work in my animal.
Please IM me

Thanks :)
Carina Catteneo
Registered User
Join date: 20 Apr 2007
Posts: 7
Forgot
08-14-2007 10:40
I pay 500 linden
Ollj Oh
Registered User
Join date: 28 Aug 2007
Posts: 522
12-26-2007 21:15
Nah. dont pay for incompetent code!

This barely works. It fails in communication.
If i reset the movement script it stops moving, forever, thus it can barely be modified.

I can not make it turn.