在之前,笔者写过一编博客,通过lua在加载场景加载spineAnimation动画精灵,保存在table中,然后在游戏中创建动画精灵时,提取加载好的spineAnimaiton中的
spSkeletonData来创建spineAnimation,但后来笔者发现重复创建spineAnimation时,全部相同spSkeletonData会重用同一个spSkeletonData,以下是spSkeletonData拷贝方法的源代码:
spSkeleton* spSkeleton_create (spSkeletonData* data) {
int i, ii;
_spSkeleton* internal = NEW(_spSkeleton);
spSkeleton* self = SUPER(internal);
CONST_CAST(spSkeletonData*, self->data) = data;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
spBone* parent = 0;
if (boneData->parent) {
/* Find parent bone. */
for (ii = 0; ii < self->bonesCount; ++ii) {
if (data->bones[ii] == boneData->parent) {
parent = self->bones[ii];
break;
}
}
}
self->bones[i] = spBone_create(boneData, self, parent);
}
CONST_CAST(spBone*, self->root) = self->bones[0];
self->slotsCount = data->slotsCount;
self->slots = MALLOC(spSlot*, self->slotsCount);
for (i = 0; i < self->slotsCount; ++i) {
spSlotData *slotData = data->slots[i];
/* Find bone for the slotData's boneData. */
spBone* bone = 0;
for (ii = 0; ii < self->bonesCount; ++ii) {
if (data->bones[ii] == slotData->boneData) {
bone = self->bones[ii];
break;
}
}
self->slots[i] = spSlot_create(slotData, bone);
}
self->drawOrder = MALLOC(spSlot*, self->slotsCount);
memcpy(self->drawOrder, self->slots, sizeof(spSlot*) * self->slotsCount);
self->r = 1;
self->g = 1;
self->b = 1;
self->a = 1;
self->ikConstraintsCount = data->ikConstraintsCount;
self->ikConstraints = MALLOC(spIkConstraint*, self->ikConstraintsCount);
for (i = 0; i < self->data->ikConstraintsCount; ++i)
self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);
spSkeleton_updateCache(self);
return self;
}
在拷贝当中,骨骼数据确实新开辟一个内存,拷贝了一份新的spSkeletonData,但是,由于spSkeletonData属于在table中保存的SkeletonAnimation中,受到SkeletonAnimation的影响,所以不能使用SkeletonAnimation中的spSkeletonData去创建另外一个SkeletonAnimation。
笔者也试过从lua中创建spSkeletonData数据,保存在table中,然后在游戏中传递spSkeletonData去创建SkeletonAnimation,
但在切换场景过程中,spSkeletonData会被释放掉,所以不能被复用。
后来笔者从c++入手,将spSkeletonData保存在c++静态的字典中,通过键值提取spSkeletonData去创建SkeletonAnimation,避免释放问题。
以下是实现方法:
//SpineAnimation_new.h
#include <stdio.h>
#include "cocos/editor-support/spine/SkeletonAnimation.h"
#include "cocos/editor-support/spine/spine.h"
#include "spine/SkeletonRenderer.h"
#include "cocos2d.h"
using namespace spine;
using namespace std;
class SpineAnimation_new:spine::SkeletonAnimation
{
public:
static SpineAnimation_new *createWithSkeletonData(spSkeletonData* skeletonData);
static SpineAnimation_new *createWithKey(const std::string& key);
virtual ~SpineAnimation_new();
spAnimationState* getState() {return SkeletonAnimation::getState();}
spSkeletonData* getSkeletonData()
{
spSkeletonData*skData =SkeletonRenderer::getSkeleton()->data;
return skData;
}
static spSkeletonData*loadSkeletonData(const std::string& atlasFile,const std::string& jsonFile,const std::string& key);
static map<const std::string,spSkeletonData*> skeletonDataMap;
static void clear();
private:
SpineAnimation_new(spSkeletonData*skeletonData);
SpineAnimation_new(const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
};
#endif
//SpineAnimation_new.cpp
#include "SpineAnimation_new.h"
#include "cocos2d.h"
#include "cocos/scripting/lua-bindings/manual/cocos2d/LuaScriptHandlerMgr.h"
#include "CCLuaStack.h"
#include "CCLuaEngine.h"
USING_NS_CC;
map<const std::string,spSkeletonData*> SpineAnimation_new::skeletonDataMap;
SpineAnimation_new *SpineAnimation_new::createWithSkeletonData(spSkeletonData* skeletonData)
{
SpineAnimation_new* node = new (std::nothrow)SpineAnimation_new(skeletonData);
node->autorelease();
return node;
}
spSkeletonData*SpineAnimation_new::loadSkeletonData(const std::string& atlasFile,const std::string& jsonFile,const std::string& key)
{
spAtlas* atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = 1;
spSkeletonData* sd = spSkeletonJson_readSkeletonDataFile(json, jsonFile.c_str());
SpineAnimation_new::skeletonDataMap.insert(pair<const std::string,spSkeletonData*>(key,sd));
return sd;
}
SpineAnimation_new *SpineAnimation_new::createWithKey(const std::string& key)
{
map<const std::string,spSkeletonData*>::iterator iter = SpineAnimation_new::skeletonDataMap.find(key);
spSkeletonData* sd = iter->second;
SpineAnimation_new*sa = createWithSkeletonData(sd);
return sa;
}
SpineAnimation_new::~SpineAnimation_new()
{
ScriptHandlerMgr::getInstance()->removeObjectAllHandlers((void*)this);
}
SpineAnimation_new::SpineAnimation_new(spSkeletonData*skeletonData):
SkeletonAnimation(skeletonData)
{
}
SpineAnimation_new::SpineAnimation_new(const std::string& skeletonDataFile, const std::string& atlasFile, float scale):SkeletonAnimation(skeletonDataFile,atlasFile,scale)
{
}
void SpineAnimation_new::clear()
{
SpineAnimation_new::skeletonDataMap.clear();
}
(转载时请注明出处,from 博客园:HemJohn)