文章转载自:http://www.cocoachina.com/bbs/read.php?tid=189665
CocoStuido sample----SampleCollision源代码地址
https://github.com/chukong/CocoStudioSamples
大家可以预先下载这个源代码, 等下要用到里面的图片资源哦
今天我们再来学习下骨骼动画在CocoStudio中的制作. 骨骼动画由各个关节有机的结合起来, 并附着以皮肤. 当关节运动时, 相关的关节会一起运动, 以达到更加真实的动画效果.
代码实现
我们要在cocos2d-x工程中实现两个牛仔, 一个走路, 一个打枪, 子弹和牛仔碰撞后, 牛仔消失一下.
代码中包含了普通, box2d, chipmunk三种碰撞判断, box2d, chipmunk这两种判断方式太过复杂, 我们这次就不再展开了, 只带大家看下普通的碰撞判断.
我们创建一个TestColliderDetector类, 包含TestColliderDetector.h 和 TestColliderDetector.cpp.
先来看下TestColliderDetector.h
#include "cocos2d.h"
#include "cocos-ext.h"
class TestColliderDetector : public cocos2d:: CCLayer
{
public :
~TestColliderDetector();
virtual void onEnter();
virtual void update( float delta); //检测对象位置,判断是否有碰撞
virtual void draw(); //绘制右边牛仔的碰撞区域
//帧事件响应函数
void onFrameEvent(cocos2d::extension:: CCBone *bone, const char *evt, int originFrameIndex, intcurrentFrameIndex);
//左边牛仔对象
cocos2d::extension:: CCArmature *armature;
//右边牛仔对象
cocos2d::extension:: CCArmature *armature2;
//子弹对象
cocos2d:: CCSprite * bullet;
};
TestColliderDetector.cpp
#include "TestColliderDetector.h"
using namespace cocos2d;
using namespace cocos2d::extension;
TestColliderDetector ::~TestColliderDetector()
{
//CCArmatureDataManager::purge();
}
void TestColliderDetector ::onEnter()
{
CCLayer ::onEnter();
scheduleUpdate(); //每帧都会调用update函数, 用于碰撞判断
//加载动画数据
CCArmatureDataManager ::sharedArmatureDataManager()->addArmatureFileInfo( "Cowboy0.png","Cowboy0.plist" , "Cowboy.ExportJson");
//左边牛仔对象
armature = CCArmature ::create("Cowboy" );
armature->getAnimation()->play( "FireWithoutBullet" );//播放FireWithoutBullet动画
armature->getAnimation()->setSpeedScale(0.2f); //以0.2倍的速度播放, 牛仔动作会比较慢
armature->setScaleX(-0.2f); //缩放牛仔, 并且让牛仔脸向右
armature->setScaleY(0.2f);
armature->setPosition( ccp (CCDirector ::sharedDirector()->getVisibleSize().width * 0.2, CCDirector ::sharedDirector()->getVisibleSize().height * 0.5));
//给左边牛仔对象绑定对象
armature->getAnimation()->setFrameEventCallFunc( this , frameEvent_selector (TestColliderDetector ::onFrameEvent));
addChild(armature);
//右边牛仔对象
armature2 = cocos2d::extension:: CCArmature ::create("Cowboy" );
armature2->getAnimation()->play( "Walk" );//播放Walk动画
armature2->setScaleX(-0.2f); //缩放牛仔, 并且让牛仔脸向右
armature2->setScaleY(0.2f);
armature2->setPosition( ccp (CCDirector ::sharedDirector()->getVisibleSize().width * 0.8, CCDirector ::sharedDirector()->getVisibleSize().height * 0.5));
addChild(armature2);
//创建子弹对象
bullet = CCSprite ::createWithSpriteFrameName("25.png" );
addChild(bullet);
}
//我们刚才在编辑器中设置的帧事件会调用这个函数
void TestColliderDetector ::onFrameEvent( CCBone * bone , const char * evt, int originFrameIndex, intcurrentFrameIndex )
{
//获取武器所在节点的坐标
CCPoint p = armature->getBone("gun" )->getDisplayRenderNode()->convertToWorldSpaceAR( ccp (0, 0));
//设置子弹的坐标
bullet->setPosition( ccp (p.x + 60, p.y));
bullet->stopAllActions();
//子弹向右运动
bullet->runAction( CCMoveBy ::create(2.5f, ccp (CCDirector ::sharedDirector()->getVisibleSize().width, 0)));
}
void TestColliderDetector ::update( float delta)
{
//先设置右边牛仔对象可见
armature2->setVisible( true );
//获取子弹的boundingBox区域, 用于碰撞检测
CCRect rect = bullet->boundingBox();
//逐一判断左边牛仔子节点中碰撞区域, 是否与子弹有相交之处
CCDictElement *element = NULL ;
CCDictionary *dict = armature2->getBoneDic();
CCDICT_FOREACH(dict, element)
{
CCBone *bone = static_cast < CCBone*>(element->getObject());
CCArray *bodyList = bone->getColliderBodyList();
CCObject *object = NULL ;
CCARRAY_FOREACH (bodyList, object)
{
ColliderBody *body = static_cast < ColliderBody*>(object);
CCArray *vertexList = body->getCalculatedVertexList();
float minx, miny, maxx, maxy = 0;
int length = vertexList->count();
for (int i = 0; i<length; i++)
{
CCContourVertex2 *vertex = static_cast < CCContourVertex2*>(vertexList->objectAtIndex(i));
if (i == 0)
{
minx = maxx = vertex->x;
miny = maxy = vertex->y;
}
else
{
minx = vertex->x < minx ? vertex->x : minx;
miny = vertex->y < miny ? vertex->y : miny;
maxx = vertex->x > maxx ? vertex->x : maxx;
maxy = vertex->y > maxy ? vertex->y : maxy;
}
}
CCRect temp = CCRectMake (minx, miny, maxx - minx, maxy - miny);
if (temp.intersectsRect(rect))
{
//与子弹相交隐藏右边牛仔
armature2->setVisible( false );
}
}
}
}
//绘制右边牛仔的碰撞区
void TestColliderDetector ::draw()
{
armature2->drawContour();
}