cocos2d-lua 控制台输入Lua指令方便调试
用脚本进行开发,如果不能实时去输入指令,就丧失了脚本的一大特色,所以对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库掌握的不是很多,而且感觉这个样子已经
足够开发使用,就没有深入去研究。
如果以后有机会的话我回去完善这个东西
祝我无坚不摧,祝我百毒不侵,祝我狼心狗肺,祝我逍遥快活。