1. 热更新基本思路
得到CocoaChina论坛上fysp和akira_cn的帮助,理清了游戏热更新的思路:
* 执行AssetsManager后,搜索路径增加了Jsb.fileUtils.getWritablePath()目录,并且是优先搜索;
* 需要热更新Js不放在project.Json中定义,等AssetsManager更新完了,用cc.loader.load动态加载;
* 所以在Jsb.fileUtils.getWritablePath()目录下载的资源和Js文件,与项目目录保持一致,那么优先加载新下载的资源和Js文件,再进入游戏,从而实现热更新。
2. AssetsManager
Cocos2d-Js 3.0 rc0对AssetsManager功能进行了完善增强,支持多线程下载、断点续传、文件压缩、更好的进度信息以及错误重试机制,实现游戏资源文件和脚本文件的热更新变的更加方便。
用cocos new MyGame -l Js -d /directory/to/project方式新建一个测试项目,参考sample写的src/AssetsManager.Js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | var__failCount=0;varassetsManagerLoaderScene=cc.Scene.extend({ _am:null, _progress:null, _percent:0, _percentByfile:0, run:function(){ if (!cc.sys.isNative){ this .loadGame(); return ; } varlayer= new cc.Layer(); .addChild(layer); ._progress= cc.LabelTTF.create( "0%" , "Arial" ._progress.x=cc.winSize.wIDth/2; ._progress.y=cc.winSize.height/2+50; layer.addChild( ._progress); //androID:/data/data/com.huanle.magic/files/ varstoragePath=(Jsb.fileUtils?Jsb.fileUtils.getWritablePath(): "./" ); ._am= Jsb.AssetsManager( "res/project.manifest" ._am.retain(); (! ._am.getLocalManifest().isLoaded()) { cc. log ( "Failtoupdateassets,stepskipped." ); .loadGame(); @H_326_404@ } else { varthat= ; varListener= cc.EventListenerAssetsManager( ._am,function(event){ switch (event.getEventCode()){ case cc.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST: "Nolocalmanifestfilefound,skipassetsupdate." ); that.loadGame(); break ; cc.EventAssetsManager.UPDATE_PROGRESSION: that._percent=event.getPercent(); that._percentByfile=event.getPercentByfile(); (that._percent+ "%" ); varmsg=event.getMessage(); (msg){ (msg); } ; cc.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: cc.EventAssetsManager.ERROR_PARSE_MANIFEST: "Failtodownloadmanifestfile,updateskipped." ); that.loadGame(); ; cc.EventAssetsManager.ALREADY_UP_TO_DATE: cc.EventAssetsManager.UPDATE_FINISHED: "Updatefinished." ); that.loadGame(); ; cc.EventAssetsManager.UPDATE_Failed: "UpdateFailed." +event.getMessage()); __failCount++; (__failCount<5) { that._am.downloadFailedAssets(); } else { "Reachmaximumfailcount,exitupdateprocess" ); __failCount=0; that.loadGame(); } ; cc.EventAssetsManager.ERROR_UPDATING: "Assetupdateerror:" +event.getAssetID()+ "," +event.getMessage()); that.loadGame(); ; cc.EventAssetsManager.ERROR_DECOMPRESS: (event.getMessage()); that.loadGame(); ; default : ; } }); cc.eventManager.addListener(Listener,1); ._am.update(); cc.director.runScene( ); } .schedule( .updateProgress,0.5); }, loadGame:function(){ cc.loader.loadJs([ "src/files.Js" ],function(err){ cc.loader.loadJs(Jsfiles,function(err){ HelloWorldScene()); }); }); updateProgress:function(dt){ ._progress.string= "" + ._percent; onExit:function(){ "AssetsManager::onExit" ); ._am.release(); ._super(); }}); |
修改项目目录下的main.Js:
cc.game.onStart=function(){ cc.vIEw.setDesignResolutionSize(800,450,cc.ResolutionPolicy.SHOW_ALL); cc.vIEw.resizeWithbrowserSize( true ); varscene= AssetsManagerLoaderScene(); scene.run();};cc.game.run(); |
修改项目目录下的project.Json:
{ "project_type" : "JavaScript" "deBUGMode" :1,monospace!important; Font-size:1em!important; min-height:inherit!important; color:blue!important; background:none!important">"showFPS" : "frameRate" :60, "ID" "gameCanvas" "renderMode" :0, "engineDir" "frameworks/cocos2d-HTML5" "modules" :[ "cocos2d" "extensions" "JsList" :[ "src/AssetsManager.Js" ]} |
就留一个AssetsManager.Js,其他的Js都通过它来加载。
增加一个src/files.Js,需要动态加载的Js文件都写在Jsfiles这个数组里,这样Js文件有增加变化,这个files.Js一并更新,方便动态加载:
varJsfiles=[ "src/app.Js" "src/resource.Js" ]; |
项目res目录增加一个project.manifest文件,AssetsManager.Js里会用到:
"packageUrl" "http://10.0.128.219/res" "remoteManifestUrl" "http://10.0.128.219/res/project.manifest" "remoteVersionUrl" "http://10.0.128.219/res/version.manifest" "version" "1.0.0" "groupVersions" :{ "1" "1.0.0" "engineVersion" "3.0rc0" "searchPaths" :[ ]} |
这里主要配置服务端资源下载地址,具体字段说明,在下面服务端配置里说明。然后用cocos compile -p androID编译打包成一个apk安装包,等配置好服务端更新资源安装测试。
3. 服务端配置
需要建一个WEB服务器做下载用,在其WEB目录http://10.0.128.219/res(我的测试机),增加version.manifest文件:
"1.0.1" "3.0rc0" } |
测试发现,AssetsManager首先会下载version.manifest文件,如果有更新的版本,那么才会去下载project.manifest,然后下载其中描述的资源文件。
project.manifest如下:
"assets" :{ "update1" :{ "path" "src/app.zip" "md5" "f6bf54e5a0d42c963cc5ae81bf9dc6c6" "compressed" "group" "1" } :[ ] } |
写法和官方文档里不太一样,特别是有个groupVersions字段,这个字段来自fysp在cocoachina论坛回答其他网友问题写的示例,测试发现用来做增量更新很方便,后面再说明。其他字段的说明官方文档已经很详细了。
由于客户端本地project.manifest里groupVersions的版本信息比服务器端的低,所以AssetsManager会下载http://10.0.128.219/res/src/app.zip到手机的/data/data/org.cocos2dx.helloJavaScript/files/src/app.zip,并且会自动解压,但不会删除压缩包本身。
建议用root过的androID手机测试,否则/data/data是没有权限查看。运行客户端测试程序后用adb连接查看:
e:\>adbshell shell@androID:/$su su shell@androID:/#ls-l/data/data/org.cocos2dx.helloJavaScript/files/src/ls-l/data/data/org.cocos2dx.helloJavaScript/files/src/ -rw-rw-rw-app_65app_6522282014-07-0814:23app.Js -rw-rw-rw-app_65app_6515522014-07-0814:23app.zip shell@androID:/#ls-l/data/data/org.cocos2dx.helloJavaScript/files/ls-l/data/data/org.cocos2dx.helloJavaScript/files/ -rw-rw-rw-app_65app_655532014-07-0814:23project.manifest drwxrwxrwxapp_65app_652014-07-0814:23src -rw-rw-rw-app_65app_653072014-07-0814:23version.manifest |
用firefox调试连上手机,发现app.Js资源地址是/data/data/org.cocos2dx.helloJavaScript/files/src/app.Js,而不是assets/src/app.Js,实现了热更新:
4. 增量更新
修改服务端version.manifest:
修改服务端project.manifest:
:{ "1" "update2" :{ "src/config.zip" "5d59789090e4143166430b2cf7b313ff" "2" } :[ ] } |
这时在androID客户端测试,已经更新到update1的,只会下载update2的更新,而没有更新过的,会把update1和update2都下载下来。
来源网址:https://github.com/faint2death/cocos2d-js/blob/master/assetsmanager.md
分享到: 总结以上是内存溢出为你收集整理的cocos2d-js热更新全部内容,希望文章能够帮你解决cocos2d-js热更新所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)