|
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
|
01-14-2007 14:36
Has anyone written script for a 'plane' style vehicle entirely piloted by a script? I'm trying to write scripts for a bird-type creature that should be able to fly around on its own (as well as landing, swooping down to eat seeds, etc), and even with the simplification of setting buoyancy to 1.0 so I don't have to be moving to generate lift, I still don't think it's simple to get them going where I want them to, while still looking realistic.
Has anyone got experience with this, or better, scripts to share?
|
|
grumble Loudon
A Little bit a lion
Join date: 30 Nov 2005
Posts: 612
|
01-14-2007 23:55
The AutoBahn system creates a vechical without using the vehicle system. http://www.lslwiki.com/lslwiki/wakka.php?wakka=AutobahnHere is the current vehicle script. The rotation does not work yet, but it shows the basic concept. // Automatic car script, By grumble Loudon //From Simple car script V1.0 // //V0.4 (not done)
integer m_DesiredSpeed = 0; // forward/ reverse integer m_WheelPos = 0; // Right / left
//********************************************************************************* integer m_Lane = 1; integer m_Segment = 0;
integer m_Scanning = FALSE; key m_DetectedKey; //
integer m_RoadValid; //We have an item.
string m_DetectedRoadName;
//list m_DetectedList; //it's data
integer m_UseRotation; //true to use prim rotation //vector m_DetOffset; //true to use prim rotation vector m_TargetPos; rotation m_TargetRot; key m_TargetKey;
vector m_RotVect;
// vector m_VelLast; rotation m_RotLast;
//------------------------------------------------------------------- // NoteCard configuration
string m_strNotecard = "Config"; integer m_lineCounter = 0; key m_dataRequestID = "";
vector m_SitTargetPos = <0,0,0>; //Overridden by notecard rotation m_SitTargetRot = ZERO_ROTATION; //
//********************************************************************************* UseCommand(string msg) { //message from either chat or notecard integer msgLen = llStringLength(msg); if (msgLen >= 3) //we need at least one command char and one data char { if (llGetSubString(msg,0,0) != ";") { //comment integer nFind = llSubStringIndex(msg,"="); if ((nFind >= 1 ) && ((msgLen - nFind) > 1)) { //commands must be at least 1 chars string command = llGetSubString(msg,0,nFind - 1); string strData = llGetSubString(msg, nFind + 1, msgLen - 1); if (command == "SitTargetPos"){ m_SitTargetPos = (vector)strData; llSitTarget(m_SitTargetPos, m_SitTargetRot); }else if (command == "SitTargetRot"){ m_SitTargetRot = (rotation)strData; llSitTarget(m_SitTargetPos, m_SitTargetRot); };// command };//find }; //comment };// len <4
}//Use message //********************************************************************************* UpdateStatus(){ string msg;
msg = "Wheel = " + (string) m_WheelPos; msg += "\nSpeed = " + (string) m_DesiredSpeed; msg += "\nEnergy = " + (string) llGetEnergy(); if (m_RoadValid == FALSE){ msg += "\nRoad not valid. Scaning = " + (string)m_Scanning; }else{ msg += "\n" + m_DetectedRoadName + " Target Pos = " + (string)m_TargetPos; if (m_UseRotation){ msg += "\n Rotation = " + (string)m_TargetRot; }else{ msg += "\n Auto Rotation = "; }; msg += "\n Test tourqe = " + (string)m_RotVect; }; llMessageLinked(LINK_ALL_CHILDREN, 1, msg, NULL_KEY); //llSetText(msg,<1,1,1>,1); }
//********************************************************************************* UseRoadName(string ObjectName){ // //llOwnerSay(ObjectName); m_RoadValid = FALSE; list Prams = llParseStringKeepNulls(ObjectName,[";"],[]); integer listLenght = llGetListLength(Prams); if (listLenght >= 7 ){ //0 PublicRoad //1 version //2 Lane //3 speed m_DetectedRoadName = llList2String(Prams,4); //4 Name m_TargetPos = (vector)llList2String(Prams,5); //5 target string RotStr = llList2String(Prams,6); //6 rotation if (llStringLength(RotStr) > 2){ m_TargetRot = (rotation)RotStr; m_UseRotation = TRUE; }else{ m_UseRotation = FALSE; }; string keyStr = llList2String(Prams,7);//7 next key if (llStringLength(keyStr) > 10){ m_TargetKey = (key)keyStr; m_RoadValid = TRUE; }; UpdateStatus(); };//list count >= 7
}//Use name
//********************************************************************************* default { state_entry() { llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", NULL_KEY); llCollisionSound("", 0.0); llSetSitText("Drive"); llSitTarget(<0.0,-0.0,-0.1>, ZERO_ROTATION); llStopSound();
llSetTimerEvent(0.0); // llSitTarget(<0.1, 0.35, 0.6>, <0,-0.2,0,1>); //buggy llSetCameraEyeOffset(<-5.0, 0.0, 2.5>); llSetCameraAtOffset(<0.0, 0.0, 1.0>);
// remove all flags llRemoveVehicleFlags(-1); llSetStatus(STATUS_PHYSICS, FALSE); llSetStatus(STATUS_PHANTOM, TRUE); llSetBuoyancy(1); //floats llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE); //Kick off notecard reader m_dataRequestID = llGetNotecardLine(m_strNotecard, m_lineCounter); } //**************************************************************************** on_rez(integer startPram){ llResetScript(); } //**************************************************************************** dataserver(key queryid, string data) { //Check to make sure this is the request we are making. //Remember that when data comes back from the dataserver, //it goes to *all* scripts in your prim. //So you have to make sure this is the data you want, and //not data coming from some other script. if(m_dataRequestID == queryid) { if(data != EOF){ UseCommand(data); //feed the notecard to the message processor m_lineCounter++; m_dataRequestID = llGetNotecardLine(m_strNotecard, m_lineCounter); } } }//dataserver //**************************************************************************** changed(integer change) { if (change & CHANGED_LINK) { key agent = llAvatarOnSitTarget(); if (agent) { if (agent != llGetOwner()) { llSay(0, "You aren't the owner"); llUnSit(agent); llPushObject(agent, <0,0,100>, ZERO_VECTOR, FALSE); } else { // You sit and are owner so get controls llSetStatus(STATUS_PHANTOM, FALSE); llSetStatus(STATUS_PHYSICS, TRUE); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE); llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE); llRequestPermissions(agent,PERMISSION_TAKE_CONTROLS); //timer is turned on after premissions are ok } } else { // You stand so car stops // llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", NULL_KEY); llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE); llSetStatus(STATUS_PHYSICS, FALSE); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, FALSE); llSetStatus(STATUS_PHANTOM, TRUE); llReleaseControls(); // llStopSound(); llSetTimerEvent(0.0); llSensorRemove(); } }else if (change & CHANGED_INVENTORY) { llResetScript(); //re read notecard }; //if }//changed //**************************************************************************** run_time_permissions(integer perm) { if (perm) { // Take these controls and lets go llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_UP | CONTROL_DOWN, TRUE, FALSE);
m_DesiredSpeed=0; m_WheelPos = 0; // Right / left UpdateStatus(); m_RoadValid = FALSE; m_Scanning = TRUE; // llLoopSound("car idle",0.3); llSetTimerEvent(0.5); llSensorRepeat("",NULL_KEY,PASSIVE|ACTIVE,12,PI,2.3);
} } // //**************************************************************************** no_sensor(){ //m_Detected = 0; } sensor(integer num_detected){ //m_Detected = num_detected; vector MyPos = llGetPos(); integer i; float d; vector p; float MinDistance = 96; //find nearest integer UseIndex = -1; for (i=0; i < num_detected ; ++i){ string name = llDetectedName(i); if (llGetSubString(name,0,9) == "PublicRoad"){ p = llDetectedPos(i); d = llVecDist(p,MyPos); //get distance if (d < MinDistance){ key IdxKey = llDetectedKey(UseIndex); // integer lane = 0;//(integer)llGetObjectDesc(IdxKey); // if (lane == m_Lane){ UseIndex = i; MinDistance = d; // }; }; };//name };//for if (UseIndex != -1) { key IdxKey = llDetectedKey(UseIndex); if (m_DetectedKey != IdxKey){ m_DetectedKey = IdxKey; string nextName = llDetectedName(UseIndex); UseRoadName(nextName); if (m_RoadValid) { // llOwnerSay(nextName); llSensorRemove(); m_Scanning = FALSE; }; }; }else{ //m_Detected = 0; //might as well be zero }; // vector m_TargetPos; // rotation m_TargetRot; } //sensor //**************************************************************************** control(key id, integer level, integer edge) {
if(level & CONTROL_FWD) { // Set cruising speed faster if(m_DesiredSpeed < 10) //limit forward speed { m_DesiredSpeed +=1; UpdateStatus(); } } if(level & CONTROL_BACK) { // Set cruising speed slower if(m_DesiredSpeed > 0) //limit reverse speed { m_DesiredSpeed -=1; UpdateStatus(); } } if((level & CONTROL_FWD) && (level & CONTROL_BACK)) { // Forwards and Backwards <-- Brakes or stops // llMessageLinked(LINK_ALL_CHILDREN, 0, "brake", NULL_KEY); m_DesiredSpeed=0; UpdateStatus(); } if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT)) { m_WheelPos += 1; // Turn right UpdateStatus(); } if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT)) { m_WheelPos -= 1 ; // Turn left UpdateStatus(); } if(level & CONTROL_UP) { // add features for when you press up } if(level & CONTROL_DOWN) { // Added feature for when you press down } } //**************************************************************************** timer() {
//where are we vector MyPos = llGetPos(); //current sim position vector curVel = llGetVel(); //how fast are we moving rotation CurRot = llGetRot(); // current rotation vector RotVel = llGetOmega();//rotational velocity in radians/second float MyMass = llGetMass(); vector Force = <0.0,0.0,0.0>; //output vector Torque = <0.0,0.0,0.0>; if (m_RoadValid == TRUE) {
//Adjust for vechical size and base prim rotation // //To do!!! //movement vector v2Next = m_TargetPos - MyPos; //point at target if (llVecMag(v2Next) > 1.0){ //below 1m then dampen to stop v2Next = llVecNorm(v2Next); //normilze directon }; Force = v2Next * m_DesiredSpeed; Force -= curVel; // remove current speed //Force.z += -0.98; //make gravity again, but in local direction. Force *= MyMass; Force *= .5; // Time constant of velocity loop //Rotation rotation TargetRot; if (m_UseRotation) { TargetRot = m_TargetRot; }else{ //use vector twards target pos //Z up TargetRot = ZERO_ROTATION; //To Do!!! }; //compare to current rotation newRot = CurRot * TargetRot; // compute global rotation //llSetRot(new_rot); // orient the object accordingly vector RotVect = llRot2Euler(newRot) ; //convert to angle in radians m_RotVect = RotVect; //test //RotVect = RotVect * 5.0; //speed Torque = -RotVect; //oposite direction of where we are // Torque.x = 0.0; // Torque.y = 0.0; // Torque.z = PI; //one rotation per second test Torque -= RotVel; //remove current speed
// Torque *= MyMass; // Torque = Torque * .9; //dampen rotational speed //----------------- //next road prim ? if ((m_DesiredSpeed > 2 ) && (llVecMag(v2Next) < 2.0)){ //get next string nextName = llKey2Name(m_TargetKey); // llOwnerSay(nextName); UseRoadName(nextName); }; }else{ //road valid Force = -curVel; // remove current speed //Force.z += -0.98; //make gravity again, but in local direction. Force *= MyMass; Force *= .7; //dampen }; //road detected llApplyImpulse(Force,FALSE) ; llApplyRotationalImpulse(Torque, FALSE); //display if (m_WheelPos != 0){ m_WheelPos =0; // UpdateStatus(); }; UpdateStatus(); } //timer }//state
|
|
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
|
01-15-2007 12:14
Any particular reason you decided not to make them vehicles?
|
|
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
|
01-15-2007 12:41
From: Arachnid Baxter Any particular reason you decided not to make them vehicles? It's very hard to make an AI that can control a true Vehicle in SL. I've got one such AI on the back burner. The biggest pit-falls are knowing when to start and stop turning. Accelleration is difficult as well, but I have a routine which works fairly well for the linear movement. I haven't experimented with 3d movement (planes), but I'd imagine that the height element would need to be based along similar logic gates as the turning routine. In general it's much easier to work with a llMoveToTarget() "vehicle" for set waypoints than it is to have a true vehicle going from point A to point B.
_____________________
My SLExchange shopTypos 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.
|
|
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
|
01-15-2007 12:50
Unfortunately, I'm building 'birds' (or something a lot like them, anyway), and a direct move-to-point style motion would look rather unrealistic. Though I may simply have to start from there and try and improve it later. :/
|
|
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
|
01-15-2007 14:29
Perfect! Thanks!
|