![]() | |
| Figure 1: Cars in Second Life: Despite being unnecessary for travel, vehicles of all types are still popular in Second Life. |
![]() | |
| Figure 2: The Car Example: Although it may not be pretty, this wagon-like car uses the same basic script as a more attractive vehicle. |
Selecting Car Materials
The default material type for Second Life is wood. Unless the object is going to move, the material type does not really matter. Most builders simply leave the material type set to the default wood material. Probably 95 percent of the Second Life world is made of wood. You can select the "edit" option from a prim's menu to set the material type.
Here's where things get interesting.
The material you choose for the tires is very important. Any part of the vehicle that comes into contact with the ground must have its material specifically set. Second Life supports the following material types: stone, metal, glass, wood, flesh, plastic, and rubber. Really, all that a material type specifies is the mass and friction of an object.
It may seem logical that the wheels should be made from rubber, but rubber is actually a bad choice for tires in Second Life, because it has the most friction of any material. In Second Life's primitive physics system, the wheels do not actually "turn" to allow the car to move. A car with square tires could move just as easily. Think of the rubber tires as coming into contact with the ground, and the car being pushed with the parking brake on. In real life, such a car would hop along the ground in a bumpy and uncomfortable way. And if you choose rubber for your tire material type, your car will also bump along the ground, as the vehicle force overcomes the rubber resistance.
Instead of rubber, almost all land vehicles in Second Life use glass for their tire material. Glass has the least amount of resistance, so it makes sense as a wheel material type. Durability is not an issue. The glass tires will not shatter.
Understanding the Car Script
After building the simple car, you can script it. The car script begins by defining some constants that define how the car will operate. Of course Linden Scripting Language does not support "true constants." The values below could be changed, but the car script only reads their values. For your convenience, you can download the complete script or view it in Listing 1. Here are the constants that begin the script:
//Power used to go forward (1 to 30)
float forward_power = 15;
//Power used to go in reverse (-1 to -30)
float reverse_power = -15;
//How sharply the vehicle turns. Less is more sharply. (.1 to 10)
float turning_ratio = 2.0;
//Sit message
string sit_message = "Ride";
//Not owner message
string not_owner_message =
"You are not the owner of this vehicle ...";
You can change the preceding values to affect the car's handling, making it faster or slower, or affecting its turning ability. default
{
state_entry()
{
First, the script changes the "sit text." This causes the option to enter the car to be "ride" rather than the default "sit" in the Second Life menu system. Additionally, the script defines a sit target for the avatar. This prevents the avatar from sitting "inside" the seat, rather than on top of it: llSetSitText(sit_message);
llSitTarget(<0.2,0,0.45>, ZERO_ROTATION );
The SL "camera" follows the car automatically, just as the camera automatically follows avatars. However, for the car, it's better to move the camera 5 meters above and 8 meters behind the car. This provides both a good view of the car, and the area around it: llSetCameraEyeOffset(<-8, 0.0, 5.0>);
llSetCameraAtOffset(<1.0, 0.0, 2.0>);
The car uses two sounds, playing the car_start sound when the car starts up, and the car_run sound in a loop as the car runs: llPreloadSound("car_start");
llPreloadSound("car_run");
Second Life vehicles move using two motors. The "linear motor" moves the vehicle forward or backward. The "angular motor" turns the car about any of the three axes. You define these motors by setting vehicle parameters. //car
llSetVehicleType(VEHICLE_TYPE_CAR);
Here are some other vehicle parameter settings that you'll need: llSetVehicleFloatParam(
VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.2);
A value of 0.8 specifies a linear deflection power of 80 percent. The value specifies the effort it takes for the car to change its linear velocity: llSetVehicleFloatParam(
VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.80);
Because real-car directional changes are not instantaneous, it takes this car one tenth of a second for both linear and angular deflection to kick in: llSetVehicleFloatParam(
VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 0.10);
llSetVehicleFloatParam(
VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.10);
It also takes one second for the linear motor to reach full power: llSetVehicleFloatParam(
VEHICLE_LINEAR_MOTOR_TIMESCALE, 1.0);
The linear motor power drops off in one fifth of a second, meaning the car will not coast well: llSetVehicleFloatParam(
VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 0.2);
Remember that there are two motors. The angular motor also reaches full power in one tenth of a second: llSetVehicleFloatParam(
VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1);
But the angular motor power drops off in one half of a second. The car will stop turning fairly quickly when the user lets up on the control: llSetVehicleFloatParam(
VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.5);
Friction affects the car only in the y-coordinate, which is how the car moves forward and backwards. The car can fall or turn quickly: llSetVehicleVectorParam(
VEHICLE_LINEAR_FRICTION_TIMESCALE,
<1000.0, 2.0, 1000.0>);
The car rotates fairly easily in the z-coordinate, but less easily in the x and y coordinates: llSetVehicleVectorParam(
VEHICLE_ANGULAR_FRICTION_TIMESCALE,
<10.0, 10.0, 1000.0>);
A car should (preferably) always stay right side up. The vertical attraction setting allows this: llSetVehicleFloatParam(
VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.50);
llSetVehicleFloatParam(
VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 0.50);
These values work well for a car. However, if you were building a boat or helicopter they would need to be considerably different.
Starting and Stopping the Car
Second Life calls the changed event handler whenever an avatar enters (sits in) or leaves (stands up from) the car. The changed event handler must accommodate three basic scenarios: the owner sitting down, a non-owner sitting down, or the owner standing:
changed(integer change)
{
The changed event handler begins by checking to see if someone has sat down: if (change & CHANGED_LINK)
{
If someone did sit down, make sure it's the vehicle's owner. key agent = llAvatarOnSitTarget();
if (agent)
{
If the avatar sitting down is not the owner, inform them that only the owner can drive the car, and force the avatar to stand up: if (agent != llGetOwner())
{
llSay(0, not_owner_message);
llUnSit(agent);
llPushObject(agent, <0,0,50>,
ZERO_VECTOR, FALSE);
}
else
{
Otherwise, the avatar is the owner, so play the car_start sound: llTriggerSound("car_start",1);
After waiting for the sound to play, you need to turn physics on. Objects with physics enabled can fall and have force applied to them. Most objects in SL are non-physical: llSleep(.4);
llSetStatus(STATUS_PHYSICS, TRUE);
llSleep(.1);
Finally, you must request permission to take the avatar's controls. When the avatar attempts to move, the car (your script) will receive those inputs: llRequestPermissions(agent,
PERMISSION_TRIGGER_ANIMATION |
PERMISSION_TAKE_CONTROLS);
llLoopSound("car_run",1);
}
}
else
{
When the driver stands up, stop the sound, turn off physics, and release the controls. The llTargetOmega call stops any car movement that might be in progress: llStopSound();
llSetStatus(STATUS_PHYSICS, FALSE);
llSleep(.4);
llReleaseControls();
llTargetOmega(<0,0,0>,PI,0);
llResetScript();
}
}
}
Controlling the Car control(key id, integer level, integer edge)
{
integer reverse=1;
vector angular_motor;
Next, the script obtains the current speed of the car, which it uses when turning. Cars do not turn when they are not in motion: //get current speed
vector vel = llGetVel();
float speed = llVecMag(vel);
Next, the script checks each of the relevant controls, starting with the Forward control. When the user presses Forward, the script uses the linear motor to apply force to move the car forward. Also note that the script sets the reverse variable to one: //car controls
if(level & CONTROL_FWD)
{
llSetVehicleVectorParam(
VEHICLE_LINEAR_MOTOR_DIRECTION, <forward_power,0,0>);
reverse=1;
}
If the user presses Back, then the script applies power in the opposite direction, and stores the fact that the car is in reverse by setting the reverse variable to -1: if(level & CONTROL_BACK)
{
llSetVehicleVectorParam(
VEHICLE_LINEAR_MOTOR_DIRECTION, <reverse_power,0,0>);
reverse = -1;
}
For a right or left turn, you use the angular motor to rotate the car in the z-coordinate by the specified angle, being sure to take into account whether the car is in reverse: if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
angular_motor.z -= speed /
turning_ratio * reverse;
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
angular_motor.z += speed /
turning_ratio * reverse;
}
Now you can set the angular motor:
llSetVehicleVectorParam(
VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);
}
![]() | |
| Figure 3. Car in Motion: Here's the author's avatar driving the car. |
| DevX is a division of Jupitermedia Corporation © Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices |