Cocos2d-x with LuaでAssets Manager Extensionを使う

# TL;DR

* Cocos2d-x内の"tests/lua-tests/src/AssetsManagerExTest/"に全て書かれている
* Manifestファイルは同じく"/tests/cpp-tests/Resources/Manifests/AMTestScene1/project.manifest"を参考にする

# 背景

Cocos2d-xの[AssetsManagerExtension](http://www.cocos2d-x.org/wiki/Assets_manager)をLuaProjectで使いたかったけれどWeb上に情報があまりなくて調べた。ちなみにCocos2d-xについては全然詳しくないです。

# AssetsManagerとは

要は、アプリをリリースした後にアセット(画像やスクリプト)をサーバから配信して更新するアレです。
細かいことは[公式サイト](http://www.cocos2d-x.org/wiki/Assets_manager)に書いてあります。

# AssetsManagerの使い方

AssetsManagerの処理の流れは以下のようになります。

1. アプリ内にあるManifestファイルを参照し、アセットが配置されているサーバのURLや現在のバージョンを取得する
2. アセットサーバから新しいManifestファイルを取得する
3. 新しいManifestファイルに従って、アセットサーバから画像やスクリプトを取得する

TL;DRに書いてあったサンプルコードを改変して以下のようにしました。
※一部画像をCocos2d-xのサンプルから取得し配置しています。

```lua:AssetsManagerExLoaderScene.lua
local AssetsManagerExLoaderScene = class("AssetsManagerExLoaderScene", cc.load("mvc").ViewBase)

function AssetsManagerExLoaderScene:onCreate()

    local ttfConfig = {}
    ttfConfig.fontFilePath = "fonts/arial.ttf"
    ttfConfig.fontSize = 40

    local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
    progress:move(display.cx, display.cy + 200)
    progress:addTo(self)

    local manifestPath = "manifests/project.manifest"
    local storagePath  = cc.FileUtils:getInstance():getWritablePath()

    local am = cc.AssetsManagerEx:create(manifestPath, storagePath)
    am:retain()

    if not am:getLocalManifest():isLoaded() then
        print("Fail to update assets, step skipped.")
        display.newSprite("assetMgrBackground1.jpg")
            :move(display.center)
            :addTo(self)
    else
        local function onUpdateEvent(event)
            local eventCode = event:getEventCode()
            if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then
                print("No local manifest file found, skip assets update.")
                display.newSprite("assetMgrBackground1.jpg")
                    :move(display.center)
                    :addTo(self)
            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
                progress:setString(strInfo)
            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.")
                display.newSprite("assetMgrBackground1.jpg")
                    :move(display.center)
                    :addTo(self)
            elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or
                    eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then
                print("Update finished.")
                display.newSprite("assetMgrBackground1.jpg")
                    :move(display.center)
                    :addTo(self)
            elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then
                print("Asset " .. event:getAssetId() .. ", " .. event:getMessage())
                display.newSprite("assetMgrBackground1.jpg")
                    :move(display.center)
                    :addTo(self)
            end
        end
        local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent)
        cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(listener, 1)

        am:update()
    end
end

return AssetsManagerExLoaderScene
```

Manifestファイルも引用して以下のようにしています。

```json:res/manifests/project.manifest
{
    "packageUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/",
    "remoteManifestUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/project_dev.manifest",
    "remoteVersionUrl" : "http://tools.itharbors.com/assets_manager/AMTestScene1/version_dev.manifest",
    "version" : "1.0.0",
    "engineVersion" : "3.0 beta",

    "assets" : {
            "Images/background1.jpg" : {
                    "md5" : "..."
            }
    },

    "searchPaths" : [
    ]
}
```

これで、このSceneに遷移したと同時にAssetsManagerが起動し、プロジェクトの直下にファイルがダウンロードされます。
参考になれば幸いです。