quick 3.3 "异步"加载Spine方案.md
背景项目中, 使用了quick 3.3, 由于Spine各个功能相当强大, 所以使用了Spine作为骨骼动画, 但是Spine并非cocos官方支持,因此在一些问题上支持性不是那么好,其中如何异步加载Spine就是一个问题。 比如游戏中经常遇到这么一个问题:在主战斗场景中, 需要加载大量的图片、声音、Spine动画等, 如果我们等用到的时候再去加载,由于文件I/O是比较耗时的, 有可能就会在游戏过程中造成卡顿的现象,在低端配置手机中体现尤为明显,这或大或小造成游戏体验不佳。 对于这个问题呢, 一种比较常用的解决方案:在进入主战斗之前, 先预加载战斗中大量耗时的资源(并不一定要是所有资源),并且缓存起来,等到真到需要用到的时候,直接去读取缓存中的数据。 比如很多游戏看到的Loading条, 就是用的这种方案。 难点1、异步加载 自己实现我知道有两种方法。 我自己使用的是使用的update这种方法。 function LoadingLayer:update(ts) - --- 每帧加载一次资源 local pngNum = table.nums(ResMng._pngList) local plistNum = table.nums(ResMng._plistList) local soundNum = table.nums(ResMng._soundList) local spineNum = table.nums(ResMng._spineList) local curLoadNum = ResMng._curLoadNum -- 加载资源顺序 -- 1、加载PNG if 0 <= curLoadNum and curLoadNum < pngNum then ResMng.loadPng() -- 2、加载PLIST elseif pngNum <= curLoadNum and curLoadNum < pngNum + plistNum then ResMng.loadPlist() -- 3、加载SOUND elseif pngNum + plistNum <= curLoadNum and curLoadNum < pngNum + plistNum + soundNum then ResMng.loadSound() -- 4、加载Spine elseif pngNum + plistNum + soundNum <= curLoadNum and curLoadNum < pngNum + plistNum + soundNum + spineNum then ResMng.loadSpine() else print("所有资源预加载完成") ResMng.resortSpine() self:replaceScene() end end 2、Spine缓存 -- 加载一次Spine图 function ResMng.loadSpine() local spineInfo = self._spineList[self._curLoadIndex] assert(spineInfo,"加载Spine索引出错" .. self._curLoadIndex) local spineAnimation = require("app.common.factory.sp_animation").new() spineInfo.animation = spineAnimation:createWithID(spineInfo.id) spineInfo.animation:getNode():retain() self._curLoadNum = self._curLoadNum + 1 if self._curLoadIndex == #self._spineList then self._curLoadIndex = 1 else self._curLoadIndex = self._curLoadIndex + 1 end end -- 从缓存中获取Spine function ResMng.getSpineByID(spineID) -- 如果不存在此资源,先加载到缓存 if not self._spineList[spineID] then print("缓存文件:",spineID) local spineAnimation = require("app.common.factory.sp_animation"):new() self._spineList[spineID] = spineAnimation:createWithID(spineID) self._spineList[spineID]:getNode():retain() end local newSpine = require("app.common.factory.sp_animation"):new() return newSpine:createWithData(self._spineList[spineID]) end 3、导出createWithData到Lua层调用 class LuaSkeletonAnimation: public spine::SkeletonAnimation { public: static LuaSkeletonAnimation* createWithFile (const char* skeletonDataFile,const char* atlasFile,float scale = 1); static LuaSkeletonAnimation* createWithData(SkeletonAnimation* spineData); LuaSkeletonAnimation (const char* skeletonDataFile,float scale = 1); LuaSkeletonAnimation(SkeletonAnimation* spineData); virtual ~LuaSkeletonAnimation(); }; LuaSkeletonAnimation.cpp LuaSkeletonAnimation::LuaSkeletonAnimation (const char* skeletonDataFile,float scale) : spine::SkeletonAnimation(skeletonDataFile,atlasFile,scale) { } LuaSkeletonAnimation::LuaSkeletonAnimation(SkeletonAnimation* spineData) : spine::SkeletonAnimation(spineData) { } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithFile (const char* skeletonDataFile,float scale) { LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(skeletonDataFile,scale); node->autorelease(); return node; } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithData(SkeletonAnimation* spineData) { LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(spineData); node->autorelease(); return node; } lua_cocos2dx_spine_manual.cpp //add by chenhao on 2015/03/24 //手动添加Spine tolua代码,解决Spine缓存问题 static int lua_cocos2dx_CCSkeletonAnimation_createWithData(lua_State* L) { if (nullptr == L) return 0; int argc = 0; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertable(L,1,"sp.SkeletonAnimation",&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(L) - 1; if (1 == argc) { #if COCOS2D_DEBUG >= 1 if (!tolua_isusertable(L,&tolua_err)) { goto tolua_lerror; } #endif SkeletonAnimation* spineData = (SkeletonAnimation*)tolua_tousertype(L,2,0); auto tolua_ret = LuaSkeletonAnimation::createWithData(spineData); int nID = (tolua_ret) ? (int)tolua_ret->_ID : -1; int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL; toluafix_pushusertype_ccobject(L,nID,pLuaID,(void*)tolua_ret,"sp.SkeletonAnimation"); return 1; } luaL_error(L,"'createWithFile' function of SkeletonAnimation has wrong number of arguments: %d,was expecting %dn",argc,2); #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(L,"#ferror in function 'createWithData'.",&tolua_err); #endif return 0; } 并且在extendCCSkeletonAnimation()中,添加下面这行代码。 tolua_function(L,"createWithData",lua_cocos2dx_CCSkeletonAnimation_createWithData); 为了减少导出自定义类, 我对C++层createWithData的参数类型作了一些修改,但是不影响。改为了: static SkeletonAnimation* createWithData(SkeletonAnimation* spineData); 以上都是本人自己实现摸索过程中, 探索出来的一些方法,有什么问题大家可以提出来,我好修改。 http://www.52php.cn/article/p-nawkknxq-bhs.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |