语法及变量简介


在之前的新手教学中,我们简单地介绍了BKEngine的一些基础功能。
在本章教程中,我们将为您介绍BKE的基本语法规则以及基本的变量类型,为以后的学习做好铺垫。

脚本文件

BKEngine的脚本文件包括了游戏根目录下所有的 .bkscr 文件。BKEngine会自动按照unicode顺序搜索所有以 .bkscr 后缀名结尾的脚本文件进行编译,并读取编译后的二进制文件执行游戏。

通常来说,组成一个BKE游戏的最小脚本是两个, main.bkscrmacro.bkscr (以 .bkpsr 结尾的是配置文件,不考虑在脚本文件范围中)。其余的都是用户自行增加的脚本。事实上,把脚本文件分成很多个是没有意义的,您可以通过指定跳转到某个文件中的标签,但它与在本文件中跳转并无二致。不过使用多个剧本通常易于进行游戏路线的梳理与模块的管理,所以具体怎么划分脚本其实是无所谓的,有些人喜欢一个大文件,而有些人则喜欢很多零碎的小文件,这完全取决于您自己的喜好。

为了加速启动以及保护脚本,BKE Creator带有能将 .bkscr 编译成二进制的 .bkbin 文件的编译器。而BKEngine则是通过读取 .bkbin 文件启动的,所以在您对您的游戏进行更改之后,请在BKE Creator中执行编译选项,更新您的 .bkbin 文件,从而确保您的游戏是最新的版本。

编译器会自动搜索根目录与 config.bkpsr 中设置的放置的脚本文件夹中的脚本进行编译。如果您不想将脚本全放在根目录下的话,您可以通过BKE Creator配置 config.bkpsr 中的预设脚本搜索文件夹,来更改编译器的脚本搜索路径。

基础变量

变量可视为在内存里可修改的、存在值的命名空间。
当某个已宣告变量开始使用,引擎会设定一个空间来储存所给出的值。稍后该变量不再使用时,那些空间将会回收。 变量可以用来存储诸如游戏的好感度、人物的HP、游戏进行的路线等。
在BKE中,声明变量时的写法如下:

#var 变量名;

这样所声明的变量作用域为当前闭包(“{}”内),若是在所有作用域之外直接使用 var 声明变量,那么该变量会成为全局变量。

在声明变量的同时,可以通过等号对其赋值:

#var 变量名=值;

变量的命名

在BKE中,变量名由下划线或大小写英文字符或中文字符开头,由下划线或字符或中文字符或数字组成,如:

#var a2;
#var _aa;
#var 中文变量;

但是您不能将变量命名为BKE内已经存在的保留字。例如:

#var while;      //错误,变量名是已经存在的关键字
#var whileinit;   //正确,虽然包含关键字,但是并非关键字,所以该句正确

下面是BKE的保留字清单:

      for   foreach  in  extends  do  return  global  
      while  function  propset  propget  int  this
      string  number  typeof  var  delete  true  void
      class  if  else  continue  break  false

变量的类型

对于BKE来说,与C/C++不同,您无需声明变量的类型,变量将自动被更改为赋值对象的类型,同时,在计算过程中,某些变量会自动根据上下文来改变自己的类型(仅限 voidnumberstring 之间)。

虽然BKE的变量无需声明“类型”,但在系统内部变量实际上是拥有类型的。在BKE内的内部类型如下:

void(空)

void 表示空变量,当访问字典或数据里不存在的变量时会得到这个值。

number(数值)

表示一个整数或一个浮点数(小数)。
整数格式:
  [0|0x|0X]+数字或十六进制字母(在以 0x 开头时)。

当数字以 0x0X 开头时,后面的序列会被当成十六进制的数,其余情况被当成是十进制。如:

   0xA=10  //这是十六进制
   0xc=12  //这也是十六进制
   233=233 //十进制

浮点数格式:
  [数字|小数点+数字]+[e|E+[加号或减号]+数字],同时也支持上述的整数格式。

