前言
本文實現了spine動畫的預加載,解決在戰斗等大量加載spine動畫的時候出現卡頓現象。
這里使用和修改三個類,直接修改的源碼,當然你也可以繼承LuaSkeletonAnimation,自己封裝一個類。這里做個例子,
不自己寫類,直接改源碼。如果想自己寫,綁定到lua,看我別的帖子。廢話不多說,入主題。
在之前對圖片 應該對圖片進行異步加載,詳細以后再說。
版本:quicklua 3.3 win vs2012
原理
先分析下,LuaSkeletonAnimation類
class LuaSkeletonAnimation: public spine::SkeletonAnimation { public: static LuaSkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1); LuaSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 1); virtual ~LuaSkeletonAnimation(); };
LuaSkeletonAnimation 繼承自 SkeletonAnimation類。
在lua_cocos2dx_spine_manual.cpp中可以看到,在lua層調用 create 方法實際是 調用的LuaSkeletonAnimation的 createWithFile 方法
所以我們把新的方法也放到這里,當然你也可以直接放到SkeletonAnimation類中。建議在此處。
再看下SkeletonAnimation類:
static SkeletonAnimation* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false); static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1); static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
創建spine動畫有兩種方法,分別是createwithfile和createwithdata。
createWithFile是通過加載動作數據馬上進行創建,如果spine動畫中的json文件大小超過100k時,會出現卡頓現象,如果動畫文件偏小,可以使用這個方法來創建動畫。createWithData是通過預加載,保存動畫數據在spSkeletonData中,然后通過實現創建動畫。
上面這些我相信你們一看就懂吧。 總體來講:
lua 層使用,createwithfile 方法創建,然后保存在table 中,實現預加載 。在使用的時候使用createWithData,創建動畫。
createWithData方法需要的參數是spSkeletonData,我們需要封裝一個獲取spSkeletonData的方法,具體看LuaSkeletonAnimation的爺爺類。
c++代碼的修改
(1)SkeletonAnimation.h:
spSkeletonData* getSkeletonData();
SkeletonAnimation.cpp 實現
spSkeletonData* SkeletonAnimation::getSkeletonData(){ spSkeletonData*skData =SkeletonRenderer::getSkeleton()->data; return skData; }
(2)LuaSkeletonAnimation.h
class LuaSkeletonAnimation: public spine::SkeletonAnimation { public: static LuaSkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1); // preload spine 添加下面兩個方法 static LuaSkeletonAnimation* createWithSkeletonAnimation(SkeletonAnimation* skeletonAnimation); LuaSkeletonAnimation(SkeletonAnimation* spineData); LuaSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 1); virtual ~LuaSkeletonAnimation(); };
說明:
createWithSkeletonAnimation方法,為了減少導出自定義類,所以參數是 SkeletonAnimation。
LuaSkeletonAnimation::LuaSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale) : spine::SkeletonAnimation(skeletonDataFile, atlasFile, scale) { } LuaSkeletonAnimation::LuaSkeletonAnimation(SkeletonAnimation* spineData) : spine::SkeletonAnimation(spineData->getSkeletonData()) { } LuaSkeletonAnimation::~LuaSkeletonAnimation() { ScriptHandlerMgr::getInstance()->removeObjectAllHandlers((void*)this); } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) { LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(skeletonDataFile, atlasFile, scale); node->autorelease(); return node; } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithSkeletonAnimation(SkeletonAnimation* skeletonAnimation) { LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(skeletonAnimation); node->autorelease(); return node; }
改好上面兩個類。可以使用cocos2dx自帶的腳本重新tolua一下。這里 直接改代碼吧,省時有效。。。嘎嘎、、
lua_cocos2dx_spine_manual.cpp
1.
static int lua_cocos2dx_CCSkeletonAnimation_createWithSkeletonAnimation(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",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(L) - 1; if (1 == argc) { //TODO SkeletonAnimation* skeletonAnimation = (SkeletonAnimation*)tolua_tousertype(L, 2, 0); auto tolua_ret = LuaSkeletonAnimation::createWithSkeletonAnimation(skeletonAnimation); 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; } #if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(L,"#ferror in function 'createWithSkeletonAnimation'.",&tolua_err); #endif return 0; }
2.static void extendCCSkeletonAnimation(lua_State* L)方法中添加一行:
tolua_function(L, "createWithSkeletonAnimation", lua_cocos2dx_CCSkeletonAnimation_createWithSkeletonAnimation);
lua使用及預加載
上面代碼改好之后,編譯一下,跑起來程序,在lua測試一下,能不能正常調用函數。OK的話,就可以寫代碼 預加載了。
在項目中我們一般要有個loadlayer 吧需要的音樂 圖片 spine等預加載進去。這里測試一下就不寫了、
首先我們要封裝一下 sp.SkeletonAnimation
local SpineNode = class("SpineNode", function(spineName) spineName = "ceshi" --預加載列表有,就直接使用 if LoadingManager:isSpineLoad(spineName) then dump("****************preload:"..spineName) do return sp.SkeletonAnimation:createWithSkeletonAnimation(LoadingManager.preloadSpines[spineName]) end end if not cc.FileUtils:getInstance():isFileExist(spineName..".json") then print("Ani ERROR: not found " .. spineName .. "\n") print(debug.traceback("", 2)) spineName = "ceshi" end local s_pPathSpineBoyJson = spineName..".json" local s_pPathSpineBoyAtlas = spineName..".atlas" return sp.SkeletonAnimation:create(s_pPathSpineBoyJson, s_pPathSpineBoyAtlas, 1) end)
其他需要 的方法自己封裝幾個。這里不寫了。
在整個統一的預加載資源類 ,提前加載spine 等,就可以了。
注釋:
可以使用 createWithData ,添加一個 getAnimationData的方法。原理是一樣的。
以后會追加一篇關於lua異步加載 spine圖片的文章。
追加:
先create 一個母本,在添加到緩存數組的時候,記得retain一下。最后記得釋放release。
要不然創建母本之后,會自己釋放掉,導致直接崩潰。
總結
兄弟們那,一定要多看源碼啊。。。流程應該很清晰了吧、。、、少年們應該能看懂了。交流加我QQ776274781 。大神勿噴。。