GameMonkey FAQ的翻译

这些东西是平时遇到的, 觉得有一定的价值, 所以记录下来, 以后遇到类似的问题可以查阅, 同时分享出来也能方便需要的人, 转载请注明来自RingOfTheC[ring.of.the.c@gmail.com]

 

GameMonkey Script FAQ

     使用lua已经1年多了, 至今还常常惊叹于其作者设计的简洁和提供给用户的一套机制, "工具就在那里摆着, 去发挥你的想象力吧"~~~ lua的接口最好的体现了提供机制而不是策略的思想. 在游戏编程精粹中, 看到一篇关于介绍脚本语言的文章, 其中不光介绍了lua, 也介绍了GameMonkey :) 大概做了一下了解, 发现国内好像尚无使用的先例, 资料也比较少, 本着学习借鉴, 开拓思路的态度, 决定翻译GameMonkey的官方资料, 希望能对需要的人有帮助.

     说明:  1. 单纯的翻译并没有太大的趣味, 我将尝试在其中和lua做适当的比较做读书笔记, 以rotc开始.

              2. 我是游戏程序员, 我的注释可能会更偏向游戏中使用脚本, 因为这是我熟悉的地方.

 

 

什么是GameMonkey?

     GameMonkey是一本专门为游戏和工具应用程序设计的脚本语言, 当然它亦适用于任何需要一个简单脚本环境支持的项目.GameMonkey常被简称和缩写为gm.

     GameMonkey的灵感和其中的基本概念来自于lua, 但是从语法角度讲, 它更接近于c. 这一特点使得它可以更容易被游戏编程人员接受. GameMonkey原生提供线程机制和states的概念.

     GameMonkey是在MIT许可证下发行的, 这是一个比较"松"的许可证, 它唯一的要求就是, 你必须让别人知道它是free的. 你可以免费使用, 修改, 发行, 出售, 详细的权利和义务请参阅MIT许可证.

     rotc: 1. GameMonkey定位明确, 为游戏和工具应用程序设计, 不是通用脚本, 所以我们不要去要求它像Python等一样全面, 只是一个简单的嵌入式脚本.

             2. 类lua语言, 语法类c, 特色是提供线程机制, 这个是学习的重点.

 

 

GameMonkey的特色是什么?

     1. 很小的代码基. 库大小只有50kb的内存占用(内存的占用受到共享库, 共享程序代码, 编译选项, 是否运行时编译的影响)

     2. 可以运行时编译GameMonkey代码, 也可以链接那些预编译过的库.

     3. 轻量级本地线程.

     4. 软实时增量式垃圾回收机制. 标记可回收的内存, 不使用引用计数.

     5. 方便c\c++函数导入和调用, 亦可以从c\c++中调用GameMonkey.

     6. 运行时调试和反馈的支持.

     7. c风格语法.

     8. 在cpu占用和内存占用 在脚本语言中是具有竞争力的. 弹性, 简洁和速度的权衡.

     9. GameMonkey本身使用flex, bison, c++编写, 在必要时易于修改.

     rotc: 1. 作为游戏用脚本, 第1,4,5,8项是必要要求, 但是要注意的是第8项中的 "弹性, 简洁和速度的权衡" 这里它的意思是牺牲了部分速度换弹性和简洁, 而在lua的特色中则强调了它作为嵌入式脚本的 "效率" 的特色.

             2. GameMonkey语言的特色是第3项, 所以应该重点去看一下.

 

 

GameMonkey不是什么?

     1. 注意, GameMonkey不是为非程序员设计的, 也就是说, GameMonkey for programmer. 当然非程序员亦可以使用程序员提供的一组简洁的功能集去配置应用程序和定义一些简单的脚本行为.

     2. GameMonkey不适用于那些处理人命关天的任务. 比如远程手术等, 还好我们游戏程序员不是处理人命关天的任务的人:)

     rotc: 其实GameMonkey虽然强调了其不是为非程序员设计的, 但是其使用困难度和lua类似.

 

 

GameMonkey的跨平台性如何?

     因为GameMonkey是用c++编写的, 所以它可以运行在诸多平台上, 什么win, linux, apple mac, xbox, sp2/3, psp, wii等.

 

 

