Below is a script based on one posted byZak Esher, plus annotations and a few parts I incorperated from Apotheus Silverman's swarm script to keep the creature underwater and to have it bounce when it hits something.
This works reasonably well but isn't perfect (the not-pefect part being my melding of two seperate scripts together as opposed to anything wrong with the originals, which are wonderful).
Any tips on how I could improve it? Thanks in advance.
CODE
float ver_num = 0.7;
//the "fish" will be called "aLife", but you can change that if you wish
string obj_name = "aLife";
float fStrength = 1.0;
float repulse_force_modifier = .86;
float rotation_damping_modifier = 50000;
//Rotation function
do_rotation(vector mypos, vector myvel)
{
float fmass = llGetMass();
llLookAt(llGetPos() + llGetVel(), fmass * 2.8, fmass * rotation_damping_modifier);
}
// Collision function
collide(vector loc)
{
vector mypos = llGetPos();
float fmass = llGetMass();
// Apply repulse force
vector impulse = llVecNorm(mypos - loc);
llApplyImpulse(impulse * repulse_force_modifier * fmass, FALSE);
// Update rotation
do_rotation(mypos, llGetVel());
}
default
{
state_entry()
{
llSetColor(<1,1,1>, ALL_SIDES);
llSetStatus(STATUS_SANDBOX, FALSE);
llSetStatus(STATUS_PHYSICS, TRUE);
llCollisionSound("", 0.0);
//Set Object Name to obj_name, which has been assigned as "Alife" (see above)
llSetObjectName(obj_name);
llSetObjectDesc((string)ver_num);
llSetBuoyancy (1.0);
//Look for other fish.
//In this case,get the name of nearby objects with active, running scripts
llSensorRepeat(llGetObjectName(), NULL_KEY, ACTIVE|SCRIPTED, 30, PI, 1.0);
}
on_rez(integer start_param)
{
llResetScript();
}
sensor(integer num_detected)
{
//turn green if something is detected
llSetColor(<0,1,0>, ALL_SIDES);
vector vSwarm_Center;
vector vSwarm_Vel;
integer iSwarm_Pop;
integer i;
//for each number deteteded do this:
for (i=0; i < num_detected; i++)
{
//add the detected position of current fish to vSwarm_Center
vSwarm_Center += llDetectedPos(i);
//add the detected velocity of the current fish to vSwarm Vel
vSwarm_Vel += llDetectedVel(i);
//add add one to iSwarmPop
iSwarm_Pop++;
}
//get the average position of the Swarm
vSwarm_Center = vSwarm_Center / iSwarm_Pop;
//get the average velocity of the Swarm
vSwarm_Vel = vSwarm_Vel / iSwarm_Pop;
float fMass = llGetMass();
//vTarget will be the current swarm center plus the veloctiy
//this tells us where the swarm is going
vector vTarget = vSwarm_Center + vSwarm_Vel;
//this tells us where the individual fish is going
vector vMypos = llGetPos() + llGetVel();
//we figure out the difference between where HE is and where the swarm is
vector vDesiredHeading = vTarget - vMypos;
//this tells us the distance beteen the two
float fDist = llVecDist(vTarget,vMypos);
//this tells us which way he needs to point
vector vImpulse = llVecNorm(vDesiredHeading);
//to keep him from getting too close, we create a repulse factor
//as fDist gets smaller, vRepulse gets bigger
vector vRepulse = vImpulse / fDist;
//this launches the fish
llApplyImpulse((vImpulse - vRepulse) * fStrength * fMass, FALSE);
//this points him in the right direction
llLookAt(vMypos, fMass * 2.8, fMass * 50000);
// keep underwater
if (vMypos.z >= llWater(vMypos) - llVecMag(llGetScale()))
{
//llSay(0, "collide() called due to air/water breach.");
collide(<vMypos.x, vMypos.y, vMypos.z + 0.3>);
}
}
//if he hits a wall (or another fish)
collision_start(integer total_number)
{
//llSay(0, "collide() called due to physical object collision.");
collide(llDetectedPos(0));
}
//if he sees nobody, he turns blue
no_sensor()
{
llSetColor(<0,0,1>, ALL_SIDES);
}
}
//Notes & Reminders
//Operators used:
//++ means add one increment each time
//thus i++ means add one to i
//+= adds variables together
//more precisly, it adds the second variable to the first:
// thus vSwarm_Vel += llDetectedVel(i)
// means add llDetectedVel(i) to vSwarm_Vel
p.s.
If you're new to this stuff, as I am, the two scripts I linked to above are great learning tools.