cocos2dx 3.5での実験
やりたいこと
- ブラウザと同じぐらいに更新を行いやすくしたい。
- アップデートなしでロジックの修正をできるようにしたい。
以上2点の検証をAssetsManagerExをつかってどこまでできるのか
検証してみました。(androidのみ)
クライアント側
こちらの記事をみてassetmanagerexすごい!!
luaコードもassetに含められるみたいなので実験してみました。
(iosは未確認)
cc.FileUtils:getInstance():setPopupNotify(false)
cc.FileUtils:getInstance():addSearchPath("src/")
cc.FileUtils:getInstance():addSearchPath("res/")
cc.FileUtils:getInstance():addSearchPath(cc.FileUtils:getInstance():getWritablePath() .. "test/src/")
cc.FileUtils:getInstance():addSearchPath(cc.FileUtils:getInstance():getWritablePath() .. "test/res/")
require "config"
require "cocos.init"
local function main()
require("app.MyApp"):create():run()
end
local status, msg = xpcall(main, __G__TRACKBACK__)
if not status then
print(msg)
end
assetのダウンロード先をtestにしたのでそれにあわせてパスを通した
local MainScene = class("MainScene", cc.load("mvc").ViewBase)
MainScene.RESOURCE_FILENAME = "MainScene.csb"
MainScene.MANIFEST = "project.manifest"
MainScene.STRAGE_PATH = "test"
function MainScene:onCreate()
local root = self:getResourceNode()
local progress = root:getChildByName("Loading")
local text = root:getChildByName("LoadingLabel")
local am = cc.AssetsManagerEx:create(MainScene.MANIFEST, cc.FileUtils:getInstance():getWritablePath() .. MainScene.STRAGE_PATH)
am:retain()
if not am:getLocalManifest():isLoaded() then
printInfo("Fail to update assets, step skipped.")
self:getApp():enterScene("HomeScene")
else
local function onUpdateEvent(event)
local eventCode = event:getEventCode()
printInfo("AssetmanagerEx:EventCode:%d:%s", eventCode, event:getMessage())
if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
print("No local manifest file found, skip assets update.")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then
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
printInfo("progress:%f", percent)
text:setString(strInfo)
progress:setPercent(percent)
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or
eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then
print("Fail to download manifest file, update skipped.")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.NEW_VERSION_FOUND then
print("Fail to download new version nound")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ASSET_UPDATED then
print("asset updated")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FAILED then
print("update failed")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DECOMPRESS then
print("error decompress")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or
eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
print("Update finished.")
self:getApp():enterScene("TestScene")
elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
print("Asset ", event:getAssetId(), ", ", event:getMessage())
end
end
local listener = cc.EventListenerAssetsManagerEx:create(am, onUpdateEvent)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)
am:update()
end
end
return MainScene
ここで実際にTestScene.luaはサーバ側にあります。
いろいろとeventcodeの条件分岐があるけど、manifestのパースエラーとか
versionのmanifestがないとかのエラーなのでとりあえずログをはくだけに
MainScene.cbsはcocos builderで作成した適当なページです。
ローディングの実験もしたかったのでプログレスバーを含めました。
{
"packageUrl" : "http://cocos2dx.xperia.biz/packageUrl",
"remoteManifestUrl" : "http://cocos2dx.xperia.biz/remoteManifestUrl.manifest",
"remoteVersionUrl" : "http://cocos2dx.xperia.biz/remoteVersionUrl.manifest",
"version" : "1.0.0",
"engineVersion" : "3.5",
"assets" : {
},
"searchPaths" : [
]
}
ローカルのマニフェストファイルはこんな感じに
サーバ側
いよいよ問題のサーバ側の設定に
$ tree ./
./
├── cdn
│ ├── images
│ │ ├── Cute-Ball-Favorites-icon.png
│ │ └── ball.png
│ ├── res
│ │ └── TestScene.csb
│ ├── src
│ │ └── app
│ │ └── views
│ │ └── TestScene.lua
│ └── zip
│ └── compressed.zip
├── remoteManifestUrl.manifest
└── remoteVersionUrl.manifest
7 directories, 7 files
今回はmanifestべたで書いています。
{
"packageUrl" : "http://cocos2dx.xperia.biz/cdn",
"remoteManifestUrl" : "http://cocos2dx.xperia.biz/remoteManifestUrl.manifest",
"remoteVersionUrl" : "http://cocos2dx.xperia.biz/remoteVersionUrl.manifest",
"version" : "1.1.5",
"engineVersion" : "3.5",
"assets" : {
"images/Cute-Ball-Favorites-icon.png" : { "md5" : "....." },
"images/ball.png" : { "md5" : "..." },
"zip/compressed.zip" : { "md5" : "...", "compressed" : true },
"src/app/views/TestScene.lua" : { "md5" : "b84dfe61005304a7dba589896bf16c6e" },
"res/TestScene.csb" : { "md5" : "..." }
},
"searchPaths" : []
}
versionの値は試行錯誤した回数ということでお察しを
{
"packageUrl" : "http://cocos2dx.xperia.biz/packageUrl",
"remoteManifestUrl" : "http://cocos2dx.xperia.biz/remoteManifestUrl.manifest",
"remoteVersionUrl" : "http://cocos2dx.xperia.biz/remoteVersionUrl.manifest",
"version" : "1.1.5",
"engineVersion" : "3.5"
}
local TestScene = class("TestScene", cc.load("mvc").ViewBase)
TestScene.RESOURCE_FILENAME = "TestScene.csb"
function TestScene:onCreate()
local root = self:getResourceNode()
display.newSprite("images/Cute-Ball-Favorites-icon.png")
:addTo(root)
display.newSprite("zip/compressed/info-148099_1280.png")
:addTo(root)
end
return TestScene
zip圧縮したものもちゃんと解凍して使えた。
そしてここで重要なのがversionをかえただけでは更新されなくて
md5の値に差があると更新してくれる作りらしい
md5の値がkeyとなっていると思ってよさそう。
TestScene.luaだけmd5ちゃんといれているのは
最初は他と同じで...として、versionだけ更新していたけど
更新されいと気づいたので
画像はいちおうgoogle検索でライセンス「改変後の再利用が許可された画像」
にして実験しました。
試していないけど、fontも音声もassetに含められそう。
androidでしか試してないけど何でも更新できるのではと感じるほど。
感想
なんでも更新できる。
luaを配信する際は難読化は必須かなと。
極論、インストール型ゲームプラットフォームアプリをつくれる気がする。