前言
本文实现了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 = ); LuaSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = ); 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 = );
static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = );
创建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 = ); // preload spine 添加下面两个方法
static LuaSkeletonAnimation* createWithSkeletonAnimation(SkeletonAnimation* skeletonAnimation);
LuaSkeletonAnimation(SkeletonAnimation* spineData); LuaSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = ); 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 ; int argc = ; #if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L,,"sp.SkeletonAnimation",,&tolua_err)) goto tolua_lerror;
#endif argc = lua_gettop(L) - ; if ( == argc)
{
//TODO
SkeletonAnimation* skeletonAnimation = (SkeletonAnimation*)tolua_tousertype(L, , );
auto tolua_ret = LuaSkeletonAnimation::createWithSkeletonAnimation(skeletonAnimation); int nID = (tolua_ret) ? (int)tolua_ret->_ID : -;
int* pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL;
toluafix_pushusertype_ccobject(L, nID, pLuaID, (void*)tolua_ret,"sp.SkeletonAnimation");
return ;
}
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'createWithSkeletonAnimation'.",&tolua_err);
#endif
return ;
}
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("", ))
spineName = "ceshi"
end local s_pPathSpineBoyJson = spineName..".json"
local s_pPathSpineBoyAtlas = spineName..".atlas" return sp.SkeletonAnimation:create(s_pPathSpineBoyJson, s_pPathSpineBoyAtlas, )
end)
其他需要 的方法自己封装几个。这里不写了。
在整个统一的预加载资源类 ,提前加载spine 等,就可以了。
注释:
可以使用 createWithData ,添加一个 getAnimationData的方法。原理是一样的。
以后会追加一篇关于lua异步加载 spine图片的文章。
追加:
先create 一个母本,在添加到缓存数组的时候,记得retain一下。最后记得释放release。
要不然创建母本之后,会自己释放掉,导致直接崩溃。
总结
兄弟们那,一定要多看源码啊。。。流程应该很清晰了吧、。、、少年们应该能看懂了。交流加我QQ776274781 。大神勿喷。。