因为项目的需要,cocos骨骼动画使用了spine,之前是使用cocosstudio,也不是ccs不好,毕竟spine是这方面的强项,不废话,直接上干货:
1.需要的头文件:
#include "spine/spine.h"
#include <spine/spine-cocos2dx.h>
using namespace spine;
2.接着创建spine动画
spine::SkeletonAnimation* spine=SkeletonAnimation::createWithFile(JsonFile,AtlasFile);
3.绑定一些回调:
当动画要开始播放的时候,回调格式为:
typedef std::function<void(int trackIndex)> StartListener;
绑定代码:
spine->setStartListener(CC_CALLBACK_1(Card::spineStar, this));
当动画跳出播放的时候,一般都是发生在动画切换的过程,回调格式:
typedef std::function<void(int trackIndex)> EndListener;
绑定代码:
spine->setStartListener(CC_CALLBACK_1(Card::spineEnd, this));
当前动画完成一个播放的时候,回调格式:
typedef std::function<void(int trackIndex, int loopCount)> CompleteListener;
回调代码:
spine->setStartListener(CC_CALLBACK_1(Card::spineComplete, this));
帧事件回调格式:
typedef std::function<void(int trackIndex, spEvent* event)> EventListener;
帧时间回调代码:需要说明的是,这个事件是由动作师在某个帧添加的,当执行到该动画的该帧的时候,就会触发回调。
spine->setStartListener(CC_CALLBACK_1(Card::spineEvent, this));
4.一个高级点的用法:
(1)设置动画切换过度时间,这样在动画过度的时候,有个缓冲时间,如果两个动作衔接点差别有点大,设置一下效果很好,这也是体现spine价值的地方。
spine->setMix(SPINE_MOVE_NAME, SPINE_IDLE_NAME, 0.1f);
(2)设置调试模式:
spine在调试模式,可以看到骨头的长度,骨点的位置:
sine->setDebugBonesEnabled(true);
也可以设置查看每个骨头绑定的图片的大小,会用矩形框显示出来:
spine->setDebugSlotsEnabled(true);
(3)设置缩放,设置播放速度:
spine->setScale(0.5f);
//播放速度暂时没有用到,以后补充
(4)获取某块骨头的位置:
spBone* bone = spine->findBone("hand");
float x = bone->worldX;
float y = bone->worldY;
float scale = spine->getScale();
Vec2 pos = Vec2(x,y)*scale;
需要说明的是:
findBone()返回的是结构体,当时我也迷惑怎么获取到位置信息,如果需要看为啥用这个,可以查看spineDraw函数,里面也是这么用的。
骨头的位置坐标是基于spine软件里面的(0,0)点,并且,是没有进行程序缩放的位置,所以最后一步要乘以scale。
(5)删除spine骨骼内存
void EffectAbstract::spineEnd(int trackIndex)
{
this->removeFromParent();
}
这段代码从理论上来说,spine的回调函数没有多少问题,但是实际运行到removeFromParent之后,程序就会立马崩溃,而且断点段在引擎spine代码中,这个问题纠结了一个上午,后来想到是不是我延时删除可不可以,试了之后,果然可以,不知道这算不算一个坑,反正是爬出来了,正确的代码:
void EffectAbstract::spineEnd(int trackIndex)
{
CCDelayTime* time = CCDelayTime::create(1);
CCCallFunc* callBack = CCCallFunc::create([=]()
{
this->removeFromParent();
});
this->runAction(CCSequence::create(time, callBack, nullptr));
}
(6) spine换装
局部换装用skine,修改底层代码:\cocos2d\cocos\editor-support\spine下面修改SkeletonAnimation.cpp,
//自己加一个局部换装的函数
bool SkeletonAnimation::replacementParts(const std::string& skinName, const std::string& attachmentName)
{
if (skinName.empty())
{
return false;
}
spSkin *skin = spSkeletonData_findSkin(_skeleton->data, skinName.c_str());
if (!skin) return false;
for (int i = 0; i < _skeleton->slotsCount; ++i)
{
spSlot* slot = _skeleton->slots[i];
if (strcmp(slot->data->name, attachmentName.c_str()) == 0)
{
spAttachment* attachment = spSkin_getAttachment(skin, i, slot->data->attachmentName);
if (attachment) spSlot_setAttachment(slot, attachment);
return true;
}
}
return false;
}
}
目前用到的就这么多,可能还要用到,后续更新。现在自己的游戏做的有点烂,要加把油了!