1.导论
林登脚本语言(LSL)是一种简单易学,并能给Second Life中的物体赋予生命的强大语言。它的语法与C/JAVA语言的风格类似,每一个脚本中都有一个隐型状态机。
同一个物体可以被赋予多个不同的脚本,也允许利用一个只有简单函数功能的脚本来进行升级。这使得脚本会表现出特定的功能(如“漂浮”,“跟随”等等)也允许他们联合起来组成新的行为。
脚本语言会被编译成可执行的代码,就像JAVA一样,代码可以在仿真器的虚拟机上运行。所有脚本分享仿真器分配的时间片,所以一个有很多脚本的仿真器能允许每个脚本执行时间更短,而不会降低性能。另外,每一个脚本在其自己的内存空间中运行,以防止脚本对仿真器的保护内存或者对其他脚本进行改写,使得脚本程序很难影响仿真器。
这个指南为读者介绍了LSL语言的基本特征,如何编辑和应用你的脚本,如何完善的引用标准常量,事件和库函数。
2.现在开始
你可能很想知道你可以利用LSL做些什么,你多久能掌握它。我们要开始一些简单的例子,解剖他们,并在同时向你介绍一些脚本的开发过程。
2.1. Hello Avatar
按照惯例,程序语言的教程总是以“Hello”开始,我们也不改变这个惯例。虽然这个小程序没有什么特别的用处,但这个例子可以让我们知道以下几件事:
"创建一个基本脚本
"脚本状态
"调用函数
"脚本事件
"在物体上应用脚本
2.1.1. 创建脚本
打开你的“清单栏(Inventory)”,在下拉列表中选择“建立(Create)|新脚本(New Script)”。这时在你的“脚本”目录中会出现一个名为“新脚本”的空白文件。双击脚本的文件名或图标在编辑器中打开脚本文件。当你打开这个脚本的时候,窗口中会自动的插入一些基本的LSL 语言框架。会像下面这样:
default
{
state_entry()
{
llSay(0, "Hello, Avatar!");
}
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
}
对这个脚本进行测试,当它进入某种状态,比如被触摸的时候。会显示“Hello, Avatar!”,和“Touched”。因为这也许是你第一次看到一个程序指令,让我们来分解这段小指令,一个小段一个小段地进行解释。
2.1.2. 默认状态
default
{
...
}
所有的LSL脚本都有一个简单的隐型状态机,它可以有一种或多种状态。所有的脚本必须有一个默认状态,所以如果脚本只有一个状态,那么它就会是“默认”状态。当一个脚本第一次启动或者重启时,它会从默认状态开始。
默认状态通过把default(默认)放在文档的最顶层,用花括号“{”开始,并以“}”结束。因为默认状态是一个特殊状态,你必须把它和其他状态区别开。
每次当你进入一个状态,脚本引擎会自动的调用state_entry()事件,从那里开始生成执行代码。当状态结束,脚本引擎会在调用下一个state_entry处理之前自动调用state_exit()事件。在上面的例子中,我们在state_entry()中调用了llSay()函数,而并没有定义一个state_exit()。进入(entry)和退出(exit)处理是一个初始化状态数据和清除诸如“listen”事件回调函数的地方。
在第五章中你能了解到关于默认状态,如何创建和利用其他状态的具体方法。
2.1.
3. 函数
LSL语言有超过200个内建函数,允许脚本和物体在环境中相互影响。所有的内建函数均以“ll”开头。
上面的例子中两次调用了llSay()函数,llSay()的作用是在特定信道中显示文字。
llSay( integer channel,string text );
Channel是信道的号,信道0是公共聊天信道,所有的人物都能够看到聊天信息。信道1到信道2147483648是专用信道,人们无法看到,仅供其它脚本从中获取信息。
你可以定义自己的函数,但函数名不能是保留字,内建常量,或者内建函数。
2.1.4. 触摸事件
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
许多事件可以通过在你的脚本中声明一个事件处理程序来检测。touch_start()事件会在用户触摸到物体的时候发生。
2.1.5. 尝试
既然我们已经看过默认脚本,也解释了其中的一些细节,现在可以试着运行这个脚本。点击“保存”保存这个脚本。在保存处理中,编辑器会保存代码然后将代码编译成字节码然后再进行储存。当你在预览窗口中看到提示“编译完成(Compile successful)!”时,编译已经完成并保存。
为了测试这个脚本,你要把它应用到一个物体中。创建一个物体的方法是在主视窗中点击“创建”。当那个棒棒出现的时候,你能够在世界中创建一个简单的物体。当物体被创建时,你能把你新编写的脚本拖拽到物体上,运用这个脚本。
当你把脚本拖拽到物体上以后,你就能看到物体显示出“Hello Avatar!”的信息。
确保触摸事件能够在你点击的时候发生。当你点击物体时应该能在聊天历史中看到信息“Touched”。
2.2.使用内建编辑器
内建编辑器有着基本文本编辑器所具有的大多数功能。你可以用鼠标或shift键+方向键选中文本。你可以使用Ctrl+X, Ctrl+C,Ctrl+V对文本进行剪切,复制,和粘贴,或者在“编辑”下拉菜单中选择上述操作。
2.3.使用其他编辑器
因为内建编辑器支持从剪贴板粘贴,所以你可以用其他的编辑器进行脚本编辑,然后复制到Second Life中。
3.基础教程
既然我们已经看见一个简单程序的运行了,现在就看看如何自己编程吧.下面这些工具用来构架基本程序块从而编程,并且会在实际中应用到。
3.1.注释
为你的脚本加上注释是一个很好的习惯,在你更新、修改或者使用别人的脚本的时候,注释会很有帮助。除非脚本很容易懂,否则你应该加上注释。
1.在脚本的开始要注明脚本的功能
2.在每一个全局变量之前要注明它在哪一段是全局的
3.在每一个全局函数之前要注明它的功能
4.在你自己一眼看不出代码功能的地方,加些注释
LSL语言使用和Java/C++一样风格的单行注释。
// 这个脚本触发一个物体的旋转
// g_is_rotating 保存旋转的当前状态。TRUE 表示
// 正在旋转, FALSE 表示其他情况。
integer g_is_rotating = FALSE;
default
{
// 在触摸时触发状态
touch(integer num)
{
if(g_is_rotating)
{
// 关闭旋转
llTargetOmega(<0,0,1>, 0, 0);
g_is_rotating = FALSE;
}
else
{
// 绕Z轴正半轴旋转,向上方。
llTargetOmega(<0,0,1>, 4, 1);
g_is_rotating = TRUE;
}
}
}
3.2.算术操作
LSL中支持大多数算术操作,和C/JAVA语法相同。
3.2.1. 赋值
大多数的算术操作都是赋值,使用“=”表示。简单的说就是把等式右边的值赋予左边,但是左边只能是一般变量。
所有的基本类型支持赋值“=”,相等“==”,和不等“!=”操作。
// 保存目标物体信息的变量
key g_target;
vector g_target_postion;
float g_target_distance;
// 赋值函数范例
set_globals(key target, vector pos)
{
g_target = target;
g_target_position = pos;
// 利用函数返回值来赋值
vector my_pos = llGetPos();
g_target_distance = llVecDist(g_target_position, my_pos);
}
3.2.2. 十六进制的使用
整数会以十六进制的形式输入,例如:
integer Mask = 0xff; // 等于整数255;
integer Bit = 0x0100; // 等于整数256;
3.2.3. 二进制运算操作
二进制运算就像是一个有两个同类参数的函数,然后返回那个类型;然而语法有些不同。表3-1 二进制运算符
每一个运算符都有详细的解析,请参见类型章节获得详情。
3.2.
4. 布尔型操作
表3-2 布尔运算符
3.2.5. 位运算操作
表3-3 位运算符
3.3.类型
变量,返回值和变量都是有不同的类型的。LSL中提供了几种基本的数据类型。
LSL 类型
整型(Integer)
一个32位带符号的整型值的有效范围是从-2147483648到2147483647。
浮点(Float)
一个IEEE标准32位浮点型值得有效范围是从1.175494351E-38到 3.402823466E+38。
键值(Key)
键值是在SL中一个唯一的,可以用来引用物体的标识。
矢量(Vector)
矢量值中包括3个浮点值。矢量值可以用来指示3维位置,方向,速度,力量,脉冲,甚至颜色。每个部分可以通过…x?…y?和…z?来访问。
表3-4. 矢量算术运算符
旋转(rotation)
旋转型变量中有4个浮点型函数。成员可以通过…x?…y?…z?和…s?访问。
表3-5. 旋转运算符
列表(list)
列表是另外一种数据类型。列表用…[?…]?括起来,内部的各个值用逗号隔开。
string StringVar = "Hello, Carbon Unit";
list MyList = [ 1234, ZERO_ROTATION, StringVar ];
生成列表: [ 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
列表可以和其他的列表进行组合。比如:
MyList = 3.14159 + MyList;
生成列表: [ 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
更简单的:
MyList = MyList + MyList;
生成: [ 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit", 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
一些库函数可以从列表中拷贝数据,分类列表,和移除子列表。
3.3.1. 类型转换
类型转换分为明转换和暗转换。明转换使用类似C语言的语法:
float foo_float = 1.0;
integer foo_int = (integer)foo_float;
3.3.1.1.暗转换
LSL只支持两种暗转换:整型(integer)到浮点型(float)和字符串(string)到键值(key)的转换。因此,你可以在需要浮点量的地方使用一个整型,可以在需要键值的地方输入字符串。
3.3.1.2.明转换
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.全局函数
全局函数的声明也和Java/C的风格相似,只是没有void返回值。也就是说,函数在没有返回值的时候不需要定义返回值(C语言中需要定义返回空值void):
make_physical_and_spin(vector torque)
{
// 扭矩变为2倍
vector double_torque = 2.0*torque;
llSetStatus(STATUS_PHYSICS, TRUE);
llApplyTorque(double_torque);
}
3.5.全局变量
全局变量在文件的各处都可以调用,全局变量的声明也和Java/C语言类似,但每一行只能声明一个变量:
vector gStartPosition;
如果需要,全局变量可以被初始化,没有初始化的全局和局部变量会被初始化成0值:vector gStartPosition = <10.0,10.0,10.0>
3.6.局部变量
局部变量要在它的声明下才可被使用(定义必须放在调用前)。在它们被定义的那个代码段中有效。下面这段合法代码就类似C语言:
integer test_function()
{
// 测试我们在函数中的任何地方都可以调用的向量
vector test = <1,2,3>;
integer j;
for (j = 0; j < 10; j++)
{
// 这个向量和上面定义的不同
// 这是不好的编程习惯
vector test =
}
// 测试失败
if (test == <9,9,9>)
{
// 无法达到
}
}
4.流控制
LSL有完整的处理条件问题的函数,比如循环或者从脚本的一点跳到另一点。
4.1.条件语句
if 状态操作符的语法和Java/C语言类似。
check_message(string message)
{
if(message == "open")
{
open();
}
else if(message == "close")
{
close();
}
else
{
llSay(0, "Unknown command: " + message);
}
}
当小括号里面的值为非0值时,花括号里面的表达式才会有效。当if后的括号中的值为真(不为零)时,else后的表达式就不再有效。无效符号NULL_KEY等同于假FALSE。
当if或者else if 后面的表达式都不是非零整型是,即执行else后面的语句。
括号中的表达式可以使用常用的整型运算符或者比较运算符。
//一个函数,如果收到了一些用来指导它下一步做什么的信息。这样的代码就像
//一个简单的块,一旦条件符合就会一下子被用到程序中。
assess_next_step(integer perm, integer attached, integer balance, float dist)
{
string msg;
if(!attached)
{
if((perm & PERMISSION_ATTACH) && (dist < 10.0))
{
attach();
}
else if((dist > 10.0) || ((dist > 20.0) && (balance > 1000)))
{
move_closer();
}
else
{
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
}
}
}
4.2.循环结构
循环是大多数程序语言都有的一种基本构件,LSL中的循环与Java/C的结构相似。
4.2.1. for语句
当你知道一个操作需要重复多少次的时候使用for语句就显得很有用了。就像Java或者C 中的循环,括号里共有三部分,初值,循环条件,和步长。循环在当中间的循环条件为真时运行,在循环结束时变量会自动增加。
//使一个非物理性的块延z轴向上做平缓的上移,移动的动作由许多次连续的移动组成move_up(float distance, integer steps)
{
float step_distance = distance / (float)steps;
vector offset = <0.0, 0.0, step_distance>;
vector base_pos = llGetPos();
integer i;
for(i = 0; i <= steps; ++i)
{
llSetPos(base_pos + i * offset);
llSleep(0.1);
}
}
4.2.2. do-while语句
当你想让一个操作不断循环但你又不知道应该循环多少次的时候do-while就显得十分有用。对do-while的一个简单描述就是:如果符合预先设置的条件,do-while后面括号里面的语句就会被执行,然后继续判断那个条件。
//输出附着在这个物体上的所有部件名称清单
talk_about_inventory(integer type)
{
string name;
integer i = 0;
integer continue = TRUE;
do
{
name = llGetInventoryName(type, i);
if(llStringLength(name) > 0)
{
llSay(0, "Inventory " + (string)i + ": " + name);
}
else
{
llSay(0, "No more inventory items");
continue = FALSE;
}
} while(continue);
}
4.2.3. while语句
While循环和do-while循环很像,不同的是do-while循环先执行代码,再判断下次是否需要继续循环,而while循环先判断,符合条件以后再执行代码。
mention_inventory_type(integer type)
{
integer i = llGetInventoryNumber(type);
while(i--)
{
llSay(0, "item: " + llGetInventory(i));
}
}
4.3.跳转
Jump语句用来从一个函数或者一个事件中跳到脚本中的其他地方。但不能跳到别的函数或者事件中。通常,你可以在用if...else条件语句过于复杂的时候使用它。
4.4.状态改变
状态改变允许你将你的脚本状态在默认状态和用户状态之间转变。你可以通过在事件处理程序的花括号(…{?和…}?)之前使用一个…state?关键字来定义你自己脚本的状态。你可以使用这样的语法来使用新的状态调用过程:…state <状态名>?。
default
{
state_entry()
{
llSay(0, "I am in the default state");
llSetTimer(1.0);
}
timer()
{
state SpinState;
}
}
state SpinState
{
state_entry()
{
llSay(0, "I am in SpinState!");
llTargetOmega(<0,0,1>, 4, 1.0);
llSetTimer(2.0);
}
timer()
{
state default;
}
state_exit()
{
llTargetOmega(<0,0,1>, 0, 0.0);
}
}
5.状态
所有的脚本必须有一个…默认(default)?状态,在脚本运行的时候会首先进入这个状态。状态包括由LSL触发的事件处理程序。所有的状态必须至少有一个事件处理程序——如果不包含任何事件处理程序,那将不是一个状态。
当状态改变时,所有的回调设置都会被保持,所有的未决事件都会被清除。
5.1. state_entry()函数
state_entry事件在进入一个新的状态时发生,在程序启动时,它总是作为程序的第一个事件来处理。这个事件处理程序没有数据的传输。
你有的时候可能会为了让你的物体起作用而在state_entry()中为定时器或传感器设置一个回调函数。
警告:这是一个常见的错误,出现这样的问题是因为假设了state_entry()会在你把一个物体从清单栏中拖出来的时候被调用。当你把一个物体放回清单栏中的时候,这个物体当前的状
态将被保存。所以,当你再次将这个物体拖出清单栏的时候,state_entry()并没有被调用。如果你想让每次这个物体被拖出来的时候都运行一个启动代码,你需要建立一个全局函数,并在state_entry()和on_rez()函数中都调用它。
//全局初始化函数。
init()
{
//为物体的拥有者设置一个listen函数。
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()函数
如果你需要在进入一个新的状态之前清除当前状态的事件,你就需要一个state_exit()函数。default
{
state_entry()
{
state TimerState;
}
}
state TimerState
{
state_entry()
{
// 设置一个5秒钟的定时器。
llSetTimerEvent(5.0);
}
timer()
{
llSay(0, "timer");
state ListenState;
}
state_exit()
{
// 关闭定时器事件。
llSetTimerEvent(0.0);
}
}
integer g_listen_control;
state ListenState
{
state_entry()
{
// 监听公共通道上的信息。
g_listen_control = llListen(0, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message)
{
llSay(0, "listen");
state TimerState;
}
state_exit()
{
// 关闭监听器。
llListenRemove(g_listen_control);
}
}
在物体被删除的时候,state_exit()处理不会被调用,所有的回调函数,处理进程,声音,或者其它都会被自动清除。
5.3.状态VS全局变量
状态和全局变量都能够达到相同的目的,每一个都能根据另一个进行表达。一般来说,推荐使用状态而不是全局变量,因为状态能让你快速实现脚本的状态而不用进行比较。更少的比较会形成更高效的代码。
6.数学
6.1. 数学函数表
表6-1. 三角函数
表6-2. 矢量函数
表6-3. 旋转函数
7. 字符串
7.1.字符串函数表
表7-1. 字符串函数
8. 列表
8.1.列表函数表
表8-1. 列表函数
9. 通信
9.1.通信函数列表
表9-1. 通信函数
表9-2. 消息函数
10. 清单
10.1.清单函数列表
表10-1. 清单函数
11.交通工具
用户制作的交通工具可以使用LSL来构造和控制。这一章将要介绍交通工具的基础知识,其中包括用来描述交通工具的术语,和更详细的API的使用。
让一个物体运动的方法有很多种,其中一条就是把这个物体变成一个“交通工具”。这种特性能让物体滑行,漂浮,飞行,和悬浮。一些可用的功能如下:
?线性和沿着轴线的旋转运动
?非线性和有角度的摩擦
?沿着地形/水面漂浮
?通过倾斜来转弯
?用线性和角度发动机来推动和旋转
11.1.概括
每一个有脚本的物体可以有一个交通工具的行为,可由以下库函数来定义:llSetVehic leType, llSetVehicleFloatParam, llSetVehicleVectorParam, llSetVehicleRotationParam, llSetVehicleFlags, and llRemoveVehic leFlags。
这些脚本函数将在下面进行详细说明,但最重要的是记住这些交通工具需要有很多参数来调整它的行为。通过对参数的选择,物体可以变成在水面上行驶的船,也可以变成在轨道上行
驶的雪橇。
设置交通工具的标志可以让你改变默认的状态。其中的一些标志只在某种行为激活的时候才起作用。举个例子,VEHICLE_FLAG_HOVER_WATER_ONLY让交通工具忽略地形的高度,然而,只有在交通工具悬浮的时候才能体现出来。
11.2.警告
交通工具的特性可能会在未来版本的Second Life中进行改变。一些交通工具的行为细节可能会为了确保用户安全而进行修改。特别的,附件中相关的函数描述将可能被改变。
不推荐你将交通工具和具有冲击或压力行为的物体进行混合,尤其是含有llSetBuoyancy, llSetForce, llSetTorque, 和llSetHoverHeight。
虽然以下的方法不会影响稳定性,它们的行为可能会和交通工具的行为相冲突而带来不确定的问题,所以当你在交通工具上使用llLookAt, llRotLookAt, llMoveToTarget, 和llTargetOmega时,你要自己承担风险。
如果你想找出交通工具运行中的bug,你可以发一个带有问题描述的交通工具和脚本给Andrew Linden。请给所提交的文件起名"Bugged Vehicle XX",XX是你在Second Life中的昵称。交通工具和脚本将尽快地得到检查。
11.3.定义
术语"roll(滚动)", "pitch(倾斜)", 和"yaw(侧转)"经常用来描述一个飞机或者船的模型的运动。它们分别相对于x、y和z轴运动。
Y-俯仰轴轴
X-翻滚轴
Z-偏航轴
右手定则,经常在物理课中被引入,它用来定义沿着任意轴的正向旋转方向。作为一个如何使用右手定则的例子,考虑沿着翻滚轴的正向旋转。为了帮助你想象旋转的方向,把你的右手拇指平行于飞机的翻滚轴,拇指指向x-轴的正向,然后其余四指握拳。你的手指将会指向飞机旋转的方向。
正向旋转
X-翻滚轴
许多控制交通工具行为的参数都是这样形态的:VEHICLE_BEHAVIOR_TIMESCALE。一个行为的“timescale(时标)”用来作为推,扭曲,或者其它的对于交通工具影响的时间,区分当前在做什么和将要做什么,比如把一个量改变为1/e大小所用的时间,这里的“e”是自然指数(大约是2.718281828)。换句话说,是它的行为会按照指数衰减到期望行为的时间。如果你想要交通工具很快的响应,就使用一个更短的时间尺度,比如一秒钟或者更少,如果你希望停用一个行为,可以设置时标到一个很大的值,比如300秒(5分钟)或更多。记住,出于稳定性的原因,一般对于时标的最小值有一个限制,一般为1/10秒。设置时标到0是
安全的,这和把它设定为最小值的意思相同。任何有时标的特性都能通过设置很大的时标来使之失效,比如让它要花一天的时间来改变状态。
11.4.设定交通工具类型
在任何交通工具能够设置参数之前,交通工具的行为必须先被激活。可以通过调用llSetVehicleType并使用VEHICLE_TYPE_*参数来激活(用来停用交通工具的
VEHICLE_TYPE_NONE除外)。在交通工具类型常数中选择正确的类型。以后将会有更多的类型可用。
设置交通工具类型对于激活交通工具的行为是必要的,它将把所有的参数设置为默认值。每种交通工具的类型列在相应的长长的等式中。要知道,默认的值不是最佳的参数,这些参数将在以后被改变。不要依赖这些初始值。
如果你想制造一个用来试验的交通工具,你仍需要使用默认类型来激活这个交通工具的行为。在那以后,你就能够在允许的范围内改变任何一个参数或者标志。
设置交通工具的类型后它并不会自己运动。然而,你应该让这个交通工具物体能自由运动,然后把它放到山顶,然后它会开始滑下。
我们正在寻找更好的定义交通工具的类型,如果你觉得你发现了建造更好的汽车、船、或者其它默认类型的交通工具的参数,你可以通过脚本或者卡片提交你的设置建议给Andrew Linden。
11.5.线性和角偏转
一个真正的交通工具的特性是他会沿着一个“特定的轴运动”。就是说,根据他们的车轮,机翼,外形或者推动力而改变到不同的轴,这个轴相对于交通工具本身是静止的。这个基本特征作为交通工具的一个类,拥有这个特性的物体就会变成一个“交通工具”:物体在背部有一个鳍,如果他在空中翻倒了,他会自动地校正他的方向—我们把这种校正称为角偏转。
不同的轮胎工艺会出现不同的效果,当把一个滑雪板向某个方向推,他会沿着能自由旋转的方向运动—我们把这种作用叫做线性偏转。
一个典型的Second Life交通工具会沿着选定的轴做线性和角度偏转。默认的运动轴是:本
地轴-X,向左-Y,向上-Z(这些轴参照的是交通工具中的“根部件”的轴线方向)。偏转行为参照了X-轴:线性偏转会使旋转的线速度变化,直至指向X轴的正向。而角度偏转会使X-轴向其转动方向旋转。与其他轴相关的行为比如“引力(让物体的Z-轴指向世界中的Z-轴)”将会在以后说明。交通工具的轴可以利用参数VEHICLE_REFERENCE_FRAME来改变为物体的本地轴,不过这是高级的操作,具体会在以后的章节中说明。
根据交通工具是否具有的线性或角度偏转。我们可以通过修改函数llSetVehicleFloatParam的参数来控制偏转的速度。每一种偏转都有一个用来衡量偏转需要花多少时间完成的“时标”。一般的,时标是全速偏转的指数衰减的时间系数。所以,一个快速偏转的交通工具就会有一个很小的时标。比如,一个投掷行为的角度偏转时标有一两秒,而线性偏转时标有十几秒,因为它在改变方向之前会自转。设置偏转时标可以使用以下的函数:llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0); llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 6.0);
每一种偏转都含有一个从0.0到1.0的“效率”参数。和其他的描述交通工具行为的参数不同,
脚本语言的发展 主流的脚本语言 目前主流的脚本语言有以下几种: Groovy Ruby Python Groovy Groovy 是 JVM 的一个替代语言—替代是指可以用 Groovy 在 Java 平台上进行 Java 编程,使用方式基本与使用 Java 代码的方式相同。在编写新应用程序时,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。目前的 Groovy 版本是 1.6.3,在 Java 1.4 和 Java 5 平台上都能使用,也能在 Java 6 上使用。 Groovy 的一个好处是,它的语法与 Java 语言的语法很相似。虽然 Groovy 的语法 源于 Smalltalk 和 Ruby 这类语言的理念,但是可以将它想像成 Java 语言的一种更加简 单、表达能力更强的变体。(在这点上,Ruby 与 Groovy 不同,因为它的语法与 Java 语法差异很大。) 许多 Java 开发人员非常喜欢 Groovy 代码和 Java 代码的相似性。从学习的角度 看,如果知道如何编写 Java 代码,那就已经了解 Groovy 了。Groovy 和 Java 语言的 主要区别是:完成同样的任务所需的 Groovy 代码比 Java 代码更少。(有时候会少很 多!) Ruby Ruby,一种为简单快捷面向对象编程(面向对象程序设计)而创的脚本语言,在 20世纪90年代由日本人松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)开发, 遵守GPL协议和Ruby License。它的灵感与特性来自于 Perl、Smalltalk、Eiffel、Ada 以及 Lisp 语言。由 Ruby 语言本身还发展出了JRuby(Java 平台)、IronRuby(.NET 平台)等其他平台的 Ruby 语言替代品。 1
1: 下述选项中不属于JDBC基本功能的是:() 1.与数据库建立连接 2.提交SQL语句 3.处理查询结果 4.数据库维护管理 2:在page指令中,()属性是可以在页面中重复的的属性。 https://www.wendangku.net/doc/425070397.html,nguage 2.buffer 3.import 4.autoFlush 3:下面哪种数据类型是基本数据类型()。 1.class 2.interface 3.数组 4.char 4:下列哪种数据类型是引用类型()。 1.boolean 2.int 3.interface 4.long
5: 在JSP中使用
3.getParameterValues() 4.getSession() 9:下面哪一个运算符有3个操作数()。 1.* 2.++ 3.&& 4.?: 10:以下文件名后缀中,只有()不是静态网页的后缀。 1..html 2..htm 3..jsp 4..shtml 11:以下选项中,哪一项不是JSP指令()。 1.page 2.import 3.include 4.taglib 12:实际开发中使用Session可以设置访问的安全性,请选择Session所设置的属性的数据类型( ) 1.String
HTML各种命令的代码 跑马灯 普通卷动 滑动 预设卷动 来回卷动向下卷动 向上卷动 向右卷动 向左卷动 卷动次数 设定宽度 设定高度 设定背景颜色设定卷动距离设定卷动时间 字体效果
浅谈计算机编程语言的发展 信息学院103班潘红10263210 摘要:一九九三年美国的克林顿政府提出了“信息高速公路”计划,从而在这十多年间在全球范围内引发了一场信息风暴,信息技术几乎触及了现代生活的方方面面,毫不夸张的说没有了信息技术,现代文明的生活将无从谈起;作为信息技术中最重要的部分,计算机技术无疑是其发展的核心问题,而我们知道计算机只是一台机器,它只能按照计算机语言编好的程序执行,那么正确认识计算机语言的过去和未来,就是关系到计算机发展的重中之重。1.引言 在计算机科学中,编程语言是用来编写可被计算机运行的一系列指令(计算机程序)的人工语言,于英语等自然语言相类似,编程语言具有词汇、语法和句法。然而,自然语言不适合计算机编程,因为它们能引起歧义,也就是说它们的词汇和语法结构可以用多种方式进行解释。用于计算编程的语言必须具有简单的逻辑结构,而且它们的语法、拼写和标点符号的规则必须精确。 2.计算机编程语言的发展历史 二十世纪四十年代当计算机刚刚问世的时候,程序员必须手动控制计算机。当时的计算机十分昂贵,唯一想到利用程序设计语言来解决问题的人是德国工程师楚泽(konrad zuse)。几十年后,计算机的价格大幅度下跌,而计算机程序也越来越复杂。也就是说,开发时间已经远比运行时间来得宝贵。于是,新的集成、可视的开发环境越来越流行。它们减少了所付出的时间、金钱(以及脑细胞)。只要轻敲几个键,一整段代码就可以使用了。这也得益于可以重用的程序代码库。随着c,pascal,fortran,等结构化高级语言的诞生,使程序员可以离开机器层次,在更抽象的层次上表达意图。由此诞生的三种重要控制结构,以及一些基本数据类型都能够很好的开始让程序员以接近问题本质的方式去思考和描述问题。随着程序规模的不断扩大,在60年代末期出现了软件危机,在当时的程序设计模型中都无法克服错误随着代码的扩大而级数般的扩大,以至到了无法控制的地步,这个时候就出现了一种新的思考程序设计方式和程序设计模型-----面向对象程 序设计,由此也诞生了一批支持此技术的程序设计语言,比如eiffel,c++,java,这些语言都以新的观点去看待问题,即问题就是由各种不同属性的对象以及对象之间的消息传递构成。面向对象语言由此必须支持新的程序设计技术,例如:数据隐藏,数据抽象,用户定义类型,继承,多态等等。 3.计算机编程语言的发展现 目前通用的编程语言有两种形式:汇编语言和高级语言。 2.1汇编语言 汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,更容易识别和记忆。计算机编程人员用汇编语言使机器语言程序编写起来更简单一些。在汇编语言中,每条语句大致对应一条机器语言指令。汇编语言的语句是借助易于记忆的命令编写的。在典型的汇编语言
一、HTML各种命令的代码: 1、文本标签(命令)
创建预格式化文本 创建最大的标题 创建最小的标题 创建黑体字 创建斜体字 创建打字机风格的字体 创建一个引用,通常是斜体 加重一个单词(通常是斜体加黑体) 加重一个单词(通常是斜体加黑体) 设置字体大小,从 1 到 7 设置字体的颜色,使用名字或十六进制值2、图形(命令) 添加一个图像 排列对齐一个图像:左中右或上中下 设置围绕一个图像的边框的大小 将段落按左、中、右对齐
插入一个回车换行符
2016-2017学年第一学期期末考试《脚本语言和互动网页设计》大作业 一、编程题((每小题100分,共100分) 编写程序register.html和register.jsp。做一用户注册界面register.html,注册信息包括:用户名,年龄,性别,籍贯。然后提交到register.jsp进行注册检验,若用户名为admin,就提示“欢迎你,管理员!”,否则显示“注册成功”并显示出注册信息。 Register.html