GameMonkey从何而来?

     在2002的第一场雪, matt和greg尝试找到一种"做正确的事"的脚本语言, 我们认为的"正确的事"是指用可以通过这门脚本语言来提高游戏和工具应用程序的开发效率. 于是我们从文章, 总结, 讨论, 用户建议, 学生意见中寻找, 从java语言的进化过程, 一直到c, python, 以及一大捆的在多种游戏中使用的脚本语言, 以及他们的源代码中比较和研究. 期间, 有一门名叫lua的语言逐渐引起了我们的重视. matt在使用lua来粘合他自己的工具时获得了相当愉悦的使用体验. 我们认为lua就是我们想要的东西, 但是在LuaV4(当时的最新版本), 我们认为还有很多想要的东西它并没有提供, 我们必须自己去实现.

     比如说线程, 强壮的分析器, states的概念, 像c一样的语法和基于0开始的习惯. 所以, 没有时间了, 我们必须拥有一门基于lua概念的脚本语言. 在那以后, 一个新的console项目开始了, 它就是GameMonkey, 它的目标就是创建我们想象中的脚本语言来用于游戏和工具应用程序中. 同样, 这也意味着我们是在工作时间中来完成它的, 它将会成为公司私有的代码. 不幸的是, 几个月过后, 这个项目被取消了(在游戏行业里这很正常), matt离开了这里去了别的地方工作. 我们请求将代码发布到社区, 让其他人受益, 并且利用社区力量来继续推动它的开发. 在2003-8-12, 公司终于同意了我们的请求, 把GameMonkey的源代码在我们挑选的free software和 open source 许可授权下发布了, 我们不能出售源代码, 或者从中受益. 但我们要感谢auran公司!

 

 

为什么它叫做 GameMonkey?

     我们想要一个独一无二的名字, 这个名字必须能够体现GameMonkey是面向游戏编程, 自然的, 响亮的, 而且必须很酷等等. 在挑选之后, 我们决定使用GameMonkey作为它的名字. 选这个名字可能有其他下意识...或者潜意识的的原因, 但是我们喜欢它.

 

 

从GameMonkey的最新版本中, 我能获得什么?

     1. GameMonkey语言和一些相关的构件.

     2. 在命令行中运行GameMonkey Script的例子.

     3. lib.

     4. 一个演示单步, 查看变量和断点的调试器的例子.

     5. 一些GameMonkey Script.

 

 

GameMonkey在下一阶段要引入的特性?

      1. 新的寄存器堆栈虚拟机, 将提升效率到现在虚拟机的二倍.

      2. 内置调试器的ide.

      3. 更多的有用的工具和应用.

      4. 原生支持枚举和常量.

 

 

我能给GameMonkey提供什么帮助?

      1. 在你的项目中使用GameMonkey.

      2. 为GameMonkey制作一些工具并分享它.

      3. 向别人介绍GameMonkey.

      4. 改进增强GameMonkey的调试器, 文档, 例子, 等等.

      5. 还有很多可以做的事情, 比如提供GameMonkey的下载镜像

 

 

第三方工具

      scintilla 用于制作调试器.  http://www.scintilla.org

      Flex和Bison用于编译器.  http://www.gnu.org/software/flexhttp://www.gnu.org/software/bison/bison .

 

 

在下载的GameMonkey包中都有什么?

      gmsrc/bin                      编译器执行文件

              /doc                      文档

              /EditorHighlighters  语法高亮的编辑器

              /scripts                  脚本例子

              /src/binds               gm的绑定例子

                    /examples         程序例子

                    /gm                  GameMonkey 脚本源码

                    /gmd                调试器例子

                    /gme                脚本执行器例子

                    /gml                 GameMonkey的lib

                    /platform          平台相关头文件

     源码目录下有VS6的项目文件和workspace文件.

 

 

