1. Introduction 导论
2. Getting Started 入门须知
2.1. Hello Avatar 例程”你好,Avatar”
2.1.1. Creating the sc
2.1.2. Default State 默认状态
2.1.3. Functions 函数
2.1.4. Touch Event 事件驱动
2.1.5. Try it Out试用
2.2. Using The Built-In Editor建模固定编辑器试用办法
2.3. Using Alternative Editors其他编辑器使用办法
3. Basics 基础教程
3.1. Comments 注释
3.2. Arithmetic Operations 算法应用
3.2.1. Assignment 任务
3.2.2. Hexadecimal Entry 十六进制录入
3.2.3. Binary Arithmetic Operators 二进制算法设置
3.2.4. Boolean Operators 布尔数据设置
3.2.5. Bitwise Operators位操作符设置
3.3. Types 分类
3.3.1. Type Conversion类型转换
3.4. Global Functions 引用全局变量时的Global文件设置
3.5. Global Variables 全局变量
3.6. Local Variables Local变量
4. Flow Control 流程控制
4.1. Conditional Statements 条件语言
4.2. Loop Constructs 循环结构
4.2.1. for loop for循环
4.2.2. do-while loop do-while循环
4.2.3. while loop while循环
4.3. Jumps 跳转
4.4. State Change状态更改
5. States 状态
5.1. state_entry() 状态录入
5.2. state_exit() 状态导出
5.3. States vs. Global variables状态VS全局变量
6. Math 数学
6.1. Tables of Functions数学函数列表
7. Strings 线性代数
7.1. Tables of Functions线性代数函数列表
8. Lists 清单
8.1. Tables of Functions列表函数列表
9. Communication 通信
9.1. Tables of Functions通信函数列表
10. Inventory 清单
10.1. Tables of Functions函数列表
11. Vehicles 交通工具
11.1. Overview 总论
11.2. Warnings 警告
11.3. Definitions 定义
11.4. Setting the Vehicle Type 设定交通工具类
11.5. Linear and Angular Deflection 角、线偏转
11.6. Moving and Steering the Vehicle 交通工具的移动和操作
11.7. The Linear Motor 线发动机
11.8. The Angular Motor 角发动机
11.9. Using the Camera to Steer 视角显示的实现控制
11.10. The Vertical Attractor引力
11.11. Banking 倾斜
11.12. Friction Timescales 摩擦力时标
11.13. Buoyancy 漂浮
11.14. Hover 盘旋
11.15. Reference Frame参考坐标
A. Linden Library Functions 林登函数库函数
Chapter 1. Introduction
The Linden sc
Multiple sc
The text of the sc
This tutorial introduces the reader to the basic features of LSL, how to edit and apply your sc
LSL语言简单有效,易学,功能强大.给第二生命中的对象赋予生命。
它与C/Java类型语言语法相似, 每个语法对应一个隐型状态机。
多重脚本可以同时赋予一个,支持功能单一、没有风格的脚本的扩展,从而一段语法执行一个具体的函数,也允许函数绑定实现新的行为.
LSL语言程序段是可执行代码,类似Java,直接在虚拟机或者仿真机上运行.每一个程序段接收分配到仿真机全部时间上的一个时间片. 因此带有多条执行指令的一个仿真机单条指令执行时间更短,而不会减低性能.而且,每条指令在其内存块内执行,防止指令写入被保护的模拟内存或者其它程序段内,使程序段很难进入仿真机.
这个教程给出了LSL的基本功能,比如如何编辑和应用指令,如何为一个标准的linden常量,事件以及函数建立参数等.
Chapter 2. Getting Started
You’re probably wondering what you can do with LSL, and how quickly you can do it. We’ll start with some simple examples, dissect them, and introduce you the sc
你可能在想要多久才会用这个LSL,我们从最简单例子开始吧,分解它们,从而介绍如何编程.
2.1. Hello Avatar 致虚拟公民
Continuing a long tradition of getting started by looking at a sc
• Creating a basic sc
• sc
• Calling functions
• sc
• Applying a sc
我们都知道任何程序语言开始都是”hello”.我们这里也是如此.虽然这个”Hello”的小程序不是特别有用,但是我们可以知道:
创建一条指令
指令状态
调用函数
指令事件
把指令应用到对象上
________________________________________
2.1.1. Creating the sc
Start by opening your inventory and selecting ‘Create|New sc
这样我们就已经创建了一条新的空指令: ‘New sc
default
{
state_entry()
{
llSay(0, "Hello, Avatar!");
}
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
}
A casual inspection of this sc
这个小程序的级联格式会在某种状态下,在屏幕显示’Hello, Avatar!’,当触摸它的时候,屏幕显示’Touched.’.因为这也许是你第一次看到一个程序指令,我们来分解这段小指令,一个小段一个小段的解释.
________________________________________
2.1.2. Default State
default
{
…
}
All LSL sc
每段LSL指令都是一个带有一到多种状态的简单隐型状态机.每一个程序都有默认状态,如果只有一种状态的话,那就一定是默认状态. 当一个程序第一次打开或者reset后,它都会是默认状态.
The default state is declared by placing the default at the root level of the document, and marking the beginning with an open brace ‘{’ and ending with a close brace ‘}’. Because of it’s privileged status, you do not declare that it is fact a state like you normally would with other states.
这种默认状态取代跟目录文件下的状态,并且在程序段开始以
{
…
}
形式标明.这和其它状态下必须特别指明.
Every time you enter a state, the sc
Every time you enter a state, the sc
每次输入一种状态,程序引擎会自动调用状态输入函数state_entry()并执行指令. 一个状态存在, ,程序引擎会在调用一下一个状态输入函数state_entry之前,自动调用状态存在处理函数state_exit(). 在例子中,我们在状态输入函数state_entry()中调用函数llSay(), 而不会去定义状态存在处理函数state_exit(). 状态输入器和存在处理函数可以非常方便初始化状态以及清除具体的状态数据,比如事件”听”的撤回.
You can read more about the default state, and how to create and utilize other states in the states chapter.
在”状态”一章中,你可以了解更多自动状态以及创建和应用其它状态.
________________________________________
2.1.3. Functions 函数
The language comes with well over 200 built in functionswhich allow sc
LSL语言有200中内置函数,允许指令和对象在环境中互相影响. 所有这些内置函数都以’ll’开始.比如调用函数llSay()两次,就可以在特定的信道中,调出文本.
The example calls the llSay() function twice, which is used to emit text on the specified channel.
指令如下:
llSay( integer channel string text );
Say text on channel. Channel 0 is the public chat channel that all avatars see as chat text. Channels 1 to 2,147,483,648 are private channels that aren’t sent to avatars but other sc
llSay( integer channel string text );
Say text on channel. Channel 0 is the public chat channel that all avatars see as chat text. Channels 1 to 2,147,483,648 are private channels that aren’t sent to avatars but other sc
以文本信道为例.信道0是公民聊天的文本框,信道1,2.147,483到648是私人信道,不对公民开放,但是其它程序段可以听取.
You can define your own functions as long as the name does not conflict with a reserved word, built in constant, or built in function.
你可以定义你函数长度,只要名字不是LSL语言中专用函数语言以及内置常量,嵌入函数
________________________________________
2.1.4. Touch Event 触摸事件
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
There are many eventsthat can be detected in your sc
许多事件可以通过你的程序宣布一个处理器来监测.在通过用户界面触摸到对象的时候, 函数touch_start()会执行.
________________________________________
2.1.5. Try it Out 测试
Now that we have seen the default sc
我们已经知道默认程序指令.现在让我们看看指令运行.点击”save”保存程序.在保存过程中,编辑器会保存程序文本并编译程序指令到执行指令中保存.当你在预览窗口,看到” Compile successful!”,编译和保存工作都做好了.
To test the sc
要测试程序,你需要在把它应用到一个对象中 . 在world里,在主视窗里,点击”create”. 当那个小棒棒”wand”出现时,可以点击world,而创建一个小的原始世界.在这个新的原始世界里,一个对象出现时,你可以拖到你新创建的程序到这个对象身上,这样我们创建的程序就可以运行了.
Soon after dragging the sc
当你把程序拖到对象身上,你可以看到对象说: Hello Avatar!
Make sure the touch event is working by clickingon the ob
当在点击对象时候,在聊天历史记录信道里,会出现” Touched”
2.2. Using The Built-In Editor 使用内置编辑器
The built in editor comes with most of the typical features you would expect from a basic text editor. Highlight text with the mouse, or by holding down the shift key while using the arrow keys. You can cut, copy, paste, and delete your selection using the ‘Edit’ pull down menu or by pressing the usual shortcut key.
在内置编辑器中,有一个基本的文本编辑器拥有的大部分功能.用鼠标选中文本,或者在利用方向键+”shift”来选中文本,然后 Ctrl+X, Ctrl+C,Ctrl+V,用其它的通常快捷键,或者在’Edit’下拉菜单中, 你可以剪切.拷贝.粘贴和删除你所选的文本.
________________________________________
2.3. Using Alternative Editors 使用可选文本
Since the built-in editor supports pasting text from the clipboard, you can employ a different editor to edit your sc
内置编辑器支持从粘贴板粘贴文本功能,我们就可以利用其它编辑器(如office系列word excel之类)来编辑指令,然后把他们拷贝到secondlife world里.
Chapter 3. Basics基础
Now that we have seen a very simple sc
既然我们已经看见一个简单程序的运行了,现在就看看如何自己编程吧.下面这些工具用来构架基本程序块从而编程,并且会在实际中应用到.
________________________________________
3.1. Comments 注释
Commenting your sc
给你指令行添加注释是个好的习惯,会帮助你更新和更改指令行,尤其在你想吧某个部分添加到其它程序中去的时候(这个真的重要.因为自己编的程序.过段时间再看,自己不一定记得其功能的.) 除非这个意思非常明显,否则一定加注释:
• at the start of the sc
• before every global variable to describe what it holds
• before every global function to describe what it does
• sprinkled through your sc
• 在指令行的开始解释这个程序段的目的
• 在全局变量嵌加描述指明这个全局变量针对哪一段程序是全局的
• 在全局函数前加描述,表明其针对功能
• 在你自己一眼看不出代码功能的地方,加些注释.
LSL uses Java/C++ st
LSL和Java/C++一样,使用单行注释.
// This sc
//这个指令用来固定一个旋转的对象
// g_is_rotating stores the current state of the rotation. TRUE is
// rotating, FALSE otherwise.
//函数g_is_rotating 保存旋转现在的状态.在Ture的时候,是旋转,false时候则固定.
integer g_is_rotating = FALSE;
default
{
// toggle state during the touch handler
touch(integer num)
{
if(g_is_rotating)
{
// turn off rotation
llTargetOmega(<0>, 0, 0);
g_is_rotating = FALSE;
}
else
{
// rotate around the positive z axis - up.
llTargetOmega(<0>, 4, 1);
g_is_rotating = TRUE;
}
}
}
________________________________________
3.2. Arithmetic Operations 算术运算
这一节请参考任何一本参考C语言中文教材
Most of the common arithmetic operations are supported in lsl, and follow the C/Java syntax.
同C/Java一样,LSL语言支持大部分算术运算________________________________________
3.2.1. Assignment “并”
The most common arithmetic operation is assignment, denoted with the ‘=’ sign. Loosely translated, it means, take what you find on the right hand side of the equal sign and assign it to the left hand side. Any ex
大部分算术运算都是”并”,用’='表示.简单地说,任何表达式产生一个基本类,把表达式右边的相同的标识赋予左边.而左边只能用普通变量.
All basic types support assignment ‘=’, equality ‘==’ and inequality ‘!=’ operators.
所有基本类都支持这几个运算符号:用’='表示”并”, ‘==’ 表示“等于”;用’!=’表示”不等于”
// variables to hold a information about the target
//以下这3行是建立一个变量,在一个目标上,表达一定信息的变量
key g_target;
vector g_target_postion;
float g_target_distance;
// function that demonstrates assignment
//下面是一个执行”并”运算功能的函数
set_globals(key target, vector pos)
{
g_target = target;
g_target_position = pos;
// assignment from the return value of a function
vector my_pos = llGetPos();
g_target_distance = llVecDist(g_target_position, my_pos);
}
________________________________________
3.2.2. Hexadecimal Entry 十六进制输入法
Integers may be entered in hex form (e.g. 0xffff). For example:
整数会以十六进制形式输入,例如:
integer Mask = 0xff; // Equivalent to integer Mask = 255;
integer Bit = 0×0100 // Equivalent to integer Mask = 256;
________________________________________
3.2.3. Binary Arithmetic Operators 二进制算术运算符号
Binary arithmetic operators behave like a function call that accepts two parameters of the same type, and then return that type; however, the syntax is slightly different.
二进制算术运算类似调用同一个类的两个参数,然后返回那个类,但是,语法有些不同.
Table 3-1. Binary Arithmetic Operators
Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo (remainder)
^ Exclusive OR
<
Where noted, each type may have a special interpretation of a binary arithmetic operator. See the lsl typessection for more details.
每一个类可能有一个具体的二进制运算符号.请参照类lsl
________________________________________
3.2.4. Boolean Operators 布尔数据设置
Table 3-2. Boolean Operators布尔运算符号
Operator Meaning
左边的数大于右边的数,运算结果为真
&& Operator returns TRUE if the left hand side and right hand side are both true.
左右两个结果都是真的时候,这个运算结果为真
|| Operator returns TRUE if either the left hand or right hand side are true. 或运算.左或者右,任一为真.则为真.
! Unary operator returns the logical negation of the ex
________________________________________
3.2.5. Bitwise Operators 位操作符号
Table 3-3. Bitwise Operators
Operator Meaning
& Returns the bitwise and of the left and right hand side.两个bit相”与”
| Returns the bitwise or of the left and right hand side.左右两个bit相”或”
~ Unary operator returns the bitwise complement of the ex
这个结果返回表达式右边bit的”补”
3.3. Types 类
Variables, return values, and parameters have type information. LSL provides a small set of basic types that are used throughout the language.
变量,返回值以及参数,都是类.LSL提供一些基本类.
LSL Types
integer 整量
A signed, 32-bit integer value with valid range from -2147483648 to 2147483647.
float 浮量 参考C语言中文教材
An IEEE 32-bit floating point value with values ranging from 1.175494351E-38 to 3.402823466E+38.
key 键
A unique identifier that can be used to reference ob
vector 矢量
3 floats that are used together as a single item. A vector can be used to represent a 3 dimensional position, direction, velocity, force, impulse, or a color. Each component can be accessed via ‘.x’, ‘.y’, and ‘.z’.
Table 3-4. Vector Arithmetic Operators 算术矢量
Operator Meaning
+ Add two vectors together把两个矢量相加
- Subtract one vector from another两个矢量相减
* Vector dot product 点矢量
% Vector cross product 相交矢量
rotation
4 floats that are used together as a single item to represent a rotation. This data is interpreted as a quaternion. Each component can be accessed via ‘.x’, ‘.y’, ‘.z’, and ‘.s’.
4个浮变量一起可以代表一个旋转.这个数据通过一个4元数组表示.每个元素通过’.x’, ‘.y’, ‘.z’, and ‘.s’来访问.
Table 3-5. Rotation Arithmetic Operators 旋转算术运算
Operator Meaning
+ Add two rotations together 两个旋转量相加
- Subtract one rotation from another两个旋转量相减
* Rotate the first rotation by the second把第一个旋转矢量选择第二个的”度”
/ Rotate the first rotation by the inverse of the second,把第一个选择量反向旋转第二个矢量的”度”
list
A heterogeneous list of the other data types. Lists are created via comma separated values of the other data types enclosed by ‘[’ and ‘]’.
其它类的异类历表,历表内部逗号隔开.见例子:
string StringVar = "Hello, Carbon Unit";
list MyList = [ 1234, ZERO_ROTATION, StringVar ];
Yields the list: [ 1234, <0>, "Hello, Carbon Unit" ]
Lists can be combined with other lists. For example:
历表之间可以捆绑.如:
MyList = 3.14159 + MyList;
Yields the list: [ 3.14159, 1234, <0>, "Hello, Carbon Unit" ]
得到历表: [ 3.14159, 1234, <0>, "Hello, Carbon Unit" ]
And similarly, 同样,
MyList = MyList + MyList;
Yields: [ 3.14159, 1234, <0>, "Hello, Carbon Unit", 3.14159, 1234, <0>, "Hello, Carbon Unit" ]
Library functions exist used to copy data from lists, sort lists, copy/remove sublists.
________________________________________
3.3.1. Type Conversion 类的转换
Type conversion can either occur implicitly or explicitly. Explicit type casts are accomplished using C syntax:
类可以明转换或者暗转换.明转换方法类似C 语法:
float foo_float = 1.0;
integer foo_int = (integer)foo_float;
________________________________________
3.3.1.1. Implicit Casting 暗转换
LSL only supports two implicit type casts: integer to float and string to key. Thus, any place you see a float specified you can supply an integer, and any place you see a key specified, you can supply a string.
LSL 语言只支持两种暗转换: 整量转浮量和串转键. 这样,当你在任何地方看到一个特定的浮量的时候,你可以提供一个整量.(因为你的整量会自动转为浮量,和你看到的目标自动匹配.所以叫暗转换,不需要编程实现.);同样,当你看到一个指定的”键”时候,你可以提供一个”串”.
________________________________________
3.3.1.2. Explicit Casting 明转换
LSL supports the following explicit casts:
LSL支持下列转换方式:
• Integer to String
• Float to Integer
• Float to String
• Vector to String
• Rotation to String
• Integer to List
• Float to List
• Key to List
• String to List
• Vector to List
• Rotation to List
• String to Integer
• String to Float
• String to Vector
• String to Rotation
________________________________________
3.4. Global Functions 全局函数
Global functions are also declared much like Java/C, with the exception that no ‘void’ return value exists. Instead, if no return value is needed, just don’t specify one:
全局函数声明更加象Java/C,没有”空”返回值.但是,如果”无返回值”需要时候,不要定义
make_physical_and_spin(vector torque)
{
// double the torque
vector double_torque = 2.0*torque;
llSetStatus(STATUS_PHYSICS, TRUE);
llApplyTorque(double_torque);
}
________________________________________
3.5. Global Variables全局变量
Global variables and functions are accessible from anywhere in the file. Global variables are declared much like Java or C, although only one declaration may be made per line:
全局变量和函数在文件中随处可见.全局变量声明也很象Java/C,虽然每一行只可以声明一个.(C 一行可以声明多个)
比如下面绿色字体声明一个矢量全局变量:
vector gStartPosition;
Global variables may also be initialized if desired, although uninitialized global and local variables are initialized to legal zero values:
全局变量可以按照需要初始化,而没有初始化的全局和本地变量会自动设置为0.
vector gStartPosition = <10>
________________________________________
3.6. Local Variables本地变量
Local variables are scoped below their declaration within the block of code they are declared in and may be declared within any block of code. Thus the following code is legal and will work like C:
本地变量在其声明的代码块内定义.可以在代码块任何部分声明.下面这段合法代码就类似C:
integer test_function()
{
// Test vector that we can use anywhere in the function
// 注释:测试我们在函数中任何地方可以用的矢量, vector test = <1>;是一个本地变量,对一下括号内所有代码都有效
vector test = <1>;
integer j;
for (j = 0; j < 10; j++)
{
// This vector is a different variable than the one declared above
// This IS NOT good coding practice
vector test =
}
// this test fails
if (test == <9>)
{
// never reached
}
}
Chapter 4. Flow Control 流控制
LSL comes with a complete complement of constructs meant to deal with conditional processing, looping, as well as simply jumping to a different point in the sc
在程序中,可以条件处理,环,以及直接跳到另一个点.
________________________________________
4.1. Conditional Statements 条件语句
The ‘if’ statement operates and has the same syntax as the Java/C version.
If条件语句和Java/C语句语法意思一样.这个不翻译了.找本C 基础看.
check_message(string message)
{
if(message == "open")
{
open();
}
else if(message == "close")
{
close();
}
else
{
llSay(0, "Unknown command: " + message);
}
}
The statements between the open and close curly brace are performed if the conditional inside the parentheses evaluates to a non-zero integer. Once a conditional is determined to be true (non-zero), no further processing of ‘else’ conditionals will be considered. The NULL_KEYconstant is counted as FALSE by conditional ex
There can be zero or more ‘else if’ statements, and an optional final ‘else’ to handle the case when none of the if statements evaluate to a non-zero integer.
The usual set of integer arithmetic and comparison operators are available.
// a function that accepts some information about its environment and
// determines the ‘best’ next step. This kind of code might be
// part of a simple box meant to move close to an agent and attach to
// them once near. This code sample relies on the standard linden
// library functions as well as two other methods not defined here.
assess_next_step(integer perm, integer attached, integer balance, float dist)
{
string msg;
if(!attached)
{
if((perm & PERMISSION_ATTACH) && (dist <10> 10.0) || ((dist > 20.0) && (balance > 1000)))
{
move_closer();
}
else
{
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
}
}
}
________________________________________
4.2. Loop Constructs 这个和C 完全相同,不翻译了.
Loops are a basic building block of most useful programming languages, and LSL offers the same loop constructs as found in Java or C.
________________________________________
4.2.1. for loop
A for loop is most useful for when you know how many times you need to iterate over an operation. Just like a Java or C for loop, the parentheses have three parts, the initializer, the continuation condition, and the increment. The loop continues while the middle term evaluates to true, and the increment step is performed at the end of every loop.
// move a non-physical block smoothly upward (positive z) the total
// distance specified divided into steps discrete moves.
move_up(float distance, integer steps)
{
float step_distance = distance / (float)steps;
vector offset = <0>;
vector ba
integer i;
for(i = 0; i
{
jump early_exit;
}
// make sure we’re roughly pointed toward the target.
// the calculation of max_cos_theta could be precomputed
// as a constant, but is manually computed here to
// illustrate the math.
float max_cos_theta = llCos(PI / 4.0);
vector toward_target = llVecNorm(target_pos - pos);
rotation rot = llGetRot();
vector fwd = llRot2Fwd(rot);
float cos_theta = toward_target * fwd;
if(cos_theta > max_cos_theta)
{
jump early_exit;
}
// at this point, we’ve done all the checks.
attach();
@early_exit;
}
________________________________________
4.4. State Change 状态改变 (此处恐龙不是很懂,需要进行程序调试几次实验后才可以明白.)
State change allow you to move through the lsl virtual machine’s flexible state machine by transitioning your sc
状态改变允许你在LSL虚拟机中保持可变状态,把指令在定义状态和默认状态间切换.把’state’这个词,放在程序段前,然后用(’{’ and ‘}’.)符号把事件指针括起来.然后通过语法: ’state
default
{
state_entry()
{
llSay(0, "I am in the default state");
llSetTimer(1.0);
}
//下面4行就是 ’state’,放程序段前,用(’{’ and ‘}’.)符号把事件指针括起来
timer()
{
state SpinState;
}
}
//例: 通过语法: ’state
state SpinState
{
state_entry()
{
llSay(0, "I am in SpinState!");
llTargetOmega(<0>, 4, 1.0);
llSetTimer(2.0);
}
timer()
{
state default;
}
state_exit()
{
llTargetOmega(<0>, 0, 0.0);
}
}
Chapter 5. States 状态
All sc
When state changes, all callback settings are retained and all pending events are cleared.
所有的程序都有个默认状态, 这是指令第一次运行开始的状态. 状态包含有LSL虚拟机激发的事件指针. 所有的状态都必须赋予一个事件指针.没有事件指针的状态是不存在的.
当状态改变时,所有的调用设置都被保存,所有暂停的事件都被清除.
________________________________________
5.1. state_entry() 状态输入函数
The state_entry event occurs whenever a new state is entered, including program start, and is always the first event handled. No data is passed to this event handler.
每一个状态输入时候,状态输入事件都会发生,其中包括程序开始,第一个事件指针开始,没有数据传入这个指针内.
You will usually want to set callbacks for things such as timers and sensor in the state_entry() callback of the state to put your ob
计算器和感应器需要在状态输入函数调用时设置好,以便对象适合于那种状态下使用.
Warning: It is a common mistake to assume that the state_entry() callback is called when you rez an ob
警告:通常错误是认为调用状态输入函数是调用库里 你rez的对象. 当derez一个对象入库的时候,程序现在状态被保存,所以在rez过程中,没有调用状态输入函数.在创建一个对象时,需要提供启动代码的话,可以创建一个全局函数,然后同时调用函数state_entry() 和the on_rez()
// global initialization function.全局初始函数
init()
{
// Set up a listen callback for whoever owns this ob
//设定一个听的调用,无论谁拥有这个对象时.
key owner = llGetOwner();
llListen(0, "", owner, "");
}
default
{
state_entry()
{
init();
}
on_rez(integer start_param)
{
init();
}
listen(integer channel, string name, key id, string message)
{
llSay(0, "Hi " + name + "! You own me.");
}
}
________________________________________
5.2. state_exit()状态存在函数
You will want to provide a state_exit()if you need to clean up any events that you have requested in the current state, but do not expect in the next state.
如果需要在当年状态下,清除事件,就可以用状态存在函数.而不用考虑下一个状态.
default
{
state_entry()
{
state TimerState;
}
}
state TimerState
{
state_entry()
{
// set a timer event for 5 seconds in the future.
llSetTimerEvent(5.0);
}
timer()
{
llSay(0, "timer");
state ListenState;
}
state_exit()
{
// turn off future timer events.
llSetTimerEvent(0.0);
}
}
integer g_listen_control;
state ListenState
{
state_entry()
{
// listen for anything on the public channel
g_listen_control = llListen(0, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message)
{
llSay(0, "listen");
state TimerState;
}
state_exit()
{
// turn off the listener
llListenRemove(g_listen_control);
}
}
The state_exit() handler is not called when an ob
状态存在函数不会在一个对象删除时候调用. 所有的调用.指针,声音等都会对象删除时候自动清除.
________________________________________
5.3. States vs. Global variables状态vs全局变量
A state and a set of global variables can serve the same purpose, and each can be expressed in terms of the other. In general, you should prefer the use of states over global variables since states allow you to immediately assume sc
一个状态和一套全局变量可以有同样效果,也可以互相转换.一般来说,最好用状态,而不是全局变量,因为状态允许马上设定程序状态而不用做比较.一个程序比较越少,它可以允许更通常的代码状态.
________________________________________
Chapter 6. Math 代数
6.1. Tables of Functions 函数表
Table 6-1. Trigonometry Functions
Function
llAbs
llAcos
llAsin
llAtan2
llCeil
llCos
llFabs
llFloor
llFrand
llPow
llRound
llSin
llSqrt
llTan
Table 6-2. Vector Functions
Function
llVecDist
llVecMag
llVecNorm
Table 6-3. Rotation Functions
Function
llAngleBetween
llAxes2Rot
llAxisAngle2Rot
llEuler2Rot
llRot2Angle
llRot2Axis
llRot2Euler
llRot2Fwd
llRot2Left
llRot2Up
llRotBetween
________________________________________
Chapter 7. Strings 串
7.1. Tables of Functions
Table 7-1. String Functions
Function
llba
llDeleteSubString
llGetSubString
llInsertString
llMD5String
llStringLength
llSubStringIndex
llStringToba
llToLower
llToUpper
llXorba
________________________________________
Chapter 8. Lists 历表
8.1. Tables of Functions
Table 8-1. List Functions
Function
llCSV2List
llDeleteSubList
llGetListEntryType
llGetListLength
llList2CSV
llList2Float
llList2Integer
llList2Key
llList2List
llList2ListStrided
llList2Rot
llList2String
llList2Vector
llListFindList
llListInsertList
llListRandomize
llListSort
llParseString2List
________________________________________
Chapter 9. Communication 交流
9.1. Tables of Functions
Table 9-1. In World Functions
Function
llListen
llListenControl
llListenRemove
llSay
llShout
llWhisper
Table 9-2. Messaging Functions
Function
llEmail
llGetNextEmail
llInstantMessage
________________________________________
Chapter 10. Inventory 库
10.1. Tables of Functions
Table 10-1. Inventory Functions
Function
llAllowInventoryDrop
llGetInventoryCreator
llGetInventoryKey
llGetInventoryName
llGetInventoryType
llGetInventoryNumber
llGetInventoryPermMask
llGetNotecardLine
llGiveInventory
llGiveInventoryList
llRemoveInventory
llRequestInventoryData
llRezob
llRezAtRoot
Chapter 11. Vehicles 交通工具
用LSL可以创建和控制交通工具.这张将讲述交通工具基本原理,描述交通工具的术语,以及API函数的应用.
有很多方法可以编程控制对象移动.一个方法就是把对象编程”交通工具”.这个功能可以让物体侧身,盘旋,飞翔和漂浮.一些动作可以:
• deflection of linear and angular velocity to preferred axis of motion
• 通过改变线速度和角速度来选择运动坐标
• asymmetric linear and angular friction
• 非均匀线和角度摩擦
• hoveringover terrain/water or at a global height
• 盘旋在在梯田和水面,或者以全局高度盘旋
• bankingon turns 通过倾斜转弯
• linearand angularmotor for push and turning 线和角发动机,用来推和转
11.1. Overview 综述
每一个被编程对象都可以带一个交通工具,交通工具在llSetVehicleType, llSetVehicleFloatParam, llSetVehicleVectorParam, llSetVehicleRotationParam, llSetVehicleFlags, and llRemoveVehicleFlags中调用并组合.
下面会详细讲述这些调用指令.最重要的是一定要注意一个交通工具行为有几个参数,来改变交通工具的控制.不同的值使交通工具既可以象水中的船一样漂转,有可以象轨道上雪橇一样.
设定交通工具旗子可以得到默认值以外的行为.一些旗子只能在某些行为下有效.比如, VEHICLE_FLAG_HOVER_WATER_ONLY这个函数可以让交通工具不考虑梯田高度,但是它只在交通工具盘旋的状态下有效.
11.2. Warnings
在以后几个版本的secondlife中,交通工具会改善.有些行为细节会根据稳定性和用户安全而改善.特别地,附录中一些限制和默认设置并不会长期使用.
建议交通工具和其它程序调用一起使用,比如脉冲函数,对象的力量函数.特别是这几个函数: llSetBuoyancy, llSetForce, llSetTorque, and llSetHoverHeight
尽管下面这些方法不会引起不稳定,但这些行为可能可能让交通工具矛盾,引起不可预料的或者不连续的结果,比如这些函数: llLookAt, llRotLookAt, llMoveToTarget, and llTargetOmega
如果交通工具有bug,一个办法是提交问题,这样给Andrew Linden这个交通工具的程序代码拷贝及其注释,或者标识问题.请把提交报告命名为: "Bugged Vehicle XX",这个XX是你的Second Life姓名缩写. Andrew Linden公司就会尽快改善这个交通工具.
11.3. Definitions 定义
"roll转"; "pitch颠" "yaw侧" 用来描述飞机或者轮船的旋转.分别绕X.Y.Z轴一定角度..
z-axis .
yaw-axis /|\
| __. y-axis
._ ___| /| pitch-axis
_||\ \\ |\. /
\|| \_______\_|__\_/_______
| _ _ o o o o o o o |\_ ______\ x-axis
// ./_______,—-,__________) / roll-axis
/_,/ // ./
/__,/
按照右手定则(高中物理学过的电磁定律),定义这里的顺时针选择规则.比如:绕一个旋转轴顺时针旋转.
.-.–.–.–. __
/ / / / _ \ / \
(-(- (- (- ( | _________|______\ axis of
\.\._\._\._) | | / rotation
| \:__,—. \|/
| | + positive
\ .,_.___.’ rotation
\_ ^ `.__,/
| /
| |
许多控制交通工具的参数是同一个形式:函数VEHICLE_BEHAVIOR_TIMESCALE.一个行为”时间刻度”可以指用时间来设定推.转或者用来影响交通工具,比如设定它现在的行为和把其改变1/e后该有的行为.e是自然指数因子.也就是说,其行为会按照自然指数衰减. 当想要交通工具动作改变快,就把时间刻度设置大一些,比如300(5分钟)会更大.注意,因为稳定性需要,时间刻度有个最小值限制.一般按照每秒10倍变化.把时间刻度设置为0等于把它设置到其最小值.任何功能都可以通过把时间刻度设置足够大而使之失效.因为刻度大,改变一个行为可能需要花费1天时间.
11.4. Setting the Vehicle Type 设置交通工具类
在任何交通工具行为必须先激活,才可以设定交通工具参数. 通过来任何类VEHICLE_TYPE_*的函数llSetVehicleType来激活. 函数VEHICLE_TYPE_NONE会使交通工具行为失效,不可以用来激活.参考交通工具类常量.更多的交通工具类会在以后提供.
为激活交通工具行为,必须设定交通工具类,以及为其各种默认值设定参数. 我们提供了每种类的代码. 请注意每种类的默认值不是特定的,在将来会改变的.不用把这些值当成常量,而不去指定.
如果想要制定交通工具,必须先在某一种默认类下激活交通工具行为,然后可以改变其参数,或者在允许范围内改变其旗帜.
设定交通工具类不会自动去控制和移动对象.如果激活交通工具行为,而那个对象正好是在移动或者在一个山上,它就会移动飘游.
我们正在建立新的默认类. 如果你自行设计了一种汽交通工具,船或者其它任何交通工具的默认类,请把你参数设置历表发送给我们.
11.5. Linear and Angular Deflection 线和角偏转
理解此节内容最好参考(即坐标旋转,参看高三数学解析几何.)
所有的交通工具都可以绕着特定的轴旋转. 根据其轮胎,交通工具翼,形状或者其绕轴驱动力的不同方法而选择不同轴. 这个轴相对交通工具自身是静止得. 这个基本特征界定了交通工具的类别以及在这个标定中的交通工具: 交通工具身后部有鳍,这样在其需要在空气中翻筋斗的时候,可以让其对准点向前—我们定义这种对准为角偏转.
不同的轮胎工艺,不同的结果.当滑板被推向某个方向的时候,它会朝它可以自由旋转的方向前进.我们将此效应称为:线性偏转.
一个典型的secondlife对象可以朝着其选择的轴进行线性或者角偏转. 在交通工具的原始部落的坐标下, 默认的轴,是本地轴X,左边Y轴,Z轴向上.偏转是相对于本地轴而言: 线性偏转会使旋转线速率变化,直至指向X轴正向,而角偏转则是使X轴按照其移动发现旋转.(即坐标旋转,参看高三数学解析几何.)
不同的交通工具,线性和角偏转不同. 通过函数llSetVehicleFloatParam 来设定相关参数改变偏转速度. 每个偏转速率都有一个时标参数,这个参数可以决定偏转变化快慢. 一般这个时标是针对全速偏转的指数衰减函数的系数. 因此, 时标越小,也就是指数函数系数小,一个交通工具偏转会越快. 例如,一个典型的投掷可能由好几秒钟的角偏转和几秒钟的线性偏转组成, 在它改变方向之前,它会自转. 用下面两行来设定一个投掷行为的时标:
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 6.0);
每一种偏转的速率有效率参数, 一个在0.0 到1.0的数字.不像其它设定交通工具行为的效率参数, 这个偏转参数不会在”完全弹性”和”阻尼”态, 而是从”没有任何偏转(0.0)”到”最大偏转(1.0)”. 它们类似偏转时标,变化范围从0.0 到 1.0
11.6. Moving and Steering the Vehicle移动和控制交通工具.
一旦激活,一个交通工具可以
通过外力或者调用函数llApplyImpulse实现推行或者旋转.然而线性和角发动机是内嵌的,以使其运动更加平滑和易于控制.
通过函数llSetVehicleVectorParam调用可以设定其方向.比如,实现一个交通工具沿其X轴,也就是观察到的当前轴方向每秒位移5米,
通过这个以下指令就可以:
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <5>);
除了上述有控制发动机的力量的函数, 还有函数(VEHICLE_LINEAR_MOTOR_TIMESCALE)控制其引擎速度. 发动机的效率随时间递减的参数函数为: (VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE)
控制一辆交通工具,涉及到设定函数VEHICLE_ANGULAR_MOTOR_DIRECTION及其相关参数. 也可以通过设定一些旗帜来允许角发动机为”Camera”“视角”服务.
更多内容请参考线和角”Motor(发动机)”.
11.7. The Linear Motor 线Motor(发动机)”
控制线”Motor(发动机)”的参数如下:
• VEHICLE_LINEAR_MOTOR_DIRECTION
• 函数VEHICLE_LINEAR_MOTOR_DIRECTION,一个矢量.表征交通工具达到的速度.单位米/秒.起点在交通工具身上,最大长度为40
• VEHICLE_LINEAR_MOTOR_OFFSET
一个矢量.指与交通工具的中心点偏置的位移,线”Motor(发动机)”的启动就从这个中心点开始.这也是”Motor(发动机)”产生转力矩.这个矢量起始于交通工具身,最大长度达100米.而且无需担心稳定性—如果交通工具旋转过快(超过44*P弧度),角速度就会下降.这就是这个偏置可以大达100米的原因,因为这样它可以和其它交通工具的行为展开竞争.比如行为角偏差,垂直吸收. 其它一些交通工具行为可能引起线”Motor(发动机)”偏置,造成非常大的转力矩效应降低,这种情况下,平衡力臂可以缓冲这种降低.
• VEHICLE_LINEAR_MOTOR_TIMESCALE
一个浮量.决定发动机推动交通工具达到全速需要的时间.最小值大约为0.06秒.
• VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE
一个浮量.发动机效率随时间刻度指数下降,但是如果发动机的值被明确设定的时候,发动机效率会被重置.最大衰减时标为120秒, 这个时标一直有效.
影响线发动机的旗帜:
• VEHICLE_FLAG_LIMIT_MOTOR_UP
对”地交通工具”有用.这个旗帜用来夹住线发动机的Z轴部件,以防止地心引力影响.这个Z轴是针对secondlife坐标而言.
设计一个优秀的交通工具,光设定发动机速度是不够的.比如,有人会想要一辆可以马上达到他想要的速度的交通工具,而有些人则想要一个船,一个可以慢慢达到其最大速度的船.
函数VEHICLE_LINEAR_MOTOR_TIMESCALE可以用来设定参数以实现控”交通工具”还是”船”的控制.基本上,对于一辆指数增速到其全速的交通工具,其发动机的时标是一个常数.
如果不小心设定交通工具线速达到其可能最大值并让其发动了,这会产生什么现象呢?交通工具会跑远并永远停不下来吗? 事实并非如此.一个自动的”发动机衰减器”内嵌在这种发动机里,这样在设定好后,发动机会自动衰减其效率.
每次线发动机矢量设定其方向盘,然后启动,并按照指数衰减,指数衰减时标则由函数VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE决定, 这样在一定时间后,发动机就静止了.
这个衰减时标有两个用途.一呢,因为它最长不超过120秒,而且它永远设置为有效,以防止交通工具在没有控制(如键盘控制,或者通过程序指令控制)的情况下,永远前进不停止.第二个目的, 它可以用来推进某些交通工具达到一种脉冲模型效果. 而不是设定交通工具启动或者停止.这在通过特定键来”上””下”移动衰减时标值,以使交通工具在”发动”状态下,随着不同的衰减时标而随之自动衰减速度.
既然发动机在交通工具矢量设定的时候,会被清零重置,那么设定它为矢量长度0就和其完全衰减不同. 前一种情况会使交通工具达到速度为0,而后一种情况则让发动机停止.
两种发动机时标有类似的名字,但是不同的用途,因此不要混淆.
函数VEHICLE_LINEAR_MOTOR_TIMESCALE是让发动机”赢”的时间,
而函数VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE是让发动机的效率衰减到零的时间.错误的使用只有错误的结果.同时,发动机衰减时标比一般的时标短,发动机矢量的有效数量级会减少.
11.8. The Angular Motor 角发动机
控制角发动机的参数:
• VEHICLE_ANGULAR_MOTOR_DIRECTION
一个矢量.这是交通工具旋转的角速度矢量.它的原点在交通工具身,最大值4*PI,即每秒2周.
• VEHICLE_ANGULAR_MOTOR_TIMESCALE
一个浮量.觉得发动机使交通工具旋转到最大角速度的时间.最小值大约0.06秒.
• VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE
一个浮量.发动机效率会随这个时标指数衰减,但是同样在发动机被设定的时候,其效率会清零重置.这个衰减时标最大值为120秒,且它始终有效.
和线发动机一样,角发动机可以直接设置,有幅度/方向,时标,衰减时标等参数.
当需要真正控制一辆交通工具的时候,有几种方法.
一种是通过键盘控制,这种方法不适用于远和长距离的交通工具运行.
另一种方法是通过角发动机,让衰减时标设置比较大,产生非常大的角摩擦(以使交通工具迅速减速和发动机停止),在通过按一下键盘来设置角发动机为一个比较大的矢量,当键盘松开后,它被设置为0.这可以让交通工具凭借其角摩擦,而不受外部碰撞干扰
另一个方法是设定函数VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE到一个比较小的值,来推动交通工具以一种更加冲的方式前进,通过按住一个键给发动机加速,松开键让其发动机为0.这通过发动机的自动指数衰减实现,而不是一个角摩擦常数.
最后,通过函数VEHICLE_LINEAR_MOTOR_OFFSET可以完全不使用角发动机.一旦偏置有部件和线发动机垂直,交通工具就会旋转.
注意,错误的设定偏置和交通工具的线发动机力量,会很容易翻交通工具,或者使交通工具失去控制的旋转,所以,刚开始,最好一次比较小偏置的做实验.
设定角发动机为0,和允许其衰减不同.当发动机完全衰减,它不再影响交通工具的运动,但是设定其角发动机为0,则会重置”方向盘”,让交通工具的角速度变为0.
许多真实的交通工具以倾斜方式(绕其前进方向滚动)以达到转弯目的,比如摩托交通工具和飞机.为了更方便建立倾斜交通工具行为,有函数库倾斜行为,通过设定其它参数来控制倾斜. 这在后面后详细介绍.
It is also possible to make a vehicle turn in response to changing the camera view (right now this only works in mouselook
11.9. Using the Camera to Steer
交通工具子可以通过”Camera”“视角”的方向来引导其前进.这通过设定一些旗帜,在函数VEHICLE_ANGULAR_MOTOR_DIRECTION中体现出来.当设定正确,这些特征可以提供简单和稳定的控制.
The flags that affect the angular motor are:
影响角发动机的旗帜:
• VEHICLE_FLAG_MOUSELOOK_STEER
通过鼠标控制交通工具.这俄国旗帜可以让角发动机让交通工具转弯,比如让其本地X轴指向客户端”Camera”“视角”.
• VEHICLE_FLAG_MOUSELOOK_BANK
这个旗帜和上面那个相同,只是依靠倾斜.它改变客户”Camera”“视角”(偏航)的左右运动,来选择交通工具的本地X轴(滚动).
• VEHICLE_FLAG_CAMERA_DECOUPLED
是鼠标搜寻”Camera”“视角”独立于交通工具旋转.默认设置,客户鼠标搜寻”Camera”“视角”会绕交通工具旋转,却是在旗帜设定”Camera”“视角”方向独立于交通工具的旋转时.
当用函数VEHICLE_FLAG_MOUSELOOK_STEER (or VEHICLE_FLAG_MOUSELOOK_BANK)时候,函数VEHICLE_ANGULAR_MOTOR_DIRECTION的参数含义有所改变.不再代表角速度,而是测定的角速度,通过客户”Camera”“视角”方向和交通工具前进轴之间的偏转决定,这样来计算最后角速度.假设设定角发动机为<0>,然后移动”Camera”“视角”视野到PI/4 弧度到交通工具前进轴的左面,然后下降PI/8到地面.这个测定的角速度会是<0> 弧度/秒,最后的速度是<0>.这个交通工具转左,却不会鼻子朝下冲到地上.因此,通过设定函数的一个部件为0,可以消除发动机偏航或者堕落的效应,甚至可以更好的设定.
函数VEHICLE_ANGULAR_MOTOR_TIMESCALE 在用到鼠标控制的时候,仍然有效.可以量衡角发动机的全局反馈.也可以在用鼠标控制的时候,不考虑这个函数VEHICLE_ANGULAR_MOTOR_TIMESCALE
11.10. The Vertical Attractor
一些交通工具类,比如船,会永远保持”上—边上”的状态.这可以通过”Vertical Attractor”行为来实现,这个行为可以激发交通工具的本地Z轴沿着Secondlife的Z轴.可以通过设定函数VEHICLE_VERTICAL_ATTRACTION_TIMESCALE来利用这个特点,控制激发频率范围,设定函数VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY来控制其衰减.系数0.0会造成激发绕其平衡点颤动,而系数1.0则让激发达到其平衡点,没有任何指数衰减.
llSetVehicleVectorParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 4.0);
llSetVehicleVectorParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.5);
设定时标超过30秒,Vertical Attractor行为则失效.
主要默认设置中,”Vertical Attractor”可以防止交通工具俯冲或者攀升.因此,如果要设计一个飞机,必须把”吸引”从其定轴释放出来.这可以通过设定函数VEHICLE_FLAG_LIMIT_ROLL_ONLY的位来实现:
llSetVehicleFlags(VEHICLE_FLAG_LIMIT_ROLL_ONLY);
11.11. Banking倾斜
一些Vertical Attractor行为的功能可以必须激发,这样倾斜行为才有效.倾斜行为工作方式:绕交通工具滚动轴的旋转会产生绕其偏航轴(Y轴)的角速度,是车转弯.偏航效应副值和函数VEHICLE_BANKING_EFFICIENCY成比例,滚动旋转的角度,有时交通工具绕其本来轴运动的速度等.
函数VEHICLE_BANKING_EFFICIENCY的值在-1到+1之间变动.在为正的时候,任何绕其滚动轴的正方向旋转(右手定则)都会产生一个负的力矩绕其偏航轴, 使其向右转—这就是车倾斜转弯,飞机和摩托车都是如此.消除倾斜系数可以让车倾斜到转弯之外(物理上不可实现,但是可以实现非常有趣的交通工具,为什么不呢?)
没有评论:
发表评论