cocos2dx lua 游戏热更
cocos2dx 提供了相应的示例 可参考 lua-tests 中的 AssetsManagerExTest.lua
实现详解:
1. 客户端,配置相应的 project.manifest 文件,首次更新时会检测该文件,工程目录如下
project.mainfest 内容如下:
{
"packageUrl" : "http://192.168.1.8:8080/Download/Package/",
"remoteManifestUrl" : "http://192.168.1.8:8080/Download/version/project.manifest",
"remoteVersionUrl" : "http://192.168.1.8:8080/Download/version/version.manifest",
"version" : "1.0.0",
"engineVersion" : "3.0 beta",
"assets" : {
"Images/background1.jpg" : {
"md5" : "..."
}
},
"searchPaths" : [
]
}
2. 服务端, 服务端新建两个文件夹 version, Package
version 用于存放更新检测配置文件 project.manifest 与 version.manifest
Package 用于存放更新下载文件 如 png 资源图,lua 文件等
project.manifest 内容如下
{
"packageUrl" : "http://192.168.1.8:8080/Download/Package/",
"remoteManifestUrl" : "http://192.168.1.8:8080/Download/version/project.manifest",
"remoteVersionUrl" : "http://192.168.1.8:8080/Download/version/version.manifest",
"version" : "1.0.2",
"assets" : {
"blocks.png" : {
"md5" : "....."
},
"abc.zip" : {
"md5" : ".....",
"compressed" : true
},
"ttt.png" : {
"md5" : "....."
}
},
"searchPaths" : [
]
}
服务器 Download/Package 文件夹下存放 blocks.png, abc.zip 等文件
注:compressed 参数 true 表示下载完后直接对 zip 进行解压
version.manifest 内容如下
{
"packageUrl" : "http://192.168.1.8:8080/Download/Package/",
"remoteManifestUrl" : "http://192.168.1.8:8080/Download/version/project.manifest",
"remoteVersionUrl" : "http://192.168.1.8:8080/Download/version/version.manifest",
"version" : "1.0.2",
}
说明:.manifest 文件中的内容说明
key | 作用 |
---|---|
packageUrl | 更新包的url,更新时会从这个url 对应的地址下载更新文件 |
remoteManifestUrl | project.manifest的url,更新时会根据这个文件进行检测要更新哪些文件 |
remoteVersionUrl | 这个文件和project.manifest一个意思,但是比project.manifest更简洁, |
version | 游戏版本,本地版本号小与服务器版本号则进行更新 |
engineVersion | 引擎版本,写不写无所谓 |
assets | 所有的文件名和他的md5值,在更新的时候会比对本地和远程的md5值,不一致则会更新,否则不更新 |
更新时会先从本地加载 project.manifest 文件,从中读取到 remoteManifestUrl 及 remoteVersionUrl 后,从对应的 url 下载 project.manifest 与 version.manifest 文件, 如果 本地 project.manifest 中的 版本号小于服务器的版本号,则进行更新
3. 客户端实现代码
function UILoading:updateCheck(layer)
local ttfConfig = {}
ttfConfig.fontFilePath = "fonts/FZY3JW.TTF"
ttfConfig.fontSize = 40
local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
progress:setPosition(cc.p(960, 540 + 50))
progress:setColor(cc.c3b(0, 255, 0 ))
layer:addChild(progress)
local assetsManagerEx = cc.AssetsManagerEx:create(manifestPath, cc.FileUtils:getInstance():getWritablePath() .. storagePath)
assetsManagerEx:retain()
local localManifest = assetsManagerEx:getLocalManifest()
print("当前版本:".. localManifest:getVersion())
if not assetsManagerEx:getLocalManifest():isLoaded() then
print("Fail to update assets, step skipped.")
print("本地资源错误,请重新下载游戏。")
else
local function onUpdateEvent(event)
local eventCode = event:getEventCode()
print("====== assetsmanagerex error code:", eventCode)
--[[ cc.EventAssetsManagerEx.EventCode = {
ERROR_NO_LOCAL_MANIFEST = 0,
ERROR_DOWNLOAD_MANIFEST = 1,
ERROR_PARSE_MANIFEST = 2,
NEW_VERSION_FOUND = 3,
ALREADY_UP_TO_DATE = 4,
UPDATE_PROGRESSION = 5,
ASSET_UPDATED = 6,
ERROR_UPDATING = 7,
UPDATE_FINISHED = 8,
UPDATE_FAILED = 9,
ERROR_DECOMPRESS = 10
} ]]
if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
print("发生错误:本地找不到manifest文件", eventCode)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then
print("更新进度=" .. event:getPercent(), eventCode)
local assetId = event:getAssetId()
local percent = event:getPercent()
local strInfo = ""
if assetId == cc.AssetsManagerExStatic.VERSION_ID then
strInfo = string.format("Version file: %d%%", percent)
elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then
strInfo = string.format("Manifest file: %d%%", percent)
else
strInfo = string.format("%d%%", percent)
end
progress:setString(strInfo)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST then
print("发生错误:下载 manifest文件失败", eventCode)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then
print("发生错误:解析 manifest文件失败", eventCode)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE then
print("已经是最新版本了,进入游戏主界面", eventCode)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
print("更新完毕,重新启动", eventCode)
-- app:run()
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
print("发生错误:更新失败", eventCode)
end
end
local listener = cc.EventListenerAssetsManagerEx:create(assetsManagerEx,onUpdateEvent)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
-- 检查版本并升级
assetsManagerEx:update()
end
end
只需要调用 updateCheck() 即可
----------------------------------------------------------------------------------------------------------------------------------
今日在查看更新相关底层代码时发现还有一个 groupVersions 参数 该参数是写在 version.manifest 文件中的
"groupVersions" : {
"ver_niuniu" : "1.0.0"
}
感觉用处不大,但可做为游戏版本控制 比如大厅版本 本地与服务器都是 1.1.0 但是游戏版本 为1.1.1 此时还是会进行更新。