cocos2d-x+LUA 游戏热更新

发表于2016-07-01
评论0 2.9k浏览
注意事项:游戏全部逻辑均为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,
}
       有些小伙伴不方便搭建PHP服务端接口,那么你可以做一个版本文件放置在FTP上.

  

     update.lua文件内容至少需要两行:

 
        第一行为该渠道最新版本的lua的版本号,第二行为该最新lua版本号所兼容的最低客户端版本号(此处兼容可以控制客户端强制更新,例如程序员犯了致命错误BUG,急需修复C++/java/OC代码)
第二行的版本号的作用很关键
2、最后就需要实现一个下载实现以及更新等待界面.
3、更新完成后delete LUA虚拟机然后再重新运行第一个scene,就可以在线更新后进入游戏、、
     看了上面的文章 热爱游戏创作的你是不是已经开始热血沸腾了呢?是不是迫不及待的想加入游戏团队成为里面的一员呢?
     福利来啦~赶快加入腾讯GAD交流群,人满封群!每天分享游戏开发内部干货、教学视频、福利活动、和有相同梦想的人在一起,更有腾讯游戏专家手把手教你做游戏!

腾讯GAD游戏程序交流群:484290331Gad游戏开发核心用户群

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引