用GameMonkey编写的代码是什么样子的?

      1. 下面是一些用GameMonkey编写的代码:

          OnDoorTriggerEnter = function(door, objEntering)

          {

               if (objEntering == player && !door.IsOpen())  // 进入的对象是一个玩家, 而且门当前是锁着的

              {

                    door.Open();  // 开门

                    return true;

              }

              return false;

          }

 

          rotc: 为了方便理解我注释一下代码, 其实做过游戏的人来说或者会英文的人来说, 上面的东西太容易理解了, 但是我还是注释一下

                  对应的lua脚本:

                  OnDoorTriggerEnter = function(door, objEntering)

                          if objEntering == player and not door.IsOpen() then

                                door.Open()

                                return true

                          end

                          return false

                   end

 

      2. 下面再展示如何从把c函数导入到GameMonkey中

          #include "gmThread.h"

          #include "gmMachine.h"

 

           // float SquareRoot(int / float)

           int GM_CDECL SquareRoot(gmThread* a_thread) 

           // 注意, 要导入到GameMonkey中的c函数的原型必须是  int GM_CDECL funcname(gmThread* thread)

          {

               float fValue;

               GM_CHECK_NUM_PARAMS(1);  //检查, 有一个参数

 

              // 根据参数的类型, 获取参数

              if (a_thread->ParamType(0) == GM_INT)

              {

                     fValue = (float) a_thread->Param(0).m_value.m_int;

              }

              else if (a_thread->ParamType(0) == GM_FLOAT)

              {

                     fValue = a_thread->Param(0).m_value.m_float;

              }

               else

              {

                      return GM_EXCEPTION;

              }

 

              // 处理数据并返回

              a_thread->PushFloat(sqrtf(fValue));

              return GM_OK;

          }

 

          // 注意下面是怎么将SquareRoot这个c函数导入到GameMonkey中

          extern gmMachine* machine;

          machine->RegisterLibraryFunction("SquareRoot", SquareRoot);

 

         rotc: 把C函数导入脚本中, 是所有嵌入式脚本的基本功能, 等价的lua实现

                  #include “lua.h”

                  int lua_sqrtf(lua_State* L){

                       int top = lua_gettop(L);

                       if (top != 1)

                           return 0;

                       float param = lua_tonumber(L, -1);

                       lua_pushnumber(L, sqrtf(param));

                       return 1;

                   }

                   导出:

                   lua_State* L = lua_open();

                   lua_register(L, "SquareRoot", lua_sqrtf);

                   还是lua简洁些哈

 

 

      3. 下面演示c中如何调用GameMonkey中的函数

          #include "gmMachine.h"

          #include "gmCall.h"

          extern gmMachine machine;

          // 假设在GameMonkey中存在 int Add(int. int) 这样一个函数

          int AddTwoIntegers(int valueA, int valueB)

          {

               int resultInt = 0;

               gmCall call;

               if (call.BeginGlobalFunction(&machine, "Add"))

               {

                      call.AddParamInt(valueA); // 压入第一个参数

                      call.AddParamInt(valueB); // 压入第二个参数

                      call.End();                       // 调用

                      call.GetReturnedInt(resultInt); // 取返回值

               }

               return resultInt;

          }

 

          rotc: c 作为宿主, 调用脚本语言也是嵌入式脚本的基本功能, 等价的lua下的实现

          #include “lua.h”

          int AddTwoIntegers(int a, int b){

                lua_getglobal(L, “Add”);

                lua_pushnumber(L, a);

                lua_pushnumber(L, b);

                lua_pcall(L, 2, 1, 0);

                return lua_tonumber(L, -1);

           }

           注意, 这些lua的等价实现都只是功能演示, 实际中会有更多的出错判定:) 说实话, 经过上述的对比, 我更喜欢lua了, 通信一个lua stack搞定, 多么一致啊:)

 

 

如何运行第一个GameMonkey例子?

     按照传统的惯例, 我们应该先演示 hello world 小例子:)

     1)  先得在你的硬盘上解压下到的GameMonkey压缩包

     2)  创建一个 test.gm 文件

     3)  键入' print("Hello World"); '

     4)  将 test.gm保存到 ...../gmsrc/bin下

     5)  在命令行中键入 ' gme test.gm '

 

 

