Quick-Cocos2d-x的热更新机制实现(终极版2)

Quick-Cocos2d-x的热更新机制实现(终极版2),第1张

概述模块支持: 1.游戏热更新。 2.framework的更新。 3.自身更新。 4.平台初始化模块嵌入(现在的游戏除了app store上 不需要集成第三方SDK,其他的基本上都需要集成各种平台SDK, 所以就加上了这个功能)。 5.更新进度显示。 6.纯lua实现。 模块流程如下: 第一步修改AppDelegate.cpp 逻辑 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1

模块支持:

1.游戏热更新。

2.framework的更新。

3.自身更新。

4.平台初始化模块嵌入(现在的游戏除了app store上 不需要集成第三方SDK,其他的基本上都需要集成各种平台SDK,所以就加上了这个功能)。

5.更新进度显示。

6.纯lua实现。


模块流程如下:

第一步修改AppDelegate.cpp 逻辑

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 #include"AppPlatform.h" bool AppDelegate::applicationDIDFinishLaunching() { //initializedirector CCDirector*pDirector=CCDirector::sharedDirector(); pDirector->setopenGLVIEw(CCEGLVIEw::sharedOpenGLVIEw()); pDirector->setProjection(kCCDirectorProjection2D); //setFPS.thedefaultvalueis1.0/60ifyoudon'tcallthis pDirector->setAnimationInterval(1.0/60); initResourcePath(); //registerluaengine ccluaEngine*pEngine=ccluaEngine::defaultEngine(); ccScriptEngineManager::sharedManager()->setScriptEngine(pEngine); ccluaStack*pStack=pEngine->getLuaStack(); #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS||CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID) stringpath=CCfileUtils::sharedfileUtils()->fullPathForfilename( "scripts/main.lua" ); #else stringpath=CCfileUtils::sharedfileUtils()->fullPathForfilename(m_projectConfig.getScriptfileRealPath().c_str()); #endif size_t pos; while ((pos=path.find_first_of( "\" ))!=std::string::npos) { path.replace(pos,1, "/" ); } size_t p=path.find_last_of( "/\" ); if (p!=path.npos) { const stringdir=path.substr(0,p); pStack->addSearchPath(dir.c_str()); p=dir.find_last_of( "/\" ); if (p!=dir.npos) { pStack->addSearchPath(dir.substr(0,p).c_str()); } } stringenv= "__LUA_STARTUP_file__=\"" ; env.append(path); env.append( "\"" ); pEngine->executeString(env.c_str()); cclOG( "------------------------------------------------" ); cclOG( "LOADLUAfile:%s" ,path.c_str()); cclOG( "------------------------------------------------" ); pEngine->executeScriptfile(path.c_str()); return true ; } voID AppDelegate::initResourcePath() { CCfileUtils*sharedfileUtils=CCfileUtils::sharedfileUtils(); //设置SearchPaths #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS||CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID) std::vector<std::string>oldSearchPaths=sharedfileUtils->getSearchPaths(); std::vector<std::string>tempPaths(oldSearchPaths); std::vector<std::string>searchPaths; searchPaths.push_back(sharedfileUtils->getWritablePath()+ "upd/" ); #if(CC_TARGET_PLATFORM==CC_PLATFORM_IOS) searchPaths.push_back( "res/" ); #else std::stringstrBasePath=getAppBaseResourcePath(); searchPaths.push_back(strBasePath); searchPaths.push_back(strBasePath+ "res/" ); #endif for ( int i=0;i<tempPaths.size();++i){ searchPaths.push_back(tempPaths); } sharedfileUtils->setSearchPaths(searchPaths); #else sharedfileUtils->addSearchPath( "res/" ); #endif }

说明:

1:删除加载framework_@[email protected] 函数调用(启动更新模块时不需要)

2:添加的初始化游戏资源路径方法(为什么要写在这里 大多数情况下资源搜索路径应该是固定的),

有人会问如果资源搜索路径有改变怎么办? 如果有修改,只需要把上述逻辑在脚本里面实现即可。

3:对androID特定做了一个BasePath,这个路径是用于设置基础资源搜索的(可以是"assert/"、“/data/data/com.xxoo.xxoo/files/”、"/mnt/sdcard/xxoo/")便于初始资源读取位置。


1 2 3 4 5 6 7 8 9 10 11 12 //AppPlatform.h #ifndef__xxoo__AppPlatform__ #define__xxoo__AppPlatform__ #include<string> extern "C" { std::stringgetAppBaseResourcePath(); } #endif/*defined(__xxoo__AppPlatform__)*/
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 //AppPlatform.cpp #include"AppPlatform.h" #include"cocos2d.h" #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID) #include"jni/JniHelper.h" #include<jni.h> #defineGAME_CLASS_name"com/xxoo/xxoo/luajavabrIDge/LuajavabrIDge" #endif using namespace cocos2d; extern "C" { std::stringgetAppBaseResourcePath() { #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID) JniMethodInfot; std::stringstrAppBaseResourcePath; if (JniHelper::getStaticmethodInfo(t,GAME_CLASS_name, "getAppBaseResourcePath" , "()Ljava/lang/String;" )){ JstringbaseResourcePathJstr=(Jstring)t.env->CallStaticObjectMethod(t.classID,t.methodID); strAppBaseResourcePath=JniHelper::Jstring2string(baseResourcePathJstr); t.env->DeleteLocalRef(t.classID); t.env->DeleteLocalRef(baseResourcePathJstr); } return strAppBaseResourcePath; #else return "" ; #endif } }


说明:平台调用方法


前期准备工作做完 下一步看main.lua实现

1 2 3 4 5 6 7 8 9 10 function__G__TRACKBACK__(errorMessage) print( "----------------------------------------" ) print( "LUAERROR:" ..tostring(errorMessage).. "\n" ) print(deBUG.traceback( "" ,2)) print( "----------------------------------------" ) end ccluaLoadChunksFromZIP( "lib/launcher.zip" ) package.loaded[ "launcher.launcher" ]=nil require( "launcher.launcher" )


launcher 模块 有3个文件: launcher.lua,init.lua,config.lua


文件说明:config.lua 延用quick里面的属性设置

init.lua 为了使当前模块不引用framework中的方法,把launcher需要的方法都封装到init(借鉴framework)

launcher.lua 实现初始化平台SDK,更新资源,自更新,更新界面逻辑。


点击这里下载launcher.zip


初始化第三方SDK成功后,先去下载launcher模块;接着,下载下来的launcher模块和本地的launcher模块做内容md5比较。 如果二者md5值不同就保存新的launcher到upd/lib/目录下,再次加载main.lua;如果二者md5值相同则开始判断是否有新资源更新逻辑。


资源更新逻辑

fList 样板先贴上来

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 localfList={ appVersion=1, version= "1.0.1" , dirPaths={ {name= "common" }, {name= "common/test" }, {name= "lib" }, {name= "sound" }, }, fileInfoList={ {name= "lib/framework_@[email protected]" ,code= "b126279331bd68cc3c5c63e6fe0f2156" ,size=101677}, }, } return fList

说明:

1. appVersion:控制app打包的版本是否删除旧资源 (更新整包后upd/目录旧资源需要删除)

2. version:资源文件跟新版本(控制资源是否更新)

3. dirPaths: 当前资源目录下所有子目录(便于创建依次创建文件夹)

4. fileInfoList :资源文件信息;相对路径、文件内容的md5值、文件size


更新资源逻辑:通过服务器上下载下来的fList文件内容和本地的fList文件内容比较差异话。


另我是使用脚本生成fList 这个工具是从网上找的,做了一些修改下面贴上关键代码。

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 localcurrentFolder= "/Users/xxx/documents/quick-cocos2d-x/projects/xxoo/res" localfunctionhex(s) s=string.gsub(s, "(.)" ,function(x) return string.format( "X" ,string.byte(x))end) return s end localfunctionreadfile(path) localfile=io.open(path, "rb" ) if filethen localcontent=file:read( "*all" ) io.close(file) return content end return nil end require "lfs" localfunctionfindindir(path,wefind,dir_table,r_table,intofolder) for fileinlfs.dir(path) do if file~= "." andfile~= ".." andfile~= ".DS_Store" andfile~= "fList" andfile~= "launcher.zip" then localf=path.. "/" ..file localattr=lfs.attributes(f) assert (type(attr)== "table" ) if attr.mode== "directory" andintofolderthen table.insert(dir_table,f) findindir(f,intofolder) else table.insert(r_table,{name=f,size=attr.size}) end end end end MakefileList={} functionMakefileList:run(path) localdir_table={} localinput_table={} findindir(currentFolder, "." ,input_table, true ) localpthlen=string.len(currentFolder)+2 localbuf= "localfList={\n" buf=buf.. "\tappVersion=1,\n" buf=buf.. "\tversion=\"1.0.2\",\n" buf=buf.. "\tdirPaths={\n" for i,vinipairs(dir_table) do --print(i,v) localfn=string.sub(v,pthlen) buf=buf.. "\t\t{name=\"" ..fn.. "\"},\n" end buf=buf.. "\t},\n" buf=buf.. "\tfileInfoList={\n" for i,vinipairs(input_table) do --print(i,v) localfn=string.sub(v.name,pthlen) buf=buf.. "\t\t{name=\"" ..fn.. "\",code=\"" localdata=readfile(v.name) localms=crypto.md5(hex(dataor "" ))or "" buf=buf..ms.. "\",size=" ..v.size.. "},\n" end buf=buf.. "\t},\n" buf=buf.. "}\n\n" buf=buf.. "returnfList" io.writefile(currentFolder.. "/fList" ,buf) end return MakefileList

此代码依赖Quick ,使用player 跑一下 上面code就可以生成相关fList文件了。


希望大家在使用中有更好的方案是可以我相关的建议,大家一起学习。


本文已经在论坛中发帖讨论,欢迎大家加入论坛,与开发者们一起研讨学习。


推荐阅读:

Quick-Cocos2d-x的热更新机制实现(终极版)


来源网址:http://www.cocoachina.com/bbs/read.php?tid=213257

总结

以上是内存溢出为你收集整理的Quick-Cocos2d-x的热更新机制实现(终极版2)全部内容,希望文章能够帮你解决Quick-Cocos2d-x的热更新机制实现(终极版2)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1033604.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存