查看: 9286|回复: 2

Nasal 语法

[复制链接]
发表于 2014-5-16 16:25:14 | 显示全部楼层 |阅读模式
1.1  print()函数
     学习大部分编程语言的第一步就是就是学习如何使用 print 打印函数。一个最简单
的函数实例如下:
      #hello.nas
      print(‘hello world’);
     Nasal 语言中的字符串被看做是一连串的字节数组而非字符,这与常用的 UTF-8
是不同的。这些字符串可以像在 C 语言当中一样被索引,但是与 C 语言不同的是,在Nasal 中字符并不是以 nul 结尾的。所以在取字符串长度的函数(size())中结果是不同
的。
1.2  变量
     声明一个变量时,使用者可以使用各种字符为变量命名,其关键字为 var。  Nasal支持数字和字符串,数组和矢量,哈希函数,以及更加复杂的如树等的数据结构。在Nasal 脚本语言中,#号后面的是注释。
var w=100;   # w 是一个数字型变量
var x="hello";   # x 是一个字符型变量
var y=[];      # y 是一组向量(也可以是数组)
     向量与哈希函数的区别在于,在向量中,每个元素是连续的,被编号了的,每一个元素都有一个数字的索引:
var my_vector=['A','B','C'];
现在需要初始化一个拥有三个元素的向量。访问向量中的每一个元素,都需要使用向量的数字索引。
var my_vector=['A','B','C'];
print (my_vector[0]);   #prints A
print (my_vector[1]);   #prints B
print (my_vector[2]);   #prints C
     由上可知,向量下标是从 0 开始的。与其他的标量相比,哈希变量不需要使用方括号,而是大括号。
var my_hash={};
     当寻找键值的时候,哈希不需要数字化的下标,但是需要符号化的下标。
var my_hash={first:’A’,second:’B’,third:’C’};
     以上句子创建了一个 hash 函数,并初始化它的三个值(A,B,C)。这三个值被分配了三个用来寻找值的键值:first,second,third。使用者可以通过寻找键值去访问每一个哈希的元素。
var my_hash={first:’A’,second:’B’,third:’C’};
print {my_hash.first};
print {my_hash.second};
print {my_hash.third};
    Nasal 支持一个’nil’来标识一个空指针:
     var foo=nil;
    在 Nasal 中,它是大小写敏感的,也就是说变量 abc 与变量 aBc 是不同的。如果写代码的时候没有给变量使用‘var’关键字,那么有可能在稍后的时候在其他的命名空间中重写该符号。所以这些被绑定的函数也需要使用‘var’关键字。
在原来的‘hello world’例子中,全局变量被定义在 hello.nas 脚本中,它需要通过使用 hello 作为前缀,才能在其他的模型当中被访问。
# hello.nas
var greeting=”Hello World”;
     如果在其他的 nasal 模型中读出 greeting 这个变量,那么必须使用 hello 前缀。
# greetme.nas
print(hello.greeting);
1.3  Nasal 语言中的函数

     函数是一片能够重复执行的代码。通过使用函数,那么编程人员就可以在这些地方取而代之的放置一个符号化的名字在代码中,并用大括号包住它。
无论什么时候这个符号化的名字在程序中被使用,程序就会跳到函数定义的地方然后开始运行它,一旦被调用的函数完成了执行,它就自动返回到调用的函数段。
正如前文所说,在定义一个 Nasal 的函数需要使用 func 关键字。接下来的代码定义了一个名为‘log_message’的空的函数体。
var log_message=func{};
     在 Nasal 中,自变量 arguments 是在‘arg’数组中默认隐式定义的。
2.2  监听器和信号灯变量
flightgear 中,绝大部分的 Nasal 文件是在启动的时候加载并执行的。只有 Nasal的子模型才会使用监听器动态加载。所以,监听器是一种连接属性树的方式。监听器会回调那些附属于属性节点的函数。当属性节点发生变化,依据监听器的类型相关的函数将会被触发。如果属性节点的值没有通过适当的属性方法进行设置的话,监听器失效。对于那些偶尔会改变的属性值,使用监听器是非常有效的。编写一个监听器的基本语句如下:
     var listener_id = setlistener(<property>, <function> [, <startup=0> [, <runtime=1>]]);
     第一个参数是一个属性节点或属性的路径。第二个参数是一个函数对象,而非一个函数调用。func 关键字将代码变成一个函数对象。第三个参数是可选的。如果它非空,那么它能够在最初调用监听器。这在启动时让回调函数取得节点值的时候很有用。
第四个参数也是可选的,默认值是 1。这意味着当属性值被写入的时候,回调函数将会执行。如果将该参数设置为 0,那么只有当前值写入到该节点的时候,函数才会执行。

当一个属性无论其值是否改变都要在每一帧写入时,这种设置方法就显得非常有用了。当执行成功是,setlistener()返回监听器的 id,执行失败时返回空值。当需要移除监听器时,需要使用其 id。语句如下:
      var num_listeners = removelistener(<listener id>);   
若执行成功,它会返回现有的活动的监听器的数量,若失败则返回空值。
在系统中,需要设置当视角在飞行器外面时,hud 将不可见。语句如下:
setlistener("/sim/current-view/view-number",func(n){setprop("/sim/hud/visibility[1]",n.
getValue() == 0) },1);
3.3  飞行器襟翼动作定义
装在飞行器机翼前缘或后缘,能够向上或向下活动,用来改变机翼升力的部分称
为襟翼。本飞行器的襟翼为后缘襟翼。当后缘襟翼向下偏转时,能够增大机翼的弯度,从而提升飞机的升力。作者用 Nasal 脚本语言对本飞行器的襟翼编写了两个函数,使得襟翼能够向上或向下转动。
     函数如下:
controls.flapsDown = func(down){
      if (down > 0) {setprop("controls/flight/flaps-lever",1);}
      elsif (down < 0) {setprop("controls/flight/flaps-lever", 0);}
      var operative = 0;
      var volts = getprop("systems/electrical/outputs/flaps");
      if (volts > 22) {operative = 1;}
      else {operative = 0;}

      if (down > 0 and operative == 1) {registerTimerControls(flapRaise);} #  设置时钟
      else {
      if(operative > 0) {setprop("controls/flight/flaps", 0);}  #  仅升起襟翼
   }
} # end function

var flapRaise = func{
      var down = getprop("controls/flight/flaps-lever");
      var airspeed = getprop("velocities/airspeed-kt");
if (down == 1 and airspeed < 250) {
     setprop("controls/flight/flaps", 1);
     return registerTimerControls(flapRaise);   #降低襟翼,计时器继续工作  }      elsif (down == 1 and airspeed > 250) {
    setprop("controls/flight/flaps", 0);
    return registerTimerControls(flapRaise);   #自动升起襟翼  }
   else {
   setprop("controls/flight/flaps", 0);
    }
} # end function



发表于 2018-4-21 16:59:22 | 显示全部楼层
2周后继续对flightgear的其它模块i进行学习
您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

快速回复 返回顶部 返回列表