您的位置:首页 > 移动开发 > Cocos引擎

spine cocos2d-x runtime修改:支持挂接CCNode到slot,并跟随动画(包括TSR, color, alpha)

2014-03-22 14:39 531 查看
spine的cocos2d-x runtime不是专门为cocos2d-x写的,核心部分是一个通用的spine c runtime,所以对于cocos2d-x的支持不是很好。当然如果只是播个动画啥的也足够了,但是真实使用场景中会有各种需求。比如我们现在需要在spine动画的某个骨骼上绑定一个CCSprite。因为spine的骨骼并不是一个CCNode,所以无法直接绑定,因此需要对spine runtime做一些修改。

核心想法是对于需要绑定的骨骼(其实是slot),生成一个CCNodeRGBA,然后把这个CCNodeRGBA作为CCSkeleton的child,根据骨骼的SRT更新node的TSR,根据slot的rgba设置node的RGBA。这样就可以将任意一个CCNode,如一个CCSprite挂接到该slot/bone上面。如果需要同时支持color动画,则要递归设置node的setCascadeColorEnabled和setCascadeOpacityEnabled。

为了以后升级合并官方runtime方便,我将修改限定在CCSkeleton.h和CCSkeleton.cpp文件中。
CCSkeleton.h中添加:

class CCSkeleton
{
public:
cocos2d::CCNodeRGBA* getNodeForSlot(const char* slotName);
private:
struct sSlotNode
{
spSlot* slot;
cocos2d::CCNodeRGBA* node;
};

typedef std::map<const char*,sSlotNode> SlotNodeMap;
typedef SlotNodeMap::iterator SlotNodeIter;
SlotNodeMap m_slotNodes;

};


方法getNodeForSlot用来根据一个slot name获取一个CCNodeRGBA,如果node不存在则创建。

解释一下为什么不获取骨骼而是获取slot。因为spine runtime中一个骨骼可以带有多个slot,并且除了TSR动画(位移缩放旋转),我们还需要挂接上去的Node能支持Color动画(包含alpha),

那么slot就可以满足条件,并且从slot很容易获取相应的bone。也因为如此,使用CCNodeRGBA而不是CCNode。

我们使用m_slotNodes来保存slot name到slot和node的映射。

下面是CCSkeleton.cpp中的实现:

cocos2d::CCNodeRGBA* CCSkeleton::getNodeForSlot(const char* slotName){
SlotNodeIter iter = m_slotNodes.find(slotName);
if (iter!=m_slotNodes.end()) {
sSlotNode& slot_node = iter->second;
return slot_node.node;
}
else{
spSlot* slot = findSlot(slotName);

if(slot!=NULL){
CCNodeRGBA* node = new CCNodeRGBA();
if(node->init()){
node->autorelease();
}
node->setPosition(0, 0);
this->addChild(node);
sSlotNode slot_node;
slot_node.slot = slot;
slot_node.node = node;
m_slotNodes.insert(SlotNodeMap::value_type(slotName,slot_node));
return node;
}
else{
return NULL;
}
}
}


getNodeForSlot是被客户代码调用的,使用场景是创建CCSkeletonAnimation后,需要将某个CCNode挂接到某个slot上一起动画。此时调用getNodeForSlot获取该slot对应的CCNodeRGBA。

并且使用获取到的CCNodeRGBA作为父node来执行addChild(需要挂接的node)。

getNodeForSlot的实现很简单:如果该slot name对应的CCNodeRGBA不存在,则创建一个并且放入map中。

之后就剩下最核心的工作了,根据bone和slot来更新CCNodeRGBA。按理说,根据骨骼更新transform的代码应该放到spSkeleton_updateWorldTransform中,但是我不想多修改一个文件,所以我直接放到了CCSkeleton::draw ()中,虽然不那么完美,但是直接有效。另外如果放到CCSkeleton::update中其实是会慢一帧的,所以也不能用。

void CCSkeleton::draw () {
//原始代码
//我们添加的代码放到最后好了,放到if (debugSlots) 这行之前即可。
//for each attached CCNodeRGBA, update the TSR and RGBA
for (SlotNodeIter iter=m_slotNodes.begin(), end=m_slotNodes.end(); iter!=end; ++iter) {
sSlotNode& slot_node = iter->second;
spSlot* slot = slot_node.slot;
CCNodeRGBA* node = slot_node.node;
spBone* bone = slot->bone;
if(bone!=NULL){
node->setPosition(ccp(bone->worldX, bone->worldY));
            node->setRotation(-bone->worldRotation);
            node->setScaleX(bone->worldScaleX);
            node->setScaleY(bone->worldScaleY);
}
node->setOpacity(255*slot->a);
node->setColor(ccc3(255*slot->r, 255*slot->g, 255*slot->b));
}
}


这段代码遍历所有我们添加的node,并且找出他所绑定的slot和slot所属的bone。使用bone的x,y,rotation,scale来设置node的相应属性,使用slot的rgba来设置node的opacity和color。
这里的rotation需要反转一下,因为spine runtime的旋转正方向和cocos2d-x不一样。

几乎全部搞定了,但是此时如果将一个CCSprite挂接到getNodeForSlot获取的node上去动画,发现颜色和alpha并不会改变,这是由于我们还没设置CascadeColor和CascadeOpacity,
下面这个方法是从cocos2d-x testcpp工程中拿来的,可以将一个CCNode和其子node递归设置级联透明度和颜色,前提是该node实现了CCRGBAProtocol。因为我们创建的是CCNodeRGBA所以肯定是支持的了,而CCSprite也是支持的,所以再将sprite挂接到rgba node后,执行setEnableRecursiveCascadingRGBA(rgba_node,true)再播放动画,sprite的颜色和alpha就会跟着动画变化了。

static void setEnableRecursiveCascadingRGBA(CCNode* node, bool enable)
{
CCRGBAProtocol* rgba = dynamic_cast<CCRGBAProtocol*>(node);
if (rgba)
{
rgba->setCascadeColorEnabled(enable);
rgba->setCascadeOpacityEnabled(enable);
}

CCObject* obj;
CCArray* children = node->getChildren();
CCARRAY_FOREACH(children, obj)
{
CCNode* child = (CCNode*)obj;
setEnableRecursiveCascadingRGBA(child, enable);
}
}


基本的内容都说完了,那么这个功能的作用是啥呢?可以发挥各种想象力,在这里我要喷一下spine的skin功能,这个功能虽然想法很好,但是局限性太大,必须在编辑器里面将skin创建好并绑定。
如果skin很少还好说,如果有非常多的skin,并且以后游戏内容还是动态更新下载的,就很不方便了,这种大批量的情况下,编辑器里面的操作远远没有配置表方便实用。

当然spine是一个很好的编辑器,我非常喜欢,只是由于作者精力有限并且也不可能了解到所有其他人的需求,所以关键时候我们还得自己动手。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