cocos2d-x 3.x版本号变动比較大,从改用cmake管理整个项目,到使用python集成一体化的项目工具。
这些都是我喜欢的。我能够非常easy的在我的ubuntu上面搭建好开发环境,并且根本就不用考虑IDE的事情,sublime-text or emacs足矣。唯一须要自己动手的就是制作一个比較好的调试工具。我是使用lua+cplusplus开发,所以调试就比較的难受,临时仅仅能这样,后面考虑自己实现一个远程lua调试工具。
触控有公布一款IDE,但是眼下没有linux平台的版本号。我想以后也不会做的,所以就干脆胡忽略了吧。以下就说一下怎样在cocos2d-x 3.1里面集成pbc吧。
网上有关于怎样在quick-cocos2dx里面集成pbc的,只是quick和cocos2d-x的lua集成方式不一样,并且3.x的版本号在安卓平台使用的是luajit,只是在开发人员方面还是和lua一样。这仅仅是为了提高效率。
能够简单的看一下pbc中的lua binding以下的makefile,也是能够使用luajit的。假设对luajit感兴趣,那么就自己去搜罗吧。网上的这些关于集成pbc的文章,我有粗略的看过一些,结合cocos2d-x 3.x的情况,參考意义并不大,以下我也会给出我自己的做法。
我大三的时候写过一篇关于怎样在cocos2d-x中集成luasocket的文章,应该也算是比較早的了。只是。那篇文章的做法。在如今看来的确不是什么好方法,不值得推荐。
cocos2dx从2.x的某个版本号就加入了自己的lua loader,用来载入lua engine执行的脚本,详细可參考Cocos2dxLuaLoader.cpp/.h文件里的函数。
1 int cocos2dx_lua_loader(lua_State *L) 2 { 3 std::string filename(luaL_checkstring(L, 1)); 4 size_t pos = filename.rfind(".lua"); 5 if (pos != std::string::npos) 6 { 7 filename = filename.substr(0, pos); 8 } 9 10 pos = filename.find_first_of("."); 11 while (pos != std::string::npos) 12 { 13 filename.replace(pos, 1, "/"); 14 pos = filename.find_first_of("."); 15 } 16 filename.append(".lua"); 17 18 Data data = FileUtils::getInstance()->getDataFromFile(filename); 19 20 if (!data.isNull()) 21 { 22 if (luaL_loadbuffer(L, (char*)data.getBytes(), data.getSize(), filename.c_str()) != 0) 23 { 24 luaL_error(L, "error loading module %s from file %s :\n\t%s", 25 lua_tostring(L, 1), filename.c_str(), lua_tostring(L, -1)); 26 } 27 } 28 else 29 { 30 log("can not get file data of %s", filename.c_str()); 31 } 32 33 return 1; 34 }
假设想要实现对自己项目的lua脚本进行解密或者是解压缩处理,都能够在这里下一点功夫。会有不错的收获,这部分我在后面也会做。只是还在写加密算法中,还要再等等。 - -
或许我这里给出的函数仅仅是个開始。准确的说应该是个错误的開始。不要尝试从这里思考。
为什么? 由于cocos2d-x改动了lua的文件载入器。
详细的原因是lua在5.1版本号以后完好了管理机制。
採用统一的require载入,这也不难在cocos2d-x里面看出来。能够随便看看Lua引擎入口载入运行的函数,例如以下:(CCLuaStack.cpp)
1 int LuaStack::executeScriptFile(const char* filename) 2 { 3 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 4 std::string code("require \""); 5 code.append(filename); 6 code.append("\""); 7 return executeString(code.c_str()); 8 #else 9 std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename); 10 ++_callFromLua; 11 int nRet = luaL_dofile(_state, fullPath.c_str()); 12 --_callFromLua; 13 CC_ASSERT(_callFromLua >= 0); 14 // lua_gc(_state, LUA_GCCOLLECT, 0); 15 16 if (nRet != 0) 17 { 18 CCLOG("[LUA ERROR] %s", lua_tostring(_state, -1)); 19 lua_pop(_state, 1); 20 return nRet; 21 } 22 return 0; 23 #endif 24 }
假设你须要写自己的脚本资源管理模块,那么这里就须要注意了。在android和其它平台处理的时候有明显的不同。不过不过在入口的不同,在兴许的require载入中都是一样的。由于在注冊
lua loader(也就是上面的cocos2dx_lua_loader)是一样的。
- - 当作一个友善的提示吧。然而lua本身提供的lua loader有四个,用于载入,在Lua源代码下的loadlib.c中能够找到:
1 static const lua_CFunction loaders[] = 2 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
相应luajit中也是能够找到的.源代码在luajit源代码文件夹下的lib_package.c中:
1 static const lua_CFunction package_loaders[] = 2 { 3 lj_cf_package_loader_preload, 4 lj_cf_package_loader_lua, 5 lj_cf_package_loader_c, 6 lj_cf_package_loader_croot, 7 NULL 8 };
经过cocos2d-x改动loader之后,lua在载入c lib的时候就有问题了,载入不到。
只是。还是能够通过改动lua的环境表来做到载入pbc。详细做法例如以下,改动lua_extension.c:
1 #include "pbc-master/src/pbc-lua.h" //add 2 3 static luaL_Reg luax_exts[] = { 4 {"socket.core", luaopen_socket_core}, 5 {"mime.core", luaopen_mime_core}, 6 {"protobuf.c", luaopen_protobuf_c}, // add 7 {NULL, NULL} 8 }; 9 10 void luaopen_lua_extensions(lua_State *L) 11 { 12 // load extensions 13 luaL_Reg* lib = luax_exts; 14 lua_getglobal(L, "package"); 15 lua_getfield(L, -1, "preload"); 16 for (; lib->func; lib++) 17 { 18 lua_pushcfunction(L, lib->func); 19 lua_setfield(L, -2, lib->name); 20 } 21 lua_pop(L, 2); 22 }
将下载的pbc源代码(假设是http下载的话那应该是pbc-master,假设是git clone的话那就是pbc)放到coco/lua文件夹以下去,将binding以下的pbc-lua.c复制到src文件夹以下。将pbc.h也相同拷贝过去,
然后在创建一个pbc-lua.h文件,内容就是luaopen_protobuf_c的函数声明,例如以下:
1 #ifndef PBC_LUA_H 2 #define PBC_LUA_H 3 4 #ifdef __cplusplus 5 extern "C" { 6 #endif 7 8 extern int luaopen_protobuf_c(lua_State *L); 9 10 #ifdef __cplusplus 11 } 12 #endif 13 14 #endif/* PBC_LUA_H */
因为目标平台是安卓,所以以下就去改动ndk的Android.mk文件。目标就是coco/scripting/lua-bindings以下的Android.mk文件: 改动的部分例如以下:
1 LOCAL_SRC_FILES := manual/CCLuaBridge.cpp \ 2 manual/CCLuaEngine.cpp \ 3 manual/CCLuaStack.cpp \ 4 manual/lua_debugger.c \ 5 manual/CCLuaValue.cpp \ 6 manual/Cocos2dxLuaLoader.cpp \ 7 manual/CCBProxy.cpp \ 8 manual/Lua_web_socket.cpp \ 9 manual/LuaOpengl.cpp \ 10 manual/LuaScriptHandlerMgr.cpp \ 11 manual/LuaBasicConversions.cpp \ 12 manual/LuaSkeletonAnimation.cpp \ 13 manual/lua_cocos2dx_manual.cpp \ 14 manual/lua_cocos2dx_extension_manual.cpp \ 15 manual/lua_cocos2dx_coco_studio_manual.cpp \ 16 manual/lua_cocos2dx_ui_manual.cpp \ 17 manual/lua_cocos2dx_spine_manual.cpp \ 18 manual/lua_cocos2dx_physics_manual.cpp \ 19 manual/lua_cocos2dx_deprecated.cpp \ 20 manual/lua_xml_http_request.cpp \ 21 manual/platform/android/CCLuaJavaBridge.cpp \ 22 manual/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxLuaJavaBridge.cpp \ 23 manual/tolua_fix.cpp \ 24 manual/lua_extensions.c \ 25 auto/lua_cocos2dx_auto.cpp \ 26 auto/lua_cocos2dx_extension_auto.cpp \ 27 auto/lua_cocos2dx_studio_auto.cpp \ 28 auto/lua_cocos2dx_ui_auto.cpp \ 29 auto/lua_cocos2dx_spine_auto.cpp \ 30 auto/lua_cocos2dx_physics_auto.cpp \ 31 ../../../external/lua/tolua/tolua_event.c \ 32 ../../../external/lua/tolua/tolua_is.c \ 33 ../../../external/lua/tolua/tolua_map.c \ 34 ../../../external/lua/tolua/tolua_push.c \ 35 ../../../external/lua/tolua/tolua_to.c \ 36 ../../../external/lua/luasocket/auxiliar.c \ 37 ../../../external/lua/luasocket/buffer.c \ 38 ../../../external/lua/luasocket/except.c \ 39 ../../../external/lua/luasocket/inet.c \ 40 ../../../external/lua/luasocket/io.c \ 41 ../../../external/lua/luasocket/luasocket.c \ 42 ../../../external/lua/luasocket/mime.c \ 43 ../../../external/lua/luasocket/options.c \ 44 ../../../external/lua/luasocket/select.c \ 45 ../../../external/lua/luasocket/serial.c \ 46 ../../../external/lua/luasocket/tcp.c \ 47 ../../../external/lua/luasocket/timeout.c \ 48 ../../../external/lua/luasocket/udp.c \ 49 ../../../external/lua/luasocket/unix.c \ 50 ../../../external/lua/luasocket/usocket.c \ 51 ../../../external/lua/pbc-master/src/alloc.c \ -- begin 52 ../../../external/lua/pbc-master/src/array.c \ 53 ../../../external/lua/pbc-master/src/bootstrap.c \ 54 ../../../external/lua/pbc-master/src/context.c \ 55 ../../../external/lua/pbc-master/src/decode.c \ 56 ../../../external/lua/pbc-master/src/map.c \ 57 ../../../external/lua/pbc-master/src/pattern.c \ 58 ../../../external/lua/pbc-master/src/proto.c \ 59 ../../../external/lua/pbc-master/src/register.c \ 60 ../../../external/lua/pbc-master/src/rmessage.c \ 61 ../../../external/lua/pbc-master/src/stringpool.c \ 62 ../../../external/lua/pbc-master/src/varint.c \ 63 ../../../external/lua/pbc-master/src/wmessage.c \ 64 ../../../external/lua/pbc-master/src/pbc-lua.c \ -- end
之后就不须要不论什么的改动了。也不须要在c++代码部分手动去载入pbc的库,由于一切都已经昨晚了。能够非常easy的看出来,这样的做法的优点。PS:最后别忘记将protobuf.lua复制到你的src或者是res以下,都是能够的,这个就不须要解释了。
測试是我将addressbook.pb复制到src文件夹以下,在AppDelegate.cpp中加入了比較简单的拷贝代码,将addressbook.pb复制到writablepath,原因就是后面我使用了lua io库去读pb文件。这也是直接參考pbc中的小样例写的,假设有更好的做法请告诉我。谢谢。
1 ssize_t __len = 0; 2 auto writablepath = FileUtils::getInstance()->getWritablePath()+"addressbook.pb"; 3 unsigned char *data = FileUtils::getInstance()->getFileData("assets/src/addressbook.pb","r",&__len); 4 5 FILE *fp = fopen(writablepath.c_str(),"w"); 6 fwrite(data,sizeof(char),__len,fp); 7 fclose(fp); 8 delete[] data; 9 data = NULL;
以下我给出lua部分的測试代码,实际执行是通过的,我的环境是ubuntu 14.04 x64 + ndk r9 + android
1 local tf = cc.Label:create() 2 tf:setString(package.loaded) 3 4 local writablepath = cc.FileUtils:getInstance():getWritablePath() 5 6 local addr = io.open(writablepath .. "addressbook.pb", "rb") 7 local buffer = addr:read "*a" 8 addr:close() 9 protobuf.register(buffer) 10 11 local t = protobuf.decode("google.protobuf.FileDescriptorSet", buffer) 12 local proto = t.file[1] 13 14 tf:setString(proto.name .. " " .. proto.package) 15 16 17 local addressbook = { 18 name = "Alice", 19 id = 12345, 20 phone = { 21 { number = "1301234567" }, 22 { number = "87654321", type = "WORK" }, 23 } 24 } 25 26 local code = protobuf.encode("tutorial.Person", addressbook) 27 28 local decode = protobuf.decode("tutorial.Person" , code) 29 30 tf:setString(decode.name .. " | " .. decode.id)
我使用FileUtils:getInstance():getFileData无法获取数据,所以也就改为在C++那边拷贝,知道这部分怎样使用的能够告诉我。先谢过。
pbc lua binding 文摘:http://blog.csdn.net/kaitiren/article/details/28865725