在这种表示方法中, E 或者 e 代表的是指数,表示将前面的数字乘以 10 的 n 次幂,n 是 E 或者 e 之后的数字(带符号)。
当以数字加 . (小数点)开头时,此时变量会被当成十进制,以 0x0X 开头时,会被当成十六进制(在非十进制的情况下, 用 p 来表示以 2 为底的指数)。如:

   2.33e2=233   //即2.33x10^2
   23E-3=0.023  //即23x10^-3
   0.5=0.5      //十进制小数
   0x2.3ep10=2297    //即0x2.3e*2^10,等于2297

string(字符串)

一个不定长度,不可变的unicode字符串。由两个单引号或者双引号包围起来。例如:

   "这是一个字符串"
   "This is a string"

在字符串中 \ (反斜杠) 具有特殊的意义。跟在 \ 的字符的意义会改变。跟在 \ 后面的这种特殊的指定方式被称为转义(escape) 。

BKE的字符串默认不支持转义字符,在由一头一尾两个双引号括起来的字符串中,连起来的双引号会被当成字符串内的一个双引号而不是字符串结束符号。在以单引号括起来时,字符串支持转义字符。

要支持\n,\r,\t和 \ ” 这些转义字符,需要使用单引号将字符串括起来。比如:

   "abc"            //包含abc三个字母的字符串。
   "abc""abc"       //以一个双引号隔开的两个abc。
   "abc'abc"        //以一个单引号隔开的两个abc。
   '\r\n'           //windows下的回车换行符。
   'what\'s this'   //这里使用了 \' 来转义书写单引号

在BKE内部把所有字符用unicode格式来处理,全角字符按 1 个字符来计数,半角字符也是按 1 个字符来计数。

array(数组)

由一组变量(任意类型)组成的类型,可以嵌套。可以通过数字下标来引用元素(负下标表示从后往前数)。需要用中括号括起来,元素间由逗号隔开。
在声明数组时,并不需要对数组的大小做出定义。BKE将会自动扩展数组大小到用户所使用的大小,并将没有被赋值的元素初始化为 void

对于数组,我们可以通过其下标来对其中的元素进行索引。下标为整数,0表示数组中的第一个元素,1表示第二个对象,依此类推。如果指定负数作为索引,则将被当作从数组的结束位置开始指定元素,-1 表示最后的元素。

下面是声明一个数组的例子:

#var count=[];                   //声明一个空数组count
#var sum=["chara",100,[50,55]]   //声明一个有默认元素的数组sum

这是引用数组内元素的例子:

sum[0]    //sum[0]即数组sum的第一个元素,字符串"chara"
sum[1]    //sum[1]即数组sum的第二个元素,数字100
sum[-1]   //sum[-1]即数组sum的最后一个元素,数组[50,55]
sum[-2]   //sum[-2]即数组sum的倒数第二个元素,数字100
sum[2][1] //sum[2]即数组sum的最后一个元素,数组[50,55],同时第二个中括号内的是sum数组内这个数组的下标,即sum数组内数组的第二个元素,数字55
sum[3]    //数组的第四个元素,未定义,BKE将会自动扩展数组sum至四个大小,同时将sum[3]赋值为 void

dictionary(字典)

由一些键-值对组成的变量,键为字符串型,值可以是任意类型的变量,可以嵌套。可以通过字符串下标来引用元素。字典由 %[ 开头, ] 结尾,键-值对之间用逗号隔开,键和值之间用冒号隔开。若值被省略,则BKE将会报错。
BKE中的字典类型没有顺序,系统会自动按照Hash顺序来排序。

对于字典的声明并赋值,有两种写法:

#var book=%[page:100,price:10,name:"dict"];
#var book=%["page"=>100,"price"=>10,"name"=>"dict"];

以上两种写法都是可以的。后者的写法更类似于 Perl 。但是请您注意,后者的写法中,键的名称被双引号括了起来,而在前者的写法中,键的名称则不用加双引号。在使用后者写法的场合,请注意一定要在键的名称上加上双引号,否则系统将会报错。

