[寒江孤叶丶的Cocos2d-x之旅_17]Cocos2d-x 3.2版本以上LUA脚本热更新(动态更新)解决方案

[寒江孤叶丶的Cocos2d-x之旅_17]Cocos2d-x 3.2版本以上LUA脚本热更新(动态更新)解决方案,第1张

概述原创文章,欢迎转载,转载请注明:文章来自[寒江孤叶丶的Cocos2d-x之旅系列] 博客地址:http://blog.csdn.net/qq446569365 能够进行热更新,是Lua脚本的最大优势,通过热更新能够解决诸多问题。例如App Store的审核,不用每次都提交版本,等待审核了,直接通过热更新更新游戏逻辑和素材即可。只有在进行大版本更新(修改底层C++部分)时候才需要重新提交审核。 官方

原创文章,欢迎转载,转载请注明:文章来自[寒江孤叶丶的Cocos2d-x之旅系列]

博客地址:http://blog.csdn.net/qq446569365

能够进行热更新,是Lua脚本的最大优势,通过热更新能够解决诸多问题。例如App Store的审核,不用每次都提交版本,等待审核了,直接通过热更新更新游戏逻辑和素材即可。只有在进行大版本更新(修改底层C++部分)时候才需要重新提交审核。

官方的LuaTest中提供了一个热更新的简单例程,但是实际运行却没有效果。具体原因出在官方更新的连接上,官方的写法“貌似”不支持https的链接,但是他却用了一个https://raw.github.com/samuele3hu/AssetsManagerTest/master/version 这样的链接,自然就导致更新失败了。

这里我们对lua的这个热更新的代码进行一下简单的分析,并提供一些我们在更新时候遇见的问题的解决方法,也许非常笨的方法,希望大家不要耻笑。

首先AssetsManager.cpp文件存储在,extensions目录下的Assets-Manager目录中,在cpp文件中,封装了整套热更新的功能。

首先在:

checkUpdate 成员方法中,进行了版本的比对

