用腳本進行開發,如果不能實時去輸入指令,就喪失了腳本的一大特色,所以對cocos2d-x程序稍微修改下,使其可以直接從控制台讀入lua指令,方便調試。
1 首先在行首加入lua的引用,如下

1 #include "main.h" 2 #include "AppDelegate.h" 3 #include "cocos2d.h" 4 #include <assert.h> 5 #include <windows.h> 6 #include <sys/stat.h> 7 #include "CCLuaEngine.h"
2 在main函數前面插入以下代碼

1 #ifdef USE_WIN32_CONSOLE 2 BOOL g_bAppRun = FALSE; 3 char g_szBuffer[1024]; 4 char g_szBuffer_copy[1024]; 5 DWORD WINAPI ThreadReadConsole(LPVOID lpParam) 6 { 7 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); 8 while(g_bAppRun) 9 { 10 DWORD dwNum = 0; 11 ReadConsoleA(hConsole, g_szBuffer, 1023, &dwNum, NULL); 12 if (dwNum) 13 { 14 g_szBuffer[dwNum] = '\0'; 15 memcpy(g_szBuffer_copy, g_szBuffer, dwNum + 1); 16 } 17 } 18 return 0; 19 } 20 21 int FetchConsoleCmd(lua_State* L) 22 { 23 if ('\0' == g_szBuffer_copy[0]) 24 { 25 return 0; 26 } 27 lua_pushstring(L, g_szBuffer_copy); 28 g_szBuffer_copy[0] = '\0'; 29 return 1; 30 } 31 #endif
3 在main函數里修改如下

1 #ifdef USE_WIN32_CONSOLE 2 AllocConsole(); 3 freopen("CONIN$", "r", stdin); 4 freopen("CONOUT$", "w", stdout); 5 freopen("CONOUT$", "w", stderr); 6 7 g_bAppRun = TRUE; 8 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadReadConsole,NULL,0,NULL); 9 #endif 10 11 // create the application instance 12 AppDelegate app; 13 lua_State* L = LuaEngine::getInstance()->getLuaStack()->getLuaState(); 14 lua_register(L, "FetchConsoleCmd", FetchConsoleCmd); 15 int ret = Application::getInstance()->run(); 16 17 #ifdef USE_WIN32_CONSOLE 18 FreeConsole(); 19 g_bAppRun = FALSE; 20 #endif
4 添加lua循環
這里使用計時器,其實可以在主循環中添加操作

1 cc.Director:getInstance():getScheduler():scheduleScriptFunc(function() 2 if FetchConsoleCmd then 3 local string = FetchConsoleCmd() 4 if string then 5 local cmd = loadstring(string) 6 if cmd then 7 xpcall(cmd, __G__TRACKBACK__) 8 end 9 end 10 end 11 end, 0, false)
5 改

1 local printByte = 36 -- "$"號的內部數字編碼 2 local debug_console = setmetatable({}, {__index = _G}) 3 4 -- 對輸入的字符串進行操作(可自行擴展) 5 function debug_console:runConsloe() 6 if FetchConsoleCmd then 7 self.str = FetchConsoleCmd() 8 self.isPrint = false 9 if self.str then 10 -- 重載 $ 符號的字符串操作 11 if string.byte(self.str, 1) == printByte then 12 self.str = string.sub(self.str, 2) 13 self.str = "return " .. self.str 14 self.isPrint = true 15 end 16 17 local cmd = loadstring(self.str) 18 if cmd then 19 -- 設置函數執行環境 20 local msg = setfenv(cmd, debug_console)() 21 if self.isPrint then 22 print(dump(msg)) 23 end 24 end 25 end 26 end 27 end 28 29 -- 更新文件 30 function debug_console.updateFile(filePath) 31 local pos = string.find(filePath,"[^%/.]*$"); 32 local module_name = string.sub(filePath, pos); 33 34 local mod = package.loaded[module_name]; 35 if not mod then 36 mod = package.loaded[module_name.."_manager"]; 37 end 38 39 package.loaded[filePath] = false; 40 local ret = require(filePath); 41 42 mod = package.loaded[module_name]; 43 if not mod then 44 mod = package.loaded[module_name.."_manager"]; 45 end 46 47 return ret; 48 end 49 50 return debug_console
這樣一來,配合一些全局函數,可以在游戲開發時對游戲實現簡單的指令調試,大大節省游戲開發時間,特別是對於我這些初學者來說,每次一個bug要去找好久,甚至在每行都加入print函數去查找問題出在哪。
但是這樣的弊端在於取不到包中定義的局部變量,具體的實現需要利用lua debug庫中的debug.getupvalue()和debug.setupvalue()來實現,由於技術有限,本身對於lua 的debug庫掌握的不是很多,而且感覺這個樣子已經
足夠開發使用,就沒有深入去研究。
如果以后有機會的話我回去完善這個東西