对于字典的值的引用,也有两种写法:

book.price  //返回的值为10
book["price"]   //返回的值为10

. 运算符在BKE Parser中起着直接成员选择的作用,所以上面两种写法是等价的,后者的写法对于使用 Python 或 Perl 的用户来说可能会更亲切一些。

常量

在BKE中,有两个关键字: truefalse ,它们分别代表逻辑值真与逻辑值假。它们的值为1与0。

变量的自动转换

根据运算的需要,变量的类型有时候会被自动转换,但仅限于 voidnumberstring 之间。 void 会被转成0或者空字符串。

您也可以使用 number(变量名)string(变量名) 这两个命令进行强制转换(这样的强制转换不会影响原变量)。当数字转字符串时,只会显示六位,超过时会使用科学表示法或舍去小数点后更多的位数。字符串转数字会直到不合法的字符的时候停止。下面是例子:

  #string(100000)="100000"
  #string(1000000)="1e+006"
  #string(1.2345678)="1.23457"
  #string(0.000233)="0.000233"
  #string(0.0000233)="2.33e-005"
  #number("0x0a")=10

其余的转换(如number到array)都是非法的。

BKE命令的组成与语法

命令的组成

在BKE中,解释器会逐行解释脚本文件中的内容。BKE会根据关键字来判断当前的文字是命令、文本或是注释。

对于任何以 “//” (两个半角斜杠)开始,该行在 “//” 之后的文本都会被视为注释。BKE会无视所有注释,即使注释后面拥有命令关键字。

而对于命令来说,它们由一些非常基本的部分组成:

关键字
  关键字是必须出现在脚本里的词语。它们用来声明接下来的部分是一个BKE命令。通常使用半角的 @ 符号或是半角的 [ 。对于 @ 符号标记的命令而言,它只能出现在一行的行首位置,前面不能有任何东西。而以 [ 符号标记的命令则可以出现在除注释外的任何位置。对于脚本标签,则使用 * 符号进行标记。

命令名
  用于表明接下来的命令的名称,让BKE知道它应该接受哪些参数,起到什么样的作用。

参数名
  参数名用来让BKE知道接下来传给引擎的是什么参数。参数名可以按照任意的顺序写出,只要任何参数名只出现一次。参数名与参数名之间使用空格分割。

参数值
  对应参数名的值。值与参数名之间使用 = 号分割。

下面是两个完整的命令,你可以看到它们拥有上面的所有属性:

@sprite index=1 file="image/character/A/1_normal"
[sprite index=0 file="image/bg/BG25a_1280"]

除了命令与注释之外的文字,都会被当做文本显示出来。

不过还有两个例外,就是以 “#” 开头的用于声明变量的命令,以及以 “##” 开头,以 “##” 结尾(中间可以跨行)的语句块,在其中的所有语句都会被传给BKE的语法分析器(BKE Parser)来执行。

下面的例子就包含了所有可能在BKE中出现的文字:

*main
@bgm file="sound/bgm/bgm_1" loop=true
@basic_dialogbox
@sprite index=0 file="image/bg/bg_1"
@addto index=0 target=basic_layer pos=[0,0] zorder=0 opacity=255

这就是——[l][r]
属于我们的,美好的每一天。[p]

#var ending=1;

语法

对于BKE命令来说,需要注意的问题不多,大部分BKE命令使用同一套语法,它们都由它们都由关键字开始,关键字后面是命令名,而后是参数名和参数(如果这个命令接受参数的话)。

其实BKE的语法并没有太多复杂之处,真正拥有高度扩展性的是BKE Parser,我们会在以后的教程中详细介绍它,而它才是BKE强大之处的体现。

Go for the next!

事实上,目录里面并没有这一节,不过我还是想把它当成一个小剧场一样的东西继续下去:D

在学习了本章的内容之后,结合前面的东西,相信您已经可以很好的掌握BKE的语法了,但先别急着高兴,这其实只是冰山的一角=w=

感谢您阅读本章的教程,希望在后面的教程也能遇见您~