GameMonkey Script Executer的使用说明

     gme.exe只是一个简单的基于命令行的GameMonkey脚本解释程序, 就想lua.exe一样. 你可以使用它来编写console game 和 tool, 或者是一些演示说明脚本. gme.exe只是一个演示工具, GameMonkey真正的威力显示在当你在自己的程序中使用它来做扩展, 配置和逻辑的时候. 现在, 你可能已经想要使用gme来体验这门语言或者是用它来执行tool 脚本了, 就想.bat和.com文件一样, gme也有自己的使用语法:

    gme.exe <script file> <gme commands> <script file commands>

         <script file> --- 将要执行的脚本文件, 通常是.gm文件

         <gme commands> --- 是由以下的组合:

              -k    运行结束后按键才推出, 方便看运行结果

              -d    允许调试器的接入

              -e    在全局表'env'中加上windows 的环境变量

              -ke   在发生编译和run-time错误时按键才推出, 方便看错误信息

         <scirpt file commands> --- 任何你想传递给脚本的参数, 这些参数将被存在一个全局表'arg'里面

 

 

第一个嵌入式GameMonkey虚拟机

     这才是真正的威力所在:) 在你自己的应用中嵌入GameMonkey很简单, 就是将GameMonkey的源代码和你的应用的源代码一起编译, 然后创建一个gmMachine, 并用它执行gm脚本即可. 下面演示一下简单的应用:

     为了嵌入式GameMonkey, 你通常需要一下步骤:

      1)  将src/gm下除了gmDebugger[只有需要创建特定的调试器时才使用gmDebugger] 的所有 .cpp和 .h文件加入到你的项目中.

      2)  加入平台依赖文件, 比如win32就是 src/platform/win32/gmConfig_p.h.

      3)  加入你需要的辅助工具源文件[如binding等], 在src/binds中.

      4)  编译, 可以把他们和你的应用混在一起编译, 亦可以把GameMonkey单独编译成一个库, 这样的话, 你需要在你的应用中引入lib和配置lib的位置.

      5)  创建你自己应用的binds, 使用src/binds文件中的例子, 也可以参考FAQ和GameMonkey参考手册上的例子.

 

     下面是win32下的一个console的例子.

     1. 最小的例子

         #include “gmThread.h”   // GameMonkey Script

         int main(int argc, char* argv[]){

              gmMachine machine;                                       // 1. 创建GM虚拟机

              machine.ExecuteString(“print(‘Hello world’);”);   // 2. 编译并执行GM语句

              getchar();

              return 0;

         }

 

     2. 可以交互的例子

         #include <windows.h>

         #include <mmsystem.h>

         #include “gmThread.h”

         int main(int argc, char*argv[]) {

              //1. 创建GM虚拟机

              gmMachine* machine = new gmMachine;

 

             // 2. 从stdin中获取GM脚本

             fprintf(stdout, “Please enter one line of script\n>”);

             const int MAX_SCRIPT_SIZE = 4096;

             char script[MAX_SCRIPT_SIZE];

             fgets(script, MAX_SCRIPT_SIZE – 1, stdin);

 

            // 3. 编译, 但不马上执行GM脚本

            int errors = machine->ExecuteString(script, NULL, false, NULL);

 

            // 4. 验错

            if (errors){

                  bool first = true;

                  const char* message;

                  while ( (message = machine->GetLog().GetEntry(first) ) )

                         fprintf(stderr, “%s”GM_NL, message);

                  goto _Exit;

            }

 

            // 5. 运行

            int deltaTime = 0;

            int lastTime = timeGetTime();

            while (machine->Execute(deltaTime)){

                  int curTime = timeGetTime();

                  deltaTime = curTime – lastTime;

                  lastTime = curTime;

            }

 

            // 6. 清理

            _Exit:

            delete machine;

            getchar();

            return 0;

       }

 

总结

rotc: FQA就翻译到这里, 其实这个只是一个简单的介绍, 能从中得到的信息就是:

          1. GameMonkey是在Lua V4的基础上扩展发展起来的.

          2. luaV5对V4的改进是相当大的, 比如GameMonkey抱怨LuaV4中没有thread, LuaV5已经引入了协程, 要发展的眼光看, 哈哈.

          3. GameMonkey是对lua的扩展, 它的特色是自己实现的Thread 和 State, 其实这两个才是学习的重点, 后面会讲.

 

翻译了好几天, 将就看吧, 欢迎指出错误.

posted @ 2010-11-09 18:43  ROTC  阅读(2256)  评论(0编辑  收藏  举报