我們知道腳本語言是解除硬編碼,防止重編譯的利器,可以這樣說,任何大型遊戲都有自己的腳本系統。
想要做出一款精品遊戲,腳本語言也是我們需要掌握和運用的。
較流行的腳本語言有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
更爲重要的是,在你做了一些修改之後,完全不需要重新編譯你的遊戲代碼。
通常,在遊戲中你並不需要一個單獨的解釋器,你需要在遊戲來運行解釋器,下面,讓我們來看看,如何在你的代碼中運行解釋器:
- //這是lua所需的三個頭文件
- //當然,你需要鏈接到正確的lib
- extern "C"
- {
- #include "lua.h"
- #include "lauxlib.h"
- #include "lualib.h"
- }
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
- // 此處記住,當你使用的是5.1版本以上的Lua時,請修改以下兩句爲luaL_openlibs(L);
- luaopen_base(L);
- luaopen_io(L);
- const char *buf = "print('hello, world!')";
- // 記住,當你使用的是5.1版本以上的Lua時請使用luaL_dostring(L,buf);
- 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, name)
我們可以這樣來取得一個變量的值:
- lua_getglobal(L, "var"); //變量的值現在棧頂
- int var = lua_tonumber(L, -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"
- #inculde "lauxlib.h"
- #include "lualib.h"
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
- // 此處記住,當你使用的是5.1版本以上的Lua時,請修改以下兩句爲luaL_openlibs(L);
- 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();
- // 此處記住,當你使用的是5.1版本以上的Lua時,請修改以下這句爲luaL_openlibs(L);
- 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)
- {
- //首先取出腳本執行這個函數時壓入棧的參數
- //假設這個函數提供一個參數,有兩個返回值
- //get the first parameter
- const char *par = lua_tostring(L, -1);
- printf("%s/n", par);
- //push the first result
- lua_pushnumber(L, 100);
- //push the second result
- lua_pushnumber(L, 200);
- //return 2 result
- 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)
- {
- //首先取出腳本執行這個函數時壓入棧的參數
- //假設這個函數提供一個參數,有兩個返回值
- //get the first parameter
- const char *par = lua_tostring(L, -1);
- printf("%s/n", par);
- //push the first result
- lua_pushnumber(L, 100);
- //push the second result
- lua_pushnumber(L, 200);
- //return 2 result
- return 2;
- }
- int main(int argc, char *argv[])
- {
- lua_State *L = lua_open();
- // 此處記住,當你使用的是5.1版本以上的Lua時,請修改以下兩句爲luaL_openlibs(L);
- 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