我们知道脚本语言是解除硬编码,防止重编译的利器,可以这样说,任何大型游戏都有自己的脚本系统。
 

想要做出一款精品游戏,脚本语言也是我们需要掌握和运用的。

较流行的脚本语言有Python,LUA,Ruby等。

LUA有着轻量,高效,接口干净等特点,学起来很快,风靡全球的《魔兽争霸3:冰封王座》就是采用的LUA脚本语言。
 

以下的内容非我原创,前几天发现了这篇文章,觉得总结得不错,于是我觉得偷下懒,省得自己总结,直接转载过来供大家学习了。原文地址,我将内容进行了排版,代码进行了高亮显示,更方便大家观看了。
 

当你希望在你的游戏开始的时候读取一些信息,以配置你的游戏,这些信息通常都是放到一个文本文件中,在你的游戏启动的时候,你需要打开这个文件,然后解析字符串,找到所需要的信息。


是的,或许你认为这样就足够了,为什么还要使用Lua呢?
 

应用于“配置”这个目的,Lua提供给你更为强大,也更为灵活的表达方式,在上一种方式中,你无法根据某些条件来配置你的游戏,Lua提供给你灵活的表达方式,你可以类似于这样来配置你的游戏:

1. if player:is_dead() then
2. do_something()  
3. else
4. do_else()  
5. end

更为重要的是,在你做了一些修改之后,完全不需要重新编译你的游戏代码。

通常,在游戏中你并不需要一个单独的解释器,你需要在游戏来运行解释器,下面,让我们来看看,如何在你的代码中运行解释器:



1. //这是lua所需的三个头文件  
2. //当然,你需要链接到正确的lib  
3.  
4. extern "C"
5.  
6. {  
7. #include "lua.h"
8. #include "lauxlib.h"
9. #include "lualib.h"
10.  
11.  
12. }  
13.  
14.  
15. int main(int argc, char
16. {  
17. lua_State *L = lua_open();  
18.  
19. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
20. luaopen_base(L);   
21. luaopen_io(L);  
22.  
23. const char *buf = "print('hello, world!')";  
24.  
25. // 记住,当你使用的是5.1版本以上的Lua时请使用luaL_dostring(L,buf);  
26.  
27. lua_dostring(buf);  
28.  
29. lua_close(L);  
30.  
31. return
32. }

程序输出:hello, world!

有时你需要执行一段字符串,有时你可能需要执行一个文件,当你需要执行一个文件时,你可以这么做:
lua_dofile(L, "test.lua");

看,非常简单吧。

取得信息

下面让我们来看看如何从脚本中取得我们所需要的信息。

首先,让我来简单的解释一下Lua解释器的工作机制,Lua解释器自身维护一个运行时栈,通过这个运行时栈,Lua解释器向主机程序传递参数,所以我们可以这样来得到一个脚本变量的值:



1. <span style="font-family:'Microsoft YaHei';font-size:16px;">lua_pushstring(L, "var"); //将变量的名字放入栈  
2. lua_gettatbl(L, LUA_GLOBALSINDEX);变量的值现在栈顶</span>

假设你在脚本中有一个变量 var = 100

你可以这样来得到这个变量值:




  1. int

怎么样,是不是很简单?

Lua定义了一个宏让你简单的取得一个变量的值:




  1. lua_getglobal(L, name) 

我们可以这样来取得一个变量的值:




  1. lua_getglobal(L, "var"); //变量的值现在栈顶  
  2. int


1. </pre><p></p><p><span style="font-family: 'Microsoft YaHei'; "><span style="font-size: 16px; ">完整的测试代码如下:</span></span></p><p><span style="font-family: 'Microsoft YaHei'; "><span style="font-size: 16px; "></span></span></p><pre name="code" class="cpp">#include "lua.h"
2. #inculde "lauxlib.h"
3. #include "lualib.h"
4.  
5.  
6. int main(int argc, char
7. {  
8. lua_State *L = lua_open();  
9.  
10.  
11. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
12. luaopen_base(L);  
13. luaopen_io(L);  
14.  
15. const char *buf = "var = 100";  
16.  
17.  
18. lua_dostring(L, buf);  
19.  
20.  
21. lua_getglobal(L, "var");  
22. int
23.  
24.  
25. assert(var == 100);  
26.  
27.  
28. lua_close(L);  
29.  
30.  
31. return
32. }

调用函数

假设你在脚本中定义了一个函数:


1. function
2. number = number + 1  
3. return
4. end

在你的游戏代码中,你希望在某个时刻调用这个函数取得它的返回值。

在Lua中,函数等同于变量,所以你可以这样来取得这个函数:


1. lua_getglobal(L, "main");//函数现在栈顶

现在,我们可以调用这个函数,并传递给它正确的参数:


1. <span style="font-family:'Microsoft YaHei';">lua_pushnumber(L, 100); //将参数压栈  
2. lua_pcall(L, 1, 1, 0); //调用函数,有一个参数,一个返回值  
3. //返回值现在栈顶  
4. int

result 就是函数的返回值

完整的测试代码如下:


1. #include "lua.h"
2. #include "lauxlib.h"
3. #include "lualib.h"
4.  
5. int main(int argc, char
6. {  
7. lua_State *L = lua_open();  
8.  
9.  
10. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下这句为luaL_openlibs(L);  
11. luaopen_base(L);  
12.  
13. const char *buf = "function main(number) number = number + 1 return number end";  
14.  
15. lua_dostring(buf);  
16.  
17. lua_getglobal(L, "main");  
18. lua_pushnumber(L, 100);  
19. lua_pcall(L, 1, 1, 0);  
20.  
21. int
22.  
23. assert(result == 101);  
24.  
25. lua_close(L);  
26.  
27. return
28. }

脚本调用程序

Lua本身定位在一种轻量级的,灵活的,可扩充的脚本语言,这意味着你可以自由的扩充Lua,为你自己的游戏量身定做一个脚本语言。

你可以在主机程序中向脚本提供你自定的api,供脚本调用。

Lua定义了一种类型:lua_CFunction,这是一个函数指针,它的原型是:

typedef int (*lua_CFunction) (lua_State *L);



这意味着只有这种类型的函数才能向Lua注册。

首先,我们定义一个函数


1. int
2. {  
3. //首先取出脚本执行这个函数时压入栈的参数  
4. //假设这个函数提供一个参数,有两个返回值  
5.  
6. //get the first
7. const char
8.  
9. printf("%s/n", par);  
10.  
11. //push the first
12. lua_pushnumber(L, 100);  
13.  
14. //push the second
15. lua_pushnumber(L, 200);  
16.  
17. //return
18. return
19. }  
20.  
21. 我们可以在脚本中这样调用这个函数  
22.  
23. r1, r2 = foo("hello")  
24.  
25. print(r1..r2)

完整的测试代码如下:


1. extern "C"
2.  
3. {  
4. #include "lua.h"
5. #include "lauxlib.h"
6. #include "lualib.h"
7. }  
8.  
9. int
10. {  
11. //首先取出脚本执行这个函数时压入栈的参数  
12. //假设这个函数提供一个参数,有两个返回值  
13.  
14. //get the first
15. const char
16.  
17. printf("%s/n", par);  
18.  
19. //push the first
20. lua_pushnumber(L, 100);  
21.  
22. //push the second
23. lua_pushnumber(L, 200);  
24.  
25. //return
26. return
27. }  
28.  
29. int main(int argc, char
30. {  
31. lua_State *L = lua_open();  
32.  
33.  
34. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
35. luaopen_base(L);  
36. luaopen_io(L);  
37.  
38. lua_register(L, "foo", foo);  
39.  
40. const char *buf = "r1, r2 = foo("hello") print(r1..r2)";  
41.  
42. lua_dostring(L, buf);  
43.  
44. lua_close(L);  
45.  
46. return
47. }

程序输出:

hello
100200


转载于:https://blog.51cto.com/qianmo/875489