cocos2d-x+LUA 游戏热更新
发表于2016-07-01
注意事项:游戏全部逻辑均为lua实现(可以通过热更新更新游戏全部内容),lua所需底层接口为C++及平台实现(java/OC/win32)。
1、LUA脚本目录设置,我把脚本文件夹命名为Luascript
我在app包里、apk包里都打包了一份Luascript文件夹。
appdelegate里面设置LUA文件搜索路径,优先搜索下载目录(ios放置在Library/Caches下,android在手机存储里面创建一个目录例如:渠道_游戏名/Caches)
程序启动时设置lua的搜索路劲:
a、设置LUA优先搜索路径为上述设置的Caches路径下的Luascript文件夹,其次再搜索app、apk里面事先打包进去的Luascript文件夹。
b、
//kt_开头的方法为平台方法,需要分平台实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | void initLua() { CCLuaEngine* pEngine = CCLuaEngine::defaultEngine(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine); //library cache path //分平台实现不同平台下的library目录路径的获取 std::string cachePath = kt_library_path() + "/Caches/"; //app、apk path std::string bundleLuaPath = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(LUA_DIR_NAME); std::string cacheLuaPath = cachePath + "LuaScript"; std::string cacheXMLPath = cachePath + "XML"; //check std::string oldVersion = CCUserDefault::sharedUserDefault()->getStringForKey("AppVersion"); //分平台实现了getVersion方法以获取不同平台下的bundle 版本号 std::string newVersion = KTChannel_Help::sharedInstance()->getVersion(); if (oldVersion.empty()) { CCUserDefault::sharedUserDefault()->setStringForKey("AppVersion", newVersion); CCUserDefault::sharedUserDefault()->flush(); kt_remove_dir(cacheLuaPath.c_str()); kt_remove_dir(cacheXMLPath.c_str()); } else { if (kt_compareVersion(oldVersion, newVersion)) { //newVersion > oldVersion CCUserDefault::sharedUserDefault()->setStringForKey("AppVersion", newVersion); CCUserDefault::sharedUserDefault()->flush(); kt_remove_dir(cacheLuaPath.c_str()); kt_remove_dir(cacheXMLPath.c_str()); } else { } } pEngine->addSearchPath(cacheLuaPath.c_str(), bundleLuaPath.c_str()); std::string tempPath = cacheLuaPath + "/version.lua"; if (kt_isFileExist(tempPath.c_str())) { luaFilePathPrefix = cacheLuaPath + "/"; } else { luaFilePathPrefix = bundleLuaPath + "/"; } } void kt_setLuaSearchPath(std::string firstPath, std::string secondPath) { CCLuaEngine* pEngine = CCLuaEngine::defaultEngine(); pEngine->addSearchPath(firstPath.c_str(), secondPath.c_str()); } //修改了一下引擎里面的搜索路劲代码 void CCLuaEngine::addSearchPath(const char* path1, const char* path2) { lua_getglobal(m_state, "package"); /* stack: package */ lua_getfield(m_state, -1, "path"); /* get package.path, stack: package path */ const char* cur_path = lua_tostring(m_state, -1); lua_pop(m_state, 1); /* stack: package */ lua_pushfstring(m_state, "%s;%s/?.lua;%s/?.lua", cur_path, path1, path2); /* stack: package newpath */ lua_setfield(m_state, -2, "path"); /* package.path = newpath, stack: package */ lua_pop(m_state, 1); /* stack: - */ } |
获取游戏在userdefault.xml里面存储的版本号AppVersion,若此值为空,那么用户第一次下载次游戏,此时为了安全起见删除Caches里面的Luascript文件夹。
若此值非空,则和程序包的bundle版本号比较BundleVersion, 若AppVersion 大于BundleVersion,则不用处理,
若AppVersion小于BundleVersion则需要删除Caches下的Luascript文件夹来保证本地版本的最新.
此处这样做的目的是为了解决用户在1.0版本时热更新过Lua,之后用户在商店里更新了2.0版本的游戏包(只会更新.app Library等其余三个目录不会变),此时2.0版本里面的lua版本号可能低于
本地lua版本号,虽然游戏版本号比较新但是游戏包中事先打包的lua版本号比较旧。
c、设定了搜索路径后,我们需要读取本地该渠道的lua的版本号来对比服务端的该渠道(例如appstore)lua版本号,以此来决定是否需要下载更新包,需要的话就下载加密的zip包到本地解压到Caches里来覆盖之前的Luascript,当然我们程序里面的所有lua文件都是RSA加密的,放心吧!
本地的一份版本配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | --INT.lua require "Language/language_zh-Hans" g_platform = { id = 1, --平台id name = "INT", type = "-a", typeID = 2, flag = "XXXXXX", agent = "XXXXXX", autoUpdate = true, updatePath = "/Update/", version = { [1] = 10001, [2] = 3, [3] = 0, [4] = 6, }, isAutoLogin = false, isSingleUser = true, --是否单账号 isHaveGuest = false, --是否支持游客登陆 isHaveLoginSDK = false, --是否介入第三方SDK serverHost = "http://www.XXXX.com", fcm = 0, game = "XXXX", ftpPath = "http://10.0.9.14", battlePath = ":9110/battle_report/query?report_id=", gameURL = "http://k.XXXXX.com", giftUrl = "http://www.XXXXX.com/gamecard/show/id/2", recharge = function( ) -- KTTipLayer:sharedTip():showText("内网测试服不支持充值!", ccc3(255, 255, 0)) require "Layer/IAPLayer" IAPLayer:show() end, } |
第一行为该渠道最新版本的lua的版本号,第二行为该最新lua版本号所兼容的最低客户端版本号(此处兼容可以控制客户端强制更新,例如程序员犯了致命错误BUG,急需修复C++/java/OC代码)
第二行的版本号的作用很关键
2、最后就需要实现一个下载实现以及更新等待界面.
3、更新完成后delete LUA虚拟机然后再重新运行第一个scene,就可以在线更新后进入游戏、、
看了上面的文章 热爱游戏创作的你是不是已经开始热血沸腾了呢?是不是迫不及待的想加入游戏团队成为里面的一员呢?
福利来啦~赶快加入腾讯GAD交流群,人满封群!每天分享游戏开发内部干货、教学视频、福利活动、和有相同梦想的人在一起,更有腾讯游戏专家手把手教你做游戏!
腾讯GAD游戏程序交流群:484290331

