cocos2d-x 3.x版本变动比较大,从改用cmake管理整个项目,到使用python集成一体化的项目工具。这些都是我喜欢的,我可以很容易的在我的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 }