cocos2d-js 3.0 热更新

首先搭建服务器的配置文件的目录:

cocos2d-js 3.0 热更新_第1张图片

img文件夹是用来存放图片,js文件夹是存放需要更新的js文件,res1_0_1.zip是把img和js2个文件夹打包的zip(客户端将下载该zip并解压),

js的文件夹有2个重要文件imgFiles.js(用来加载图片文件)和jsFiles.js(用来加载需要更新的js文件,客户端更新完资源后将加载该脚本):

cocos2d-js 3.0 热更新_第2张图片



jsFiles.js我的内容如下:

var jsFiles = [//每个不同版本的js脚本直接在后面追加
    "js/imgFiles.js",
    "js/app.js"
];

imgFiles.js内容我的如下:

var res2 = {//每个不同版本的图片直接在后面追加
    HelloWorld_png : "img/HelloWorld.png",
    CloseNormal_png : "img/CloseNormal.png",
    CloseSelected_png : "img/CloseSelected.png"
};

//追加更新的资源res已在原来的第一版的包中定义了
for (var i in res2) {
    res[i]=res2[i];
}
for (var i in res2) {
    g_resources.push(res2[i]);
}

解释下res变量和g_resources是客户端文件中定义的,我是先加载客户端的本地资源,然后才是加载更新的资源

project.manifest文件是下载配置的信息,我的如下:

{
"packageUrl" : "http://xxxxxxx/update_liuYao/",
"remoteManifestUrl" : "http://xxxxxxx/update_liuYao/project.manifest",
"remoteVersionUrl" : "http://xxxxxxxxx/update_liuYao/version.manifest",
"version" : "1.0.1",
"engineVersion" : "3.0 beta",
"assets" : {
        "update1" : {
            "path" : "res1_0_1.zip",
            "md5" : "1.0.1",
            "compressed" : true,
            "group" : "1"
        }
    },   
    "searchPaths" : [
    ]
}

xxxxx代表你的服务器的地址(以下雷同),解释下参数:

  • packageUrl : 远程资源的下载根路径。
  • remoteVersionUrl : 远程版本文件的路径,用来判断服务器端是否有新版本的资源。
  • remoteManifestUrl : 远程配置文件的路径,包含版本信息以及所有资源信息。
  • version : 配置文件对应的版本。
  • engineVersion : 配置文件对应的引擎版本。
  • assets : 所有资源信息。
    • path: 键代表资源的相对路径(相对于packageUrl)。
    • md5 : md5值代表资源文件的版本信息(随便写).
    • compressed : [可选项] 如果值为true,文件被下载后会自动被解压,目前仅支持zip压缩格式。
  • searchPaths : 需要添加到cocos2d引擎中的搜索路径列表。
重点解释下MD5值的意义:

如果修改MD5值,如本文把1.0.1改成1.0.1.1那么当你新增更新第2个版本资源时,project.manifest文件现在假设修改如下:

{
"packageUrl" : "http://xxxxxx/update_liuYao/",
"remoteManifestUrl" : "http://xxxxxx/update_liuYao/project.manifest",
"remoteVersionUrl" : "http://xxxxxx/update_liuYao/version.manifest",
"version" : "1.0.2",
"engineVersion" : "3.0 beta",
"assets" : {
        "update1" : {
            "path" : "res1_0_1.zip",
            "md5" : "1.0.1.1",
            "compressed" : true,
            "group" : "1"
        },

    "update2" : {
            "path" : "res1_0_2.zip",
            "md5" : "1.0.2",
            "compressed" : true,
            "group" : "1"
        }
    },   
    "searchPaths" : [
    ]
}

现在打算更新第2个版本res1_0_2.zip,那么曾经更新过res1_0_1.zip的用户将会再次冲下该文件,如果不改update1的MD5值仍然为

1.0.1的话更新过res1_0_1.zip用户将不会再次更新只更新res1_0_2.zip,而没有更新过res1_0_1.zip的用户将会2个文件都更新。

version.manifest为文件版本信息,客户端的AssetsManager首先会下载version.manifest文件,如果有更新的版本(下载后会跟客户端的project.manifest的版本信息比较),那么才会去下载project.manifest,我的如下:

{
"packageUrl" : "http://xxxxxx/update_liuYao/",
"remoteManifestUrl" : "http://xxxxxx/update_liuYao/project.manifest",
"remoteVersionUrl" : "http://xxxxxxx/update_liuYao/version.manifest",
"version" : "1.0.1",
"engineVersion" : "3.0 beta"
}


下面解说客户端:

ios模拟器测试经过更新的沙盒


首先在res下建立个project.manifest文件:

cocos2d-js 3.0 热更新_第3张图片

内容如下:

{
"packageUrl" : "http://xxxxxx/update_liuYao/",
"remoteManifestUrl" : "http://xxxxx/update_liuYao/project.manifest",
"remoteVersionUrl" : "http://xxxxxxx/update_liuYao/version.manifest",
"version" : “1.0.0”,
"engineVersion" : "3.0 beta",
"assets" : {
    },   
    "searchPaths" : [
    ]
}

在src建立AssetsManager.js文件:

/**
 * Created by zcl on 14-10-18.
 */
var __failCount = 0;
var AssetsManagerLoaderScene = cc.Scene.extend({
    _am:null,
    _progress:null,
    _percent:0,
    _percentByFile:0,
    run:function(){
        if (!cc.sys.isNative) {
            this.loadGame();
            return;
        }


        var layer = new cc.Layer();
        this.addChild(layer);
        this._progress = new cc.LabelTTF.create("0%", "Arial", 12);
        this._progress.x = cc.winSize.width / 2;
        this._progress.y = cc.winSize.height / 2 + 50;
        layer.addChild(this._progress);


        // android: /data/data/com.huanle.magic/files/
        var storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "./")+"update/";


        this._am = new jsb.AssetsManager("res/project.manifest", storagePath);
        this._am.retain();


        if (!this._am.getLocalManifest().isLoaded())
        {
            cc.log("Fail to update assets, step skipped.");
            this.loadGame();
        }
        else
        {
            var that = this;
            var listener = new jsb.EventListenerAssetsManager(this._am, function(event) {
                switch (event.getEventCode()){
                    case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                        cc.log("No local manifest file found, skip assets update.");
                        that.loadGame();
                        break;
                    case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                        that._percent = event.getPercent();
                        that._percentByFile = event.getPercentByFile();
                        cc.log(that._percent + "%");


                        var msg = event.getMessage();
                        if (msg) {
                            cc.log(msg);
                        }
                        break;
                    case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
                    case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                        cc.log("Fail to download manifest file, update skipped.");
                        that.loadGame();
                        break;
                    case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                    case jsb.EventAssetsManager.UPDATE_FINISHED:
                        jsb.fileUtils.addSearchPath(storagePath+"js");
                        cc.log("Update finished."+jsb.fileUtils.fullPathForFilename("jsFiles.js"));
                        if(jsb.fileUtils.fullPathForFilename("jsFiles.js")!="jsFiles.js"){//找到文件说明更新过资源,加载更新的资源
                            cc.loader.loadJs(["js/jsFiles.js"], function(err){
                                cc.loader.loadJs(jsFiles, function(err){
                                });
                            });
                        }
                        that.loadGame();
                        break;
                    case jsb.EventAssetsManager.UPDATE_FAILED:
                        cc.log("Update failed. " + event.getMessage());
                        //再次尝试更新
                        __failCount ++;
                        if (__failCount < 5)
                        {
                            that._am.downloadFailedAssets();
                        }
                        else
                        {
                            cc.log("Reach maximum fail count, exit update process");
                            __failCount = 0;
                            that.loadGame();
                        }
                        break;
                    case jsb.EventAssetsManager.ERROR_UPDATING:
                        cc.log("Asset update error: " + event.getAssetId() + ", " + event.getMessage());
                        that.loadGame();
                        break;
                    case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                        cc.log(event.getMessage());
                        that.loadGame();
                        break;
                    default:
                        break;
                }
            });


            cc.eventManager.addListener(listener, 1);
            this._am.update();
            cc.director.runScene(this);
        }


        this.schedule(this.updateProgress, 0.5);
    },
    loadGame:function(){
      
      cc.director.runScene(new HelloWorldScene());
    },
    updateProgress:function(dt){
        this._progress.string = "" + this._percent;
    },
    onExit:function(){
        cc.log("AssetsManager::onExit");


        this._am.release();
        this._super();
    }
});

在project.json的文件增加AssetsManager.js文件如下:

{
    "project_type": "javascript",
   "debugMode" : 1,
    "showFPS" : true,
    "frameRate" : 60,
    "id" : "gameCanvas",
    "renderMode" : 0,
    "engineDir":"frameworks/cocos2d-html5",
    "modules" : ["cocos2d"],
    "jsList" : [
        "src/resource.js",
        "src/AssetsManager.js"

    ]
}

此处resource.js可以加载本地的图片:

var res = {
    HelloWorld_png2 : "res/HelloWorld.png",
    CloseNormal_png : "res/CloseNormal.png",
    CloseSelected_png : "res/CloseSelected.png"
};
var g_resources = [];

for (var i in res) {
    g_resources.push(res[i]);
}

修改main.js文件:

cc.game.onStart = function(){
    cc.view.adjustViewPort(true);
    cc.view.setDesignResolutionSize(1536, 2048, cc.ResolutionPolicy.EXACT_FIT);
    cc.view.resizeWithBrowserSize(true);
    //load resources
    cc.LoaderScene.preload(g_resources, function () {
        cc.log("load ben di resources,加载原有本地资源完毕!");
    },this);
    var scene = new AssetsManagerLoaderScene();
    scene.run();
};
cc.game.run();

平时生活中各种琐事比较多写的博文比较少,然本人一向本着事情要么不做要做就用心做,故而本人在此希望各位同道能本着开源,有责任的态度,以此减少后学者的困扰。

另本人推荐另一篇比较好的文章:https://github.com/faint2death/cocos2d-js/blob/master/assetsmanager.md。

你可能感兴趣的:(cocos2d-x)