bool AssetsManager::checkUpdate(){    if (_versionfileUrl.size() == 0) return false;        _curl = curl_easy_init();    if (! _curl)    {        cclOG("can not init curl");        return false;    }        // Clear _version before assign new value.    _version.clear();        CURLcode res;    curl_easy_setopt(_curl,CURLOPT_URL,_versionfileUrl.c_str());    curl_easy_setopt(_curl,CURLOPT_SSL_VERIFYPEER,0L);    curl_easy_setopt(_curl,CURLOPT_WRITEFUNCTION,getVersionCode);    curl_easy_setopt(_curl,CURLOPT_WRITEDATA,&_version);    if (_connectionTimeout) curl_easy_setopt(_curl,CURLOPT_CONNECTTIMEOUT,_connectionTimeout);    curl_easy_setopt(_curl,CURLOPT_NOSIGNAL,1L);    curl_easy_setopt(_curl,CURLOPT_LOW_SPEED_liMIT,LOW_SPEED_liMIT);    curl_easy_setopt(_curl,CURLOPT_LOW_SPEED_TIME,LOW_SPEED_TIME);    res = curl_easy_perform(_curl);        if (res != 0)    {        Director::getInstance()->getScheduler()->performFunctionInCocosThread([&,this]{            if (this->_delegate)                this->_delegate->onError(ErrorCode::NETWORK);        });        cclOG("can not get version file content,error code is %d",res);        curl_easy_cleanup(_curl);        return false;    }        string recordedVersion = UserDefault::getInstance()->getStringForKey(keyOfVersion().c_str());//首先获取当前版本    if (recordedVersion == _version)//将当前版本和服务器版本进行比对 如果不一样    {        Director::getInstance()->getScheduler()->performFunctionInCocosThread([&,this]{            if (this->_delegate)                this->_delegate->onError(ErrorCode::NO_NEW_VERSION);        });        cclOG("there is not new version");        // Set resource search path.        setSearchPath();//设置文件的搜索路径,会优先搜索热更新的目录,以达到运行最新更新下来的代码        return false;    }        cclOG("there is a new version: %s",_version.c_str());        return true;}<span ><span ><span ></span></span></span>
游戏版本通过UserDefault进行存储。他的key是通过将URL进行hash运算,然后拼接到关键字后边。代码如下:

// Multiple key namesstatic std::string keyWithHash( const char* prefix,const std::string& url )//将更新网址转化为hash并和更新 当前版本的 标识文字连接到一起{    char buf[256];    sprintf(buf,"%s%zd",prefix,std::hash<std::string>()(url));    return buf;}// hashed versionstd::string AssetsManager::keyOfVersion() const//获取用于存储当前版本的key{    return keyWithHash(KEY_OF_VERSION,_packageUrl);}// hashed versionstd::string AssetsManager::keyOfDownloadedVersion() const//获取用于存储当前已经下载的版本的key{    return keyWithHash(KEY_OF_DOWNLOADED_VERSION,_packageUrl);}
通过这种方式可以根据下载地址分别存储版本号。

版本检车结束后,就开始进行下载了。下载和解压缩的方法是:downloadAndUncompress

voID AssetsManager::downloadAndUncompress(){    do    {        if (_downloadedVersion != _version)//判断当前下载的数据包的版本是否和最新版一样        {            if (! downLoad()) break;                        Director::getInstance()->getScheduler()->performFunctionInCocosThread([&,this]{                UserDefault::getInstance()->setStringForKey(this->keyOfDownloadedVersion().c_str(),this->_version.c_str());                UserDefault::getInstance()->flush();            });        }                // Uncompress zip file.        if (! uncompress())//对下载的更新压缩包进行解压缩        {            Director::getInstance()->getScheduler()->performFunctionInCocosThread([&,this]{                if (this->_delegate)                    this->_delegate->onError(ErrorCode::UNCOMPRESS);            });            break;        }                Director::getInstance()->getScheduler()->performFunctionInCocosThread([&,this] {                        // Record new version code.            UserDefault::getInstance()->setStringForKey(this->keyOfVersion().c_str(),this->_version.c_str());            UserDefault::getInstance()->setStringForKey("GameVersionStr",this->_version.c_str());//这行是我自己添加的。由于当前游戏版本的保存key 是通过hash等一些列运算所得出的,所以比较难获取,想了个比较方便的办法就是单独保存一下…………这样就可以方便的在游戏上显示当前版本了                        // Unrecord downloaded version code.            UserDefault::getInstance()->setStringForKey(this->keyOfDownloadedVersion().c_str(),"");            UserDefault::getInstance()->flush();                        // Set resource search path.            this->setSearchPath();                        // Delete unloaded zip file.            string zipfilename = this->_storagePath + TEMP_PACKAGE_file_name;            if (remove(zipfilename.c_str()) != 0)            {                cclOG("can not remove downloaded zip file %s",zipfilename.c_str());            }                        if (this->_delegate) this->_delegate->onSuccess();        });           } while (0);        _isDownloading = false;}


以上都是废话,这里开始才是重点!

说了那么多,到底应该如何使用呢?

使用起来很简单,几句话

    <span >local function onError(errorCode)  end  local function onProgress( percent )  end  local function onSuccess()  end  self.assetsManager =cc.AssetsManager:new(fileURL,"http://dzpk.57wan.cn/dzpk_logic/version.do",pathToSave)  self.assetsManager:retain()  self.assetsManager:setDelegate(onError,cc.ASSETSMANAGER_PROTOCol_ERROR )  self.assetsManager:setDelegate(onProgress,cc.ASSETSMANAGER_PROTOCol_PROGRESS)  self.assetsManager:setDelegate(onSuccess,cc.ASSETSMANAGER_PROTOCol_SUCCESS )  self.assetsManager:setConnectionTimeout(3)<span >	</span>self.assetsManager:update()</span>self.assetsManager =cc.AssetsManager:new("http://www.xxx.com/updata.zip","http://dzpk.xxx.com/version.PHP",cc.fileUtils:getInstance():getWritablePath())    <span >	</span>self.assetsManager:retain()    <span >	</span>self.assetsManager:setDelegate(onError,cc.ASSETSMANAGER_PROTOCol_ERROR )    <span >	</span>self.assetsManager:setDelegate(onProgress,cc.ASSETSMANAGER_PROTOCol_PROGRESS)    <span >	</span>self.assetsManager:setDelegate(onSuccess,cc.ASSETSMANAGER_PROTOCol_SUCCESS )    <span >	</span>self.assetsManager:setConnectionTimeout(3)<span >	</span>self.assetsManager:update()
但是仅仅是这样,是不足以满足商业项目需求的,我们需要对其进行一些简单的修改。

首先程序一上来,我们需要先判断一下版本是否需要更新,版本跨度有多大,我所用的方法是一上来,先访问服务器,提交当前本地版本号。由服务器根据我当前版本号判断版本跨度,同时返回一个更新包的下载地址。我们订的是3个以上版本下载全部数据,1-3个版本跨度,则提供不同的更新包进行下载。

如有需要可以与我交流分享下相关心得,QQ:446569365 验证:姬如千泷 或者直接回帖吧~

总结

以上是内存溢出为你收集整理的[寒江孤叶丶的Cocos2d-x之旅_17]Cocos2d-x 3.2版本以上LUA脚本热更新(动态更新)解决方案全部内容,希望文章能够帮你解决[寒江孤叶丶的Cocos2d-x之旅_17]Cocos2d-x 3.2版本以上LUA脚本热更新(动态更新)解决方案所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1008105.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存