先标记上文章的出处,嘿休嘿,感谢这位:https://www.jianshu.com/p/fe54ca980384

cocos creator版本: 1.9.1

首先建立大厅的项目

添加文件  SubgameManager .js  文件内容如下,该文件管理的是子游戏的更新

const SubgameManager = {

_storagePath: [],

_getfiles: function(name, type, downloadCallback, finishCallback) {

this._storagePath[name] = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'ALLGame/' + name);

this._downloadCallback = downloadCallback;

this._finishCallback = finishCallback;

this._fileName = name;

/// 替换该地址

var UIRLFILE = "http://192.168.1.15/subGame/" + name + "/";

var filees = this._storagePath[name] + '/project.manifest';

var customManifestStr = JSON.stringify({

'packageUrl': UIRLFILE,

'remoteManifestUrl': UIRLFILE + 'project.manifest',

'remoteVersionUrl': UIRLFILE + 'version.manifest',

'version': '0.0.1',

'assets': {},

'searchPaths': []

});

var versionCompareHandle = function(versionA, versionB) {

var vA = versionA.split('.');

var vB = versionB.split('.');

for (var i = 0; i < vA.length; ++i) {

var a = parseInt(vA[i]);

var b = parseInt(vB[i] || 0);

if (a === b) {

continue;

} else {

return a - b;

}

}

if (vB.length > vA.length) {

return -1;

} else {

return 0;

}

};

this._am = new jsb.AssetsManager('', this._storagePath[name], versionCompareHandle);

if (!cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {

this._am.retain();

}

this._am.setVerifyCallback(function(path, asset) {

var compressed = asset.compressed;

if (compressed) {

return true;

} else {

return true;

}

});

if (cc.sys.os === cc.sys.OS_ANDROID) {

this._am.setMaxConcurrentTask(2);

}

if (type === 1) {

this._updateListener = new jsb.EventListenerAssetsManager(this._am, this._updateCb.bind(this));

} else if (type == 2) {

this._updateListener = new jsb.EventListenerAssetsManager(this._am, this._checkCb.bind(this));

} else {

this._updateListener = new jsb.EventListenerAssetsManager(this._am, this._needUpdate.bind(this));

}

cc.eventManager.addListener(this._updateListener, 1);

if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {

var manifest = new jsb.Manifest(customManifestStr, this._storagePath[name]);

this._am.loadLocalManifest(manifest, this._storagePath[name]);

}

if (type === 1) {

this._am.update();

this._failCount = 0;

} else {

this._am.checkUpdate();

}

this._updating = true;

console.log('更新文件:' + filees);

},

// type = 1

_updateCb: function(event) {

var failed = false;

let self = this;

switch (event.getEventCode()) {

case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:

/*0 本地没有配置文件*/

console.log('updateCb本地没有配置文件');

failed = true;

break;

case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:

/*1下载配置文件错误*/

console.log('updateCb下载配置文件错误');

failed = true;

break;

case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:

/*2 解析文件错误*/

console.log('updateCb解析文件错误');

failed = true;

break;

case jsb.EventAssetsManager.NEW_VERSION_FOUND:

/*3发现新的更新*/

console.log('updateCb发现新的更新');

break;

case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:

/*4 已经是最新的*/

console.log('updateCb已经是最新的');

failed = true;

break;

case jsb.EventAssetsManager.UPDATE_PROGRESSION:

/*5 最新进展 */

self._downloadCallback && self._downloadCallback(event.getPercentByFile());

break;

case jsb.EventAssetsManager.ASSET_UPDATED:

/*6需要更新*/

break;

case jsb.EventAssetsManager.ERROR_UPDATING:

/*7更新错误*/

console.log('updateCb更新错误');

break;

case jsb.EventAssetsManager.UPDATE_FINISHED:

/*8更新完成*/

self._finishCallback && self._finishCallback(true);

break;

case jsb.EventAssetsManager.UPDATE_FAILED:

/*9更新失败*/

self._failCount++;

if (self._failCount <= 3) {

self._am.downloadFailedAssets();

console.log(('updateCb更新失败' + this._failCount + ' 次'));

} else {

console.log(('updateCb失败次数过多'));

self._failCount = 0;

failed = true;

self._updating = false;

}

break;

case jsb.EventAssetsManager.ERROR_DECOMPRESS:

/*10解压失败*/

console.log('updateCb解压失败');

break;

}

if (failed) {

cc.eventManager.removeListener(self._updateListener);

self._updateListener = null;

self._updating = false;

self._finishCallback && self._finishCallback(false);

}

},

// type = 2

_checkCb: function(event) {

var failed = false;

let self = this;

switch (event.getEventCode()) {

case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:

/*0 本地没有配置文件*/

console.log('checkCb本地没有配置文件');

break;

case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:

/*1下载配置文件错误*/

console.log('checkCb下载配置文件错误');

failed = true;

break;

case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:

/*2 解析文件错误*/

console.log('checkCb解析文件错误');

failed = true;

break;

case jsb.EventAssetsManager.NEW_VERSION_FOUND:

/*3发现新的更新*/

self._getfiles(self._fileName, 1, self._downloadCallback, self._finishCallback);

break;

case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:

/*4 已经是最新的*/

console.log('checkCb已经是最新的');

self._finishCallback && self._finishCallback(true);

break;

case jsb.EventAssetsManager.UPDATE_PROGRESSION:

/*5 最新进展 */

break;

case jsb.EventAssetsManager.ASSET_UPDATED:

/*6需要更新*/

break;

case jsb.EventAssetsManager.ERROR_UPDATING:

/*7更新错误*/

console.log('checkCb更新错误');

failed = true;

break;

case jsb.EventAssetsManager.UPDATE_FINISHED:

/*8更新完成*/

console.log('checkCb更新完成');

break;

case jsb.EventAssetsManager.UPDATE_FAILED:

/*9更新失败*/

console.log('checkCb更新失败');

failed = true;

break;

case jsb.EventAssetsManager.ERROR_DECOMPRESS:

/*10解压失败*/

console.log('checkCb解压失败');

break;

}

this._updating = false;

if (failed) {

self._finishCallback && self._finishCallback(false);

}

},

// type = 3

_needUpdate: function(event) {

let self = this;

switch (event.getEventCode()) {

case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:

console.log('子游戏已经是最新的,不需要更新');

self._finishCallback && self._finishCallback(false);

break;

case jsb.EventAssetsManager.NEW_VERSION_FOUND:

console.log('子游戏需要更新');

self._finishCallback && self._finishCallback(true);

break;

// 检查是否更新出错

case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:

case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:

case jsb.EventAssetsManager.ERROR_UPDATING:

case jsb.EventAssetsManager.UPDATE_FAILED:

self._downloadCallback();

break;

}

},

/**

* 下载子游戏

* @param {string} name - 游戏名

* @param progress - 下载进度回调

* @param finish - 完成回调

* @note finish 返回true表示下载成功,false表示下载失败

*/

downloadSubgame: function(name, progress, finish) {

this._getfiles(name, 2, progress, finish);

},

/**

* 进入子游戏

* @param {string} name - 游戏名

*/

enterSubgame: function(name) {

if (!this._storagePath[name]) {

this.downloadSubgame(name);

return;

}

console.log("点击进入子游戏!");

setTimeout(() => {

console.log("200ms之后!");

if(jsb.fileUtils.isFileExist(this._storagePath[name] + '/src'))

{

console.log("subGame_src存在");

}

else

{

console.log("subGame_src不存在");

}

if(jsb.fileUtils.isFileExist(this._storagePath[name] + '/src/main.js'))

{

console.log("subGame_main.js存在");

}

else

{

console.log("subGame_main.js不存在");

}

window.require(this._storagePath[name] + '/src/main.js');

}, 200);

},

/**

* 判断子游戏是否已经下载

* @param {string} name - 游戏名

*/

isSubgameDownLoad: function (name) {

let file = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'ALLGame/' + name + '/project.manifest';

if (jsb.fileUtils.isFileExist(file)) {

console.log("子游戏已经下载!");

return true;

} else {

return false;

}

},

/**

* 判断子游戏是否需要更新

* @param {string} name - 游戏名

* @param isUpdateCallback - 是否需要更新回调

* @param failCallback - 错误回调

* @note isUpdateCallback 返回true表示需要更新,false表示不需要更新

*/

needUpdateSubgame: function (name, isUpdateCallback, failCallback) {

this._getfiles(name, 3, failCallback, isUpdateCallback);

},

};

module.exports = SubgameManager;

然后再添加个EnterSubGame.js文件,挂在场景节点上,添加按钮,按钮的回调为 ClickSubGameBtn,js文件内容如下

const SubgameManager = require('SubgameManager');

cc.Class({

extends: cc.Component,

properties: {

downloadLabel: {

default: null,

type: cc.Label

}

},

onLoad: function () {

const name = 'ddz';

//判断子游戏有没有下载

if (SubgameManager.isSubgameDownLoad(name)) {

//已下载,判断是否需要更新

SubgameManager.needUpdateSubgame(name, (success) => {

if (success) {

this.downloadLabel.string = "子游戏需要更新";

} else {

this.downloadLabel.string = "子游戏不需要更新";

}

}, () => {

console.log('出错了');

});

} else {

this.downloadLabel.string = "子游戏未下载";

}

},

ClickSubGameBtn: function()

{

//下载子游戏/更新子游戏

SubgameManager.downloadSubgame("ddz", (progress) => {

if (isNaN(progress)) {

progress = 0;

}

this.downloadLabel.string = "资源下载中 " + parseInt(progress * 100) + "%";

}, function(success) {

if (success) {

SubgameManager.enterSubgame('ddz');

} else {

console.log('下载失败');

}

});

},

});

然后创建一个子游戏的项目,添加version_generator.js,文件内容如下:

/**

* 此模块用于热更新工程清单文件的生成

*/

var fs = require('fs');

var path = require('path');

var crypto = require('crypto');

var manifest = {

//服务器上资源文件存放路径(src,res的路径)

packageUrl: 'http://192.168.1.15/hall/remote-assets/',

//服务器上project.manifest路径

remoteManifestUrl: 'http://192.168.1.15/hall/remote-assets/project.manifest',

//服务器上version.manifest路径

remoteVersionUrl: 'http://192.168.1.15/hall/remote-assets/version.manifest',

version: '1.0.4',

assets: {},

searchPaths: []

};

//生成的manifest文件存放目录

var dest = 'manifest/';

//项目构建后资源的目录

var src = 'build/jsb-link/';

/**

* node version_generator.js -v 1.0.0 -u http://your-server-address/tutorial-hot-update/remote-assets/ -s native/package/ -d assets/

*/

// Parse arguments

var i = 2;

while ( i < process.argv.length) {

var arg = process.argv[i];

switch (arg) {

case '--url' :

case '-u' :

var url = process.argv[i+1];

manifest.packageUrl = url;

manifest.remoteManifestUrl = url + 'project.manifest';

manifest.remoteVersionUrl = url + 'version.manifest';

i += 2;

break;

case '--version' :

case '-v' :

manifest.version = process.argv[i+1];

i += 2;

break;

case '--src' :

case '-s' :

src = process.argv[i+1];

i += 2;

break;

case '--dest' :

case '-d' :

dest = process.argv[i+1];

i += 2;

break;

default :

i++;

break;

}

}

function readDir (dir, obj) {

var stat = fs.statSync(dir);

if (!stat.isDirectory()) {

return;

}

var subpaths = fs.readdirSync(dir), subpath, size, md5, compressed, relative;

for (var i = 0; i < subpaths.length; ++i) {

if (subpaths[i][0] === '.') {

continue;

}

subpath = path.join(dir, subpaths[i]);

stat = fs.statSync(subpath);

if (stat.isDirectory()) {

readDir(subpath, obj);

}

else if (stat.isFile()) {

// Size in Bytes

size = stat['size'];

md5 = crypto.createHash('md5').update(fs.readFileSync(subpath, 'binary')).digest('hex');

compressed = path.extname(subpath).toLowerCase() === '.zip';

relative = path.relative(src, subpath);

relative = relative.replace(/\\/g, '/');

relative = encodeURI(relative);

obj[relative] = {

'size' : size,

'md5' : md5

};

if (compressed) {

obj[relative].compressed = true;

}

}

}

}

var mkdirSync = function (path) {

try {

fs.mkdirSync(path);

} catch(e) {

if ( e.code != 'EEXIST' ) throw e;

}

}

// Iterate res and src folder

readDir(path.join(src, 'src'), manifest.assets);

readDir(path.join(src, 'res'), manifest.assets);

var destManifest = path.join(dest, 'project.manifest');

var destVersion = path.join(dest, 'version.manifest');

mkdirSync(dest);

fs.writeFile(destManifest, JSON.stringify(manifest), (err) => {

if (err) throw err;

console.log('Manifest successfully generated');

});

delete manifest.assets;

delete manifest.searchPaths;

fs.writeFile(destVersion, JSON.stringify(manifest), (err) => {

if (err) throw err;

console.log('Version successfully generated');

});

添加子游戏的入口main.js,和返回大厅的入口dating.js,main.js内容如下,dating.js内容只需要稍稍进行修改就行:

(function () {

if (window.jsb) {

/// 1.初始化资源Lib路径Root.

var subgameSearchPath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/')+'ALLGame/ddz/';

// dating.js 改成 var subgameSearchPath = "assets"; 就可以了  ios的需要更改为:

// var subgameSearchPath = jsb.reflection.callStaticMethod("AppController", "getHallPath")+"/";

// 然后在AppController类下加入方法getHallPath:

// (NSString *)getHallPath
// {
//     return [[NSBundle mainBundle] bundlePath];
//  }

/// 2.subgame资源未映射,则初始化资源映射表,否则略过映射.  我这里没有添加 会造成内存泄漏 你们要加一下哦

//if(!cc.HallAndSubGameGlobal.subgameGlobal){

//cc.HallAndSubGameGlobal.subgameGlobal = {};

var subGameGlobal = {};

/// 加载settings.js

require(subgameSearchPath + 'src/settings.js');

var settings = window._CCSettings;

window._CCSettings = undefined;

if ( !settings.debug ) {

var uuids = settings.uuids;

var rawAssets = settings.rawAssets;

var assetTypes = settings.assetTypes;

var realRawAssets = settings.rawAssets = {};

for (var mount in rawAssets) {

var entries = rawAssets[mount];

var realEntries = realRawAssets[mount] = {};

for (var id in entries) {

var entry = entries[id];

var type = entry[1];

// retrieve minified raw asset

if (typeof type === 'number') {

entry[1] = assetTypes[type];

}

// retrieve uuid

realEntries[uuids[id] || id] = entry;

}

}

var scenes = settings.scenes;

for (var i = 0; i < scenes.length; ++i) {

var scene = scenes[i];

if (typeof scene.uuid === 'number') {

scene.uuid = uuids[scene.uuid];

}

}

var packedAssets = settings.packedAssets;

for (var packId in packedAssets) {

var packedIds = packedAssets[packId];

for (var j = 0; j < packedIds.length; ++j) {

if (typeof packedIds[j] === 'number') {

packedIds[j] = uuids[packedIds[j]];

}

}

}

}

/// 加载project.js

var projectDir = 'src/project.js';

if ( settings.debug ) {

projectDir = 'src/project.dev.js';

}

window.require(subgameSearchPath + projectDir);

/// 如果当前搜索路径没有subgame,则添加进去搜索路径。

var currentSearchPaths = jsb.fileUtils.getSearchPaths();

if(currentSearchPaths && currentSearchPaths.indexOf(subgameSearchPath) === -1){

jsb.fileUtils.addSearchPath(subgameSearchPath, true);

console.log('subgame main.js 之前未添加,添加下subgameSearchPath' + currentSearchPaths);

}

cc.AssetLibrary.init({

libraryPath: 'res/import',

rawAssetsBase: 'res/raw-',

rawAssets: settings.rawAssets,

packedAssets: settings.packedAssets,

md5AssetsMap: settings.md5AssetsMap

});

/* cc.HallAndSubGameGlobal. */subGameGlobal.launchScene = settings.launchScene;

/// 将subgame的场景添加到cc.game中,使得cc.director.loadScene可以从cc.game._sceneInfos查找到相关场景

for(var i = 0; i < settings.scenes.length; ++i){

cc.game._sceneInfos.push(settings.scenes[i]);

}

}

console.log("加载场景!");

/// 3.加载初始场景

var launchScene = /* cc.HallAndSubGameGlobal. */subGameGlobal.launchScene;

cc.director.loadScene(launchScene, null, function () {

console.log('subgame main.js 成功加载初始场景' + launchScene);

}

);

// }

})();

在子游戏中创建个按钮,按钮的回调函数为:

//因为我只弄了个ddz的,所以这边是ddz

window.require(jsb.fileUtils.getWritablePath() + "ALLGame/ddz/src/dating.js");

//这里需要注意下,子游戏的 脚本加密密钥 要跟 大厅的 脚本加密密钥 是一致的才可以

然后构建子游戏的项目,构建完成之后,把 自己创建的 main.js 和 dating.js 放进资源的 src 文件夹下,再去运行生成manifest的脚本,一定要先放文件再生成,然后把文件放到服务器上,使用大厅的项目达成apk包就可以测试了。

如果自己在本地测试的话,可以安装下 http-server 或者 tomcat 来使用局域网进行下载资源。

demo下载地址:https://github.com/chen6636865/UpdateTest

cocos creator 大厅 ➕ 子游戏(子游戏作为单独的项目更新)相关推荐

  1. cocos creator 大厅+子游戏模式探讨(creator版本1.8.2)

    之前一直从事android开发,接触cocos creator不久.近期公司安排我研究大厅子游戏模式的热更新,前后花了近一周时间,在论坛上查资料,请教大神,期间得到了一些帮助,在此很感谢cocos中文 ...

  2. cocos creator大厅、子游戏实现方案

    参考cocos论坛:http://forum.cocos.com/t/1-5-2-demo/48200 demo: https://github.com/zhangjiangyi/HallAndChi ...

  3. cocos creator学习个人踩坑(3)--关于项目调试在一些安卓机上FPS低

    一些cocos creator遇到的小问题 问题 在做点消游戏项目的时候,在一些旧的安卓机上测试时消除特效显示会有明显的卡顿,火箭消除会有残留,FPS下降明显 原因 通过真机调试,发现日志输出会明显导 ...

  4. Cocos Creator 解决热更新资源md5比较引发卡顿问题

    大家在使用Cococ Creator提供的热更新 assetsManagers ,做md5校验的时候,一定会遇到卡顿的问题. 备注:文末有完整实现源码 原因是 Cococ Creator 官方提供的热 ...

  5. Cocos Creator 2.3.3 更新说明,效率即是一切!

    效率即是一切,Cocos Creator 2.3.3 正式版来啦!本次更新带来了更多新的特性,优化了性能以及提升了稳定性,希望能为广大开发者们保驾护航.建议所有开发者升级哦! 以下是 Cocos Cr ...

  6. Cocos 篇:基于 Cocos Creator v1.9,开始 Hello World 。。。

    前言 身体好,才是真的好~ 从此之后,要会生活,努力活出自己想要的样子~!!! Enmmm,LZ 也是小白一枚,初入贵行,还望手下留情~ 本篇主要作用,或者说定位在于和 LZ 一样得小白,希望多多交流 ...

  7. cocos creator require报错Error: Cannot find module ‘./xx‘

    出现此错误,一般的情况包括: 1.文件引用路径不正确,也是报错的字面意思,找不到文件,所以报错.这个很容易修复. 2.项目文件夹与cocos creator的CocosDashboard.exe放在同 ...

  8. cocos creator 单机小驴快跑

    cocos creator 单机小驴快跑可以自行搭建项目. 演示地址:https://www.bilibili.com/video/av51569369/ 联系方式:QQ 1019429950

  9. Cocos Creator 2.1.3 正式发布

    自 Cocos Creator 2.1.0 发布以来,经过半年时间更新迭代,版本现已趋于稳定,目前 2.1 的新增用户已经占据主流.因此我们计划减少 2.0 版本的后续维护力度,将分散的精力集中投入到 ...

最新文章

  1. linux虚拟网络设备-- TUN/TAP MACVLAN MACVTAP(八)
  2. 上周热点回顾(12.8-12.14)
  3. mongodb同时更新一条记录_MongoDB 存储和优化系列一
  4. python调用stanfordNLP的NER接口
  5. asp.net core集成CAP(分布式事务总线)
  6. 1095 解码PAT准考证 (25 分)
  7. sdutacm 1566 幸运数(bfs)
  8. Windows 10下使用Xshell5连接虚拟机的ubuntu18系统
  9. 【NLP】用腻了 CRF,试试 LAN 吧?
  10. matlab cos sinx,matlab求y=sinxcos(2x)及其包络线急!!!
  11. 这些实用的WhatsApp工具,赶快用起来
  12. 计算机视觉的终极目标
  13. 《新零售:低价高效的数据赋能之路》读后感
  14. 论文复现—1—A Simple yet Effective Relation Information Guided Approach for Few-Shot Relation Extraction
  15. matlab中类的用法
  16. Linux 中的 nl 命令详解及C/C++代码实现(文件行数)
  17. Linux 系统 pptpd+radius+mysql 安装攻略
  18. 贝叶斯聂曼准则matlab程序,模式识别试题及总结
  19. i.MX RT开发笔记-03 | i.MX RT1062地址空间映射及启动方式
  20. 大三小生浅谈如何学C

热门文章

  1. 架构师喜欢用的架构图工具
  2. Django如何设置首页(默认输入域名或者ip即可跳转到指定页面)
  3. 行业幻化对我们家的影响
  4. 用产品经理的思维分析子弹短信
  5. iOS Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)崩溃错误
  6. [经济杂谈]如果你读懂了 股市就是取款机(要保存的) 管理帖子
  7. 印尼新加密税法正式实施 监管力度升级 全球加密呈现新态势
  8. sqlyog最简单的修改密码方法。
  9. “大闸蟹” 英语怎么说?
  10. 软件测试保姆级攻略(第一期 软件的结构组成和网络基础)