- /
#ifndef __CCCOLLIDERDETECTOR_H__
#define __CCCOLLIDERDETECTOR_H__
#include "cocostudio/CCArmatureDefine.h"
#include "cocostudio/CCDatas.h"
#ifndef PT_RATIO
#define PT_RATIO 32
#endif
#if ENABLE_PHYSICS_CHIPMUNK_DETECT
#include "chipmunk.h"
#elif ENABLE_PHYSICS_Box2D_DETECT
#endif
namespace cocostudio {
class Bone;
/**
* @js NA
* @lua NA
*/
class ColliderFilter
{
public:
virtual ~ColliderFilter() { }
#if ENABLE_PHYSICS_Box2D_DETECT
public:
ColliderFilter(uint16 categoryBits = 0x0001,uint16 maskBits = 0xFFFF,int16 groupIndex = 0);
void updateShape(b2Fixture *fixture);
virtual void setCategoryBits(uint16 categoryBits) { _categoryBits = categoryBits; }
virtual uint16 getCategoryBits() const { return _categoryBits; }
virtual void setMaskBits(uint16 maskBits) { _maskBits = maskBits; }
virtual uint16 getMaskBits() const { return _maskBits; }
virtual void setGroupIndex(int16 groupIndex) { _groupIndex = groupIndex; }
virtual int16 getGroupIndex() const { return _groupIndex; }
protected:
uint16 _categoryBits;
uint16 _maskBits;
int16 _groupIndex;
#elif ENABLE_PHYSICS_CHIPMUNK_DETECT
public:
ColliderFilter(cpCollisionType collisionType = 0,cpGroup group = 0);
void updateShape(cpShape *shape);
virtual void setCollisionType(cpCollisionType collisionType) { _collisionType = collisionType; }
virtual cpCollisionType getCollisionType() const { return _collisionType; }
virtual void setGroup(cpGroup group) { _group = group; }
virtual cpGroup getGroup() const { return _group; }
protected:
cpCollisionType _collisionType;
cpGroup _group;
#endif
};
- //碰撞框
- class ColliderBody : public cocos2d::Ref
- {
- public:
- ColliderBody(ContourData *contourData);
- ~ColliderBody();
- inline ContourData *getContourData() { return _contourData; }
- #if ENABLE_PHYSICS_Box2D_DETECT || ENABLE_PHYSICS_CHIPMUNK_DETECT
- void setColliderFilter(ColliderFilter *filter);
- ColliderFilter *getColliderFilter();
- #endif
- #if ENABLE_PHYSICS_Box2D_DETECT
- virtual void setB2Fixture(b2Fixture *fixture) { _fixture = fixture; }
- virtual b2Fixture *getB2Fixture() const { return _fixture; }
- #elif ENABLE_PHYSICS_CHIPMUNK_DETECT
- virtual void setShape(cpShape *shape) { _shape = shape; }
- virtual cpShape *getShape() const { return _shape; }
- #elif ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
- virtual const std::vector<cocos2d::Point> &getCalculatedVertexList() const { return _calculatedVertexList; }
- #endif
- private:
- #if ENABLE_PHYSICS_Box2D_DETECT
- b2Fixture *_fixture;
- ColliderFilter *_filter;
- #elif ENABLE_PHYSICS_CHIPMUNK_DETECT
- cpShape *_shape;
- ColliderFilter *_filter;
- #elif ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
- vector<cocos2d::Point> _calculatedVertexList;//所有顶点
- #endif
- ContourData *_contourData;//轮廓数据
- friend class ColliderDetector;
- };
- /*
- * @brief ContourSprite used to draw the contour of the display
- * @js NA
- * @lua NA
- */
- class ColliderDetector : public cocos2d::Ref
- {
- public:
- static ColliderDetector *create();
- static ColliderDetector *create(Bone *bone);
- public:
- /**
- * @js ctor
- */
- ColliderDetector();
- /**
- * @js NA
- * @lua NA
- */
- ~ColliderDetector(void);
- virtual bool init();
- virtual bool init(Bone *bone);
- void addContourData(ContourData *contourData);//手动添加 一个 轮廓顶点信息数据
- void addContourDataList(cocos2d::Vector<ContourData*> &contourDataList);//手动添加 一组 轮廓顶点信息数据
- void removeContourData(ContourData *contourData);//手动移除 一个 轮廓顶点信息数据
- void removeAll();//手动添加 所有 轮廓顶点信息数据
- void updateTransform(kmMat4 &t);//旋转更新
- void setActive(bool active);//设置激活状态
- bool getActive();
- const cocos2d::Vector<ColliderBody*>& getColliderBodyList();//得到所有轮廓框信息
- #if ENABLE_PHYSICS_Box2D_DETECT || ENABLE_PHYSICS_CHIPMUNK_DETECT
- virtual void setColliderFilter(ColliderFilter *filter);
- virtual ColliderFilter *getColliderFilter();
- #endif
- virtual void setBone(Bone *bone) { _bone = bone; }
- virtual Bone *getBone() const { return _bone; }
- #if ENABLE_PHYSICS_Box2D_DETECT
- virtual void setBody(b2Body *body);
- virtual b2Body *getBody() const;
- #elif ENABLE_PHYSICS_CHIPMUNK_DETECT
- virtual void setBody(cpBody *body);
- virtual cpBody *getBody() const;
- #endif
- protected:
- cocos2d::Vector<ColliderBody*> _colliderBodyList;//碰撞body
- Bone *_bone;//骨骼
- #if ENABLE_PHYSICS_Box2D_DETECT
- b2Body *_body;
- ColliderFilter *_filter;
- #elif ENABLE_PHYSICS_CHIPMUNK_DETECT
- cpBody *_body;
- ColliderFilter *_filter;
- #endif
- protected:
- bool _active;//是否激活
- };
- }
- #endif /*__CCCOLLIDERDETECTOR_H__*/
- class TestColliderDetector : public ArmatureTestLayer
- {
- public:
- ~TestColliderDetector();
- virtual void onEnter() override;
- virtual std::string title() const override;
- virtual void update(float delta);
- virtual void draw(Renderer *renderer,const kmMat4 &transform,bool transformUpdated) override;
- void onDraw(const kmMat4 &transform,bool transformUpdated);
- void onFrameEvent(cocostudio::Bone *bone,const std::string& evt,int originFrameIndex,int currentFrameIndex);
- void initWorld() {};
- cocostudio::Armature *armature;
- cocostudio::Armature *armature2;
- CustomCommand _customCommand; //new render needed this for drawing primitives
- cocos2d::Sprite *bullet;
- };
- void TestColliderDetector::update(float delta)
- {
- armature2->setVisible(true);
- //
- // CCNode中两个个方法方法:
- // getContentSize用来获得节点原始大小。返回CGSize类型
- // getBoundingBox获得节点当前大小,即如果经过缩放那么就是缩放后的大小。返回CGRect类型。
- // 有个问题最近才遇到,父精灵进行缩放处理,会对子精灵进行标记(boolean值),在实际绘制过程中会影响子精灵显示大小,但并不改变子精灵的getBoundingBox所获得的值,也就是只有直接setscale才会影响getBoundingBox数值。
- // CCSprite中有个方法:
- // getTextureRect返回精灵纹理大小,返回CGRect类型,并且是原始纹理大小,无关缩放。在一般情况下和getContentSize作用一样,但如果用TP处理过,还回值是实际纹理大小,留白部分会去除。这个在碰撞检测过程中经常用到。
- Rect rect = bullet->getBoundingBox();
- // This code is just telling how to get the vertex.
- // For a more accurate collider detection,you need to implemente yourself.
- const Map<std::string,Bone*>& map = armature2->getBoneDic();//得到骨骼字典
- for(const auto& element : map)//遍历字典
- {
- Bone *bone = element.second;
- ColliderDetector *detector = bone->getColliderDetector();
- if (!detector)//如否没有碰撞 跳过 继续遍历
- continue;
- //得到碰撞框列表
- const cocos2d::Vector<ColliderBody*>& bodyList = detector->getColliderBodyList();
- for (const auto& object : bodyList)
- {
- //得到一个碰撞框
- ColliderBody *body = static_cast<ColliderBody*>(object);
- //一个碰撞框包含的所有顶点
- const vector<Point> &vertexList = body->getCalculatedVertexList();
- float minx = 0,miny = 0;
- int length = (int)vertexList.size();//顶点个数
- for (int i = 0; i<length; i++)
- {
- Point vertex = vertexList.at(i);
- if (i == 0)
- {
- minx = maxx = vertex.x;//起点和终点 是 第一个点
- miny = maxy = vertex.y;
- }
- else//遍历所有点 得到4个最值
- {
- 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;
- }
}
Rect temp = Rect(minx,miny,maxx - minx,maxy - miny);//组成一个包含所有顶点的矩形 if (temp.intersectsRect(rect)) { //子弹矩形在碰撞区域内 碰撞框不可见 armature2->setVisible(false); } } }}
void TestColliderDetector::draw(Renderer *renderer,bool transformUpdated){
_customCommand.init(_globalZOrder); _customCommand.func = CC_CALLBACK_0(TestColliderDetector::onDraw,this,transform,transformUpdated); renderer->addCommand(&_customCommand);}
void TestColliderDetector::onDraw(const kmMat4 &transform,bool transformUpdated){
kmGLPushMatrix(); kmGLLoadMatrix(&transform);
armature2->drawContour();
kmGLPopMatrix();}
TestColliderDetector::~TestColliderDetector(){
}
void TestColliderDetector::onEnter(){
ArmatureTestLayer::onEnter(); scheduleUpdate(); armature = Armature::create("Cowboy"); armature->getAnimation()->play("FireWithoutBullet"); armature->getAnimation()->setSpeedScale(0.2f); armature->setScaleX(-2f); armature->setScaleY(2f); armature->setPosition(Point(VisibleRect::left().x + 70,VisibleRect::left().y)); /** Set armature's frame event callback function
* To disconnect this event,just setFrameEventCallFunc(nullptr);
*/
armature->getAnimation()->setFrameEventCallFunc(CC_CALLBACK_0(TestColliderDetector::onFrameEvent,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4)); addChild(armature); armature2 = Armature::create("Cowboy"); armature2->getAnimation()->play("Walk"); armature2->setScaleX(-2f); armature2->setScaleY(2f); armature2->setPosition(Point(VisibleRect::right().x - 60,VisibleRect::left().y)); addChild(armature2);#if ENABLE_PHYSICS_Box2D_DETECT || ENABLE_PHYSICS_CHIPMUNK_DETECT
bullet = cocos2d::extension::PhysicsSprite::createWithSpriteFrameName("25.png");#elif ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX
bullet = Sprite::createWithSpriteFrameName(#endif addChild(bullet); initWorld();}
std::string TestColliderDetector::title() const{
return "Test Collider Detector";}
void TestColliderDetector::onFrameEvent(Bone *bone,const std::string& evt,int currentFrameIndex){
CCLOG("(%s) emit a frame event (%s) at frame index (%d).",bone->getName().c_str(),evt.c_str(),currentFrameIndex); /** originFrameIndex is the frame index editted in Action Editor
* currentFrameIndex is the current index animation played to
* frame event may be delay emit,so originFrameIndex may be different from currentFrameIndex.
*/
Point p = armature->getBone("Layer126")->getDisplayRenderNode()->convertToWorldSpaceAR(Point(0)); bullet->setPosition(Point(p.x + y)); bullet->stopAllActions(); bullet->runAction(CCMoveBy::create(1.5f,Point(350,153)">0)));}
参考原地址:http://www.tuicool.com/articles/bUz6BrM