spine实现预加载(一)

好久不见. 提交于 2020-03-29 12:01:27

前言

  本文实现了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 。大神勿喷。。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!