Script of first car with acceleration curve and friction by James Argonaut. Written on 6/10/03 and featured 2 months later in the 2003 Olive Death Race.
float theta_func() { if (speed < 1) return 0.02; if (speed < 4) return 0.1; if (speed < 6) return .4; if (speed < 10) return .6; if (speed < 15) return .5; if (speed < 20) return .5; if (speed < 25) return .4; return .3; } float power_curve() { if (speed < 1) return 15.0; if (speed < 4) return 15.0; if (speed < 6) return 15.0; if (speed < 10) return 15.0; if (speed < 15) return 10.0; if (speed < 20) return 4.0; if (speed < 30) return 2.0; return 2.0; } float THROTTLE = 1.2; float STEERING = 1; float TIMER = .05; float ANGULAR_TAU = .1; // decrease for faster turn float ANGULAR_DAMPING = 3; // not sure what this should be yet float THETA_INCREMENT = 0.05; // increase for bigger turn response //float C_FRICTION = 40; //float FRONTAL_AREA = 20; //float TOT_FRICTION; float mass; float speed; vector velocity; float turn; float counter = 0; float brake = 1; // linear constants integer a = 10; integer LEVELS = 0; // we'll set this later // global variables vector gTargetPos; float gTargetTheta; key gToucher; default { state_entry() { llSay(0,"car starting"); llSetStatus(STATUS_PHYSICS, FALSE); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y, FALSE); llCollisionFilter("", "", TRUE); llStopSound(); mass = llGetMass(); llSleep(0.1); //SetHoverHeight(1,1,10); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z , TRUE); llMoveToTarget(llGetPos() + <0,0,1>, 0); llRotLookAt(llGetRot(), 0, 0); LEVELS = CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN | CONTROL_LEFT | CONTROL_RIGHT; } touch_start(integer total_number) { llStopSound(); gToucher = llDetectedKey(0); integer perm = llGetPermissions(); if (perm) { llReleaseControls(); } else { state StateDriving; } } } state StateDriving { state_entry() { llSetTimerEvent(TIMER); brake = 1; llSetStatus(STATUS_PHYSICS, TRUE); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z , TRUE); llWhisper(0, "StateDriving"); //llSetHoverHeight(a,1,.4); llRequestPermissions(gToucher, PERMISSION_TAKE_CONTROLS); //llMoveToTarget(llGetPos(), LINEAR_TAU); llRotLookAt(llGetRot(), ANGULAR_TAU, 1.0); } touch_start(integer total_number) { llWhisper(0, "Touched."); integer perm = llGetPermissions(); if (perm) { llReleaseControls(); } state default; } run_time_permissions(integer perm) { if (perm == PERMISSION_TAKE_CONTROLS) { llTakeControls(LEVELS, TRUE, FALSE); } else { state default; } } control(key driver, integer levels, integer edges) { //llWhisper(0, "l = " + (string)levels + " e = " + (string)edges); // linear control //llSetHoverHeight(a,1,.4); integer nudge = FALSE; float direction = 0; gTargetTheta *= theta_func(); if (levels & CONTROL_FWD) { direction = 1; brake = 0; } if (levels & CONTROL_BACK) { direction = -.1; brake = 5; gTargetTheta *= 2; } if (levels & CONTROL_LEFT) { } if (levels & CONTROL_RIGHT) { } if (levels & CONTROL_UP) { a +=1; } if (levels & CONTROL_DOWN) { a-=1; } // angular control if (levels & CONTROL_ROT_LEFT) { if (gTargetTheta < 0) { gTargetTheta = 0; } else { gTargetTheta += THETA_INCREMENT; } nudge = TRUE; } if (levels & CONTROL_ROT_RIGHT) { if (gTargetTheta > 0) { gTargetTheta = 0; } else { gTargetTheta -= THETA_INCREMENT; } nudge = TRUE; } if (direction) { //sound control if (speed < 24) { llLoopSound("car accel", .4);} else { llLoopSound("car go",.4); } //applies forward boost // llSay( 0, (string) power + " " + (string) direction + " " + (string) mass + (string) power_curve() + (string) theta_func() ); llApplyImpulse( <1,0,0> * direction * mass * power_curve()* THROTTLE , 1); } if (direction == 0) {llLoopSound("geardown", .4); } if (nudge) { // angular motion -- we compute the raw quaternion about z-axis counter++; float st = 0.5 * llSin(gTargetTheta*STEERING); float ct = 0.5 * llCos(gTargetTheta*STEERING); rotation rot = <0,0,st, ct> * llGetRot(); llRotLookAt(rot, ANGULAR_TAU, ANGULAR_DAMPING); } else {counter = 0;} } land_collision(vector position) { //llApplyImpulse( <0,0, .5> * mass, 1 ); } collision (integer total_number) { // llWhisper( 0, "collision 2"); //llSetHoverHeight(4,1,.2); } timer() //side ways supression { vector pos = llGetPos(); if (llGround(<0,0,0>) > (pos.z - 3) ) { velocity = llGetVel(); speed = llVecMag(velocity); float l_speed = llRot2Left( llGetRot() ) * velocity; float f_speed = llRot2Fwd( llGetRot() ) * velocity; if ( l_speed > 8 || (brake > 1 && speed > 8) ) llTriggerSound("tires burn",10); if (speed < 1) llStopSound(); if (counter * speed > 100) { l_speed /= 4; brake = 2; } if (speed > 4) brake = 2; f_speed *= brake; llApplyImpulse( <0,-1,0> * l_speed * mass *.8, 1 ); llApplyImpulse( <-1,0,0> * f_speed * mass *.05, 1 ); } } }