我们知道脚本语言是解除硬编码,防止重编译的利器,可以这样说,任何大型游戏都有自己的脚本系统。
想要做出一款精品游戏,脚本语言也是我们需要掌握和运用的。
较流行的脚本语言有Python,LUA,Ruby等。
LUA有着轻量,高效,接口干净等特点,学起来很快,风靡全球的《魔兽争霸3:冰封王座》就是采用的LUA脚本语言。
以下的内容非我原创,前几天发现了这篇文章,觉得总结得不错,于是我觉得偷下懒,省得自己总结,直接转载过来供大家学习了。原文地址http://blog.csdn.NET/b2b160/article/details/4799302,我将内容进行了排版,代码进行了高亮显示,更方便大家观看了。
当你希望在你的游戏开始的时候读取一些信息,以配置你的游戏,这些信息通常都是放到一个文本文件中,在你的游戏启动的时候,你需要打开这个文件,然后解析字符串,找到所需要的信息。
是的,或许你认为这样就足够了,为什么还要使用Lua呢?
应用于“配置”这个目的,Lua提供给你更为强大,也更为灵活的表达方式,在上一种方式中,你无法根据某些条件来配置你的游戏,Lua提供给你灵活的表达方式,你可以类似于这样来配置你的游戏:
- if player:is_dead() then
- do_something()
- else
- do_else()
- end
更为重要的是,在你做了一些修改之后,完全不需要重新编译你的游戏代码。
通常,在游戏中你并不需要一个单独的解释器,你需要在游戏来运行解释器,下面,让我们来看看,如何在你的代码中运行解释器:
-
-
-
- extern "C"
-
- {
- #include "lua.h"
- #include "lauxlib.h"
- #include "lualib.h"
-
-
- }
-
-
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
-
-
- luaopen_base(L);
- luaopen_io(L);
-
- const char *buf = "print('hello, world!')";
-
-
-
- lua_dostring(buf);
-
- lua_close(L);
-
- return 0;
- }
程序输出:hello, world!
有时你需要执行一段字符串,有时你可能需要执行一个文件,当你需要执行一个文件时,你可以这么做:
lua_dofile(L, "test.lua");
看,非常简单吧。
取得信息
下面让我们来看看如何从脚本中取得我们所需要的信息。
首先,让我来简单的解释一下Lua解释器的工作机制,Lua解释器自身维护一个运行时栈,通过这个运行时栈,Lua解释器向主机程序传递参数,所以我们可以这样来得到一个脚本变量的值:
- <span style="font-family:'Microsoft YaHei';font-size:16px;">lua_pushstring(L, "var");
- lua_gettatbl(L, LUA_GLOBALSINDEX);变量的值现在栈顶</span>
假设你在脚本中有一个变量 var = 100
你可以这样来得到这个变量值:
- int var = lua_tonumber(L, -1);
怎么样,是不是很简单?
Lua定义了一个宏让你简单的取得一个变量的值:
我们可以这样来取得一个变量的值:
- lua_getglobal(L, "var");
- int var = lua_tonumber(L, -1);
完整的测试代码如下:
- #include "lua.h"
- #inculde "lauxlib.h"
- #include "lualib.h"
-
-
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
-
-
-
- luaopen_base(L);
- luaopen_io(L);
-
- const char *buf = "var = 100";
-
-
- lua_dostring(L, buf);
-
-
- lua_getglobal(L, "var");
- int var = lua_tonumber(L, -1);
-
-
- assert(var == 100);
-
-
- lua_close(L);
-
-
- return 0;
- }
调用函数
假设你在脚本中定义了一个函数:
- function main(number)
- number = number + 1
- return number
- end
在你的游戏代码中,你希望在某个时刻调用这个函数取得它的返回值。
在Lua中,函数等同于变量,所以你可以这样来取得这个函数:
- lua_getglobal(L, "main");
现在,我们可以调用这个函数,并传递给它正确的参数:
- <span style="font-family:'Microsoft YaHei';">lua_pushnumber(L, 100);
- lua_pcall(L, 1, 1, 0);
-
- int result = lua_tonumber(L, -1);</span>
result 就是函数的返回值
完整的测试代码如下:
- #include "lua.h"
- #include "lauxlib.h"
- #include "lualib.h"
-
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
-
-
-
- luaopen_base(L);
-
- const char *buf = "function main(number) number = number + 1 return number end";
-
- lua_dostring(buf);
-
- lua_getglobal(L, "main");
- lua_pushnumber(L, 100);
- lua_pcall(L, 1, 1, 0);
-
- int result = lua_tonumber(L, -1);
-
- assert(result == 101);
-
- lua_close(L);
-
- return 0;
- }
脚本调用程序
Lua本身定位在一种轻量级的,灵活的,可扩充的脚本语言,这意味着你可以自由的扩充Lua,为你自己的游戏量身定做一个脚本语言。
你可以在主机程序中向脚本提供你自定的api,供脚本调用。
Lua定义了一种类型:lua_CFunction,这是一个函数指针,它的原型是:
typedef int (*lua_CFunction) (lua_State *L);
这意味着只有这种类型的函数才能向Lua注册。
首先,我们定义一个函数
- int foo(lua_State *L)
- {
-
-
-
-
- const char *par = lua_tostring(L, -1);
-
- printf("%s/n", par);
-
-
- lua_pushnumber(L, 100);
-
-
- lua_pushnumber(L, 200);
-
-
- return 2;
- }
-
- 我们可以在脚本中这样调用这个函数
-
- r1, r2 = foo("hello")
-
- print(r1..r2)
完整的测试代码如下:
- extern "C"
-
- {
- #include "lua.h"
- #include "lauxlib.h"
- #include "lualib.h"
- }
-
- int foo(lua_State *L)
- {
-
-
-
-
- const char *par = lua_tostring(L, -1);
-
- printf("%s/n", par);
-
-
- lua_pushnumber(L, 100);
-
-
- lua_pushnumber(L, 200);
-
-
- return 2;
- }
-
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
-
-
-
- luaopen_base(L);
- luaopen_io(L);
-
- lua_register(L, "foo", foo);
-
- const char *buf = "r1, r2 = foo("hello") print(r1..r2)";
-
- lua_dostring(L, buf);
-
- lua_close(L);
-
- return 0;
- }
程序输出:
hello
100200