spine實現預加載(一)


前言

  本文實現了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 。大神勿噴。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM