Snake脚本引擎简介:
一、高级代码编写:
1,语法类似于C。
2,支持函数定义,函数调用,数组,表达式,循环,分支。
3,弱类型(lua也是),内建类型有string,int,float,boolean
如定义变量 var x;可以给x赋的值有 x="你好Snake"; x=32; x=32.23; x=true;
4,内建35个运算符,适用于所有的表达式,如位运算>> 逻辑运算&& 赋值运算 |= 等等,运算符优先级简化为4级,
由高到低为 单目运算>算数运算>关系运算>逻辑运算,如果你写代码是不确定运算符的优先级保险起见加上括号就不会有错
5,支持转义字符输入。
6,支持注释,如行注释符// 及块注释符 /* */
二、低级代码编写:
1,语法类似于8086汇编,但要比它简单的多,有33种虚拟指令可供选择,并且可以定义方法
演示一个完整的加法函数及函数调用(分号是行注释符):
myAdd()
{
param y ;函数参数y
param x ;函数参数x
Add x, y ;将y的值与x相加并赋给x
Mov _RetVal, x ;将x值赋给寄存器(只有一个寄存器即_RetVal)
Ret ; 方法返回符(可以省略)
}
_Main()
{
var x ;定义局部变量x
var y ;定义局部变量y
var z ;定义局部变量
Mov x, 2 ;将2赋给x
Mov y, 3 ;将3赋给y
Push x ;将x压栈,调用方法需要将参数压栈
Push y ;将y压栈
Call myAdd ;调用方法
Mov z, _RetVal ;将寄存器的值赋给z
}
判断和分支的低级代码我就不给出了,想了解的话可以先写高代码,再用编译器编译成低级代码(在编译器中输入参数-A)
再参照低级代码来研究
话说回来,为什么要设计低级代码呢,干脆直接写高级代码多方便,之所以这样设计是由于编译器编译跳转分支那部分都非常的
精简,运行速度非常的快,但是编译表达式就比较繁琐,虽然在3个星期前我压根不知道什么叫编译原理,但是通过写脚本的词法分析,
语法分析,汇编等程序我才发现它的难度和复杂度超出想象好几倍,当前最流行的编译器如C++编译器是用状态机进行语法分析,在表
达式的编译上做足了优化,可是我才是个初学者,为了加快研发速度我使用了半状态机半递归下降的方式进行编译,所以在效率上没有做
太多优化,所以如果您想写复杂表达式求值并需要快速运行的代码,还是建议用低级代码编写,最后可以和高级代码进行合并,用汇编器
汇编成二进制。
三、脚本虚拟机(SVM)
1,虚拟机的执行是基于字节码的,只有一个寄存器_RetVal 用来存放返回值,运行时堆栈是用来进行函数调用的
大小默认是512K,可以自己更改 比如在低级代码上头部加入关键字 SetStackSize 1024 虚拟机会根据设置来修改堆栈大小
2,和主游戏引擎通信是基于方法调用,需要自己写方法库类,这个类需要继承Lib.class, 在自己的方法库中实现方法,考虑到效率,
没有通信是没有用到对象,并且也不是基于RTTI机制,所以使用时务必要注意2点,这两点写在测试包里,可以去看一下
3,错误处理也是考虑到效率没有基于java的异常,而是只打印错印并且虚拟机会正常运行,可是一旦打印出错误,需要做的就是停
下运行的程序 检查脚本有没有,或者是虚拟机的核心执行单元有没有BUG如果不这样做,那么后面的脚本数据已经成脏数据,
会对游戏逻辑造成潜在的危险。
4,多线程:脚本引擎能加载多个脚本并发执行,并且每个线程有个优先级,优先级高的脚本能分到更多的时间片,SVM来管理这些线程
的运行,并且主游戏引擎能方便的操作脚本虚拟机加载,暂停,停止,恢复这些脚本线程。(0.8版提供多线程功能)
5,运行方式:主游戏引擎在while循环中,每次调用虚拟机的runScript(int time)方法,通过传入时间片来决定虚拟机在这个循环
周期运行多长时间,所以脚本里就可以写这样的循环while(true)也就是脚本有自己的逻辑死循环,但是它不会干扰主引擎的逻辑死
循环,因为在传入的时间片运行完时,脚本引擎会自动跳出来让主引擎继续运行下一个循环,而这些对编程人员都是透明的。
四、最后
希望对此有兴趣的人能来共同维护这个脚本引擎,说真的,要不是自己的那点热情,做这么具有挑战的东西我想都不敢想,还好东西
总算完成了,并且经行了一些测试,并将这个引擎用到了公司的游戏中,bug还有没有我不太敢保证,毕竟是最近才做出来,所以希望
大家一起来维护它的版本,并且有好的改进策略一定要告诉我,我期待你们将优秀的编程思想注入其中,让它永远充满活力。
如果在使用的时候有什么困难或bug就欢迎联系我,我们一起探讨一下。