• 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] = '';
    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 ('' == g_szBuffer_copy[0])
    24     {
    25         return 0;
    26     }
    27     lua_pushstring(L, g_szBuffer_copy);
    28     g_szBuffer_copy[0] = '';
    29     return 1;
    30 }
    31 #endif
    main函数前插入代码

    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
    修改main函数

    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
    改写lua函数

    这样一来,配合一些全局函数,可以在游戏开发时对游戏实现简单的指令调试,大大节省游戏开发时间,特别是对于我这些初学者来说,每次一个bug要去找好久,甚至在每行都加入print函数去查找问题出在哪。

    但是这样的弊端在于取不到包中定义的局部变量,具体的实现需要利用lua debug库中的debug.getupvalue()和debug.setupvalue()来实现,由于技术有限,本身对于lua 的debug库掌握的不是很多,而且感觉这个样子已经

    足够开发使用,就没有深入去研究。

    如果以后有机会的话我回去完善这个东西

    其中大部分的实现是参照http://yestein.com/2014/09/24/%E3%80%90cocos2d-x%E3%80%91%E6%8E%A7%E5%88%B6%E5%8F%B0%E7%9B%B4%E6%8E%A5%E8%BE%93%E5%85%A5lua%E6%8C%87%E4%BB%A4%E6%94%B9%E8%BF%9B%E7%89%88/中实现的

  • 相关阅读:
    Oracle行转列,pivot函数和unpivot函数
    hive中使用spark执行引擎的常用参数
    Spark消费Kafka如何实现精准一次性消费?
    Flink 保证ExactlyOnce
    Flink的容错
    scala实现kafkaProduce1.0读取文件发送到kafka
    flume1.5的几种conf配置
    shell:ps awk杀死进程
    scala的maven项目中的pom文件
    hive开窗函数进阶
  • 原文地址:https://www.cnblogs.com/kpxy/p/11202287.html
Copyright © 2020-2023  润新知