Chipmunk简单碰撞

.h文件
#include"cocos2d.h"
#include "chipmunk.h"
#include "extensions/cocos-ext.h"
using namespace cocos2d::extension;
USING_NS_CC;
class ChipmunkTest :public Layer
{
public:
    ChipmunkTest();
    ~ChipmunkTest();
    static Scene* createScene();
    CREATE_FUNC(ChipmunkTest);
    virtual bool init();
public:
    
    void initPhysics();
    void addSpriteAtPos(Point Pos);
    virtual void update(float dt)override;

    static int beginCollision(cpArbiter* arb, cpSpace* space, void* data);
    static int preSolCollision(cpArbiter* arb, cpSpace* space, void* data);
    static void postSolCollision(cpArbiter* arb, cpSpace* space, void* data);
    static void separtCollision(cpArbiter* arb, cpSpace* space, void* data);
    static void postStepRemove(cpSpace* space, cpShape* shape, void* unused);
protected:
    PhysicsDebugNode* m_debugLayer;
    Texture2D* m_texture;
    cpSpace* m_space;
    //cpBody* m_body;
    cpShape* m_walls;
};

cpp文件

#include"ChipmunkTest.h"

int ChipmunkTest::beginCollision(cpArbiter* arb, cpSpace* space, void* data)
{
    CP_ARBITER_GET_SHAPES(arb, a, b);//获取碰撞的两个形状,分别赋予a、b
    //添加碰撞回调函数执行后的回调函数,比如可以用于删除参与碰撞的精灵,因为在碰撞过程中不能删除精灵。
    cpSpaceAddPostStepCallback(space,(cpPostStepFunc)postStepRemove, a, NULL);

    log("begin:aType:%d,bType:%d",a->collision_type,b->collision_type);
    //返回值为false时,碰撞对象会只在初次碰撞时执行回调函数,两个碰撞对象会重叠在一起 
    return 1;
}
int ChipmunkTest::preSolCollision(cpArbiter* arb, cpSpace* space, void* data)
{
    log("pre");
    //当返回值为false时将会一直调用此回调函数,直到碰撞对象分离,两个碰撞对象会重叠在一起 
    return 1;
}
void ChipmunkTest::postSolCollision(cpArbiter* arb, cpSpace* space, void* data)
{
    log("post");
}
void ChipmunkTest::separtCollision(cpArbiter* arb, cpSpace* space, void* data)
{
    log("separt");
}

void ChipmunkTest::postStepRemove(cpSpace* space, cpShape* shape, void* unused)
{
    log("remove shape X:%d,Y:%d",shape->body->p.x,shape->body->p.y);
    PhysicsSprite* sprite = (PhysicsSprite*)shape->data;
  //释放碰撞对象,释放时应注意释放顺序
  //先释放形状
    cpSpaceRemoveShape(space,shape);
    cpShapeFree(shape);
    //释放刚体
    cpSpaceRemoveBody(space, sprite->getCPBody());
    cpBodyFree(sprite->getCPBody());
    //移除精灵
    sprite->removeFromParentAndCleanup(true);

}
ChipmunkTest::ChipmunkTest()
{

}
ChipmunkTest::~ChipmunkTest()
{
    for (int i = 0; i < 4; i++)
    {
        cpShapeFree(m_walls*);
    }
    cpSpaceFree(m_space);

    //cpBodyFree
}
Scene* ChipmunkTest::createScene()
{
    Scene* scene = Scene::create();
    Layer* layer = ChipmunkTest::create();
    scene->addChild(layer);
    return scene;
}
bool ChipmunkTest::init()
{
    Size s = Director::getInstance()->getVisibleSize();
    initPhysics();
    addSpriteAtPos(Point(s.width / 2, s.height / 2));
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = &](Touch* touch, Event* event){
        return true;
    };
    listener->onTouchEnded = &](Touch* touch, Event* event){
        Point Pos = touch->getLocation();
        addSpriteAtPos(Pos);
    };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    
    this->scheduleUpdate();
    return true;
}
void ChipmunkTest::initPhysics()
{
    Size s = Director::getInstance()->getVisibleSize();
    m_space = cpSpaceNew();
    m_space->gravity = cpv(0.0, -100.0);
    //cpInitChipmunk();
    //cpBody* stBody = cpBodyNewStatic();

    //buttom
    m_walls = cpSegmentShapeNew(m_space->staticBody, cpv(0,0), cpv(s.width, 0), 0.0);
    //top
    m_walls = cpSegmentShapeNew(m_space->staticBody, cpv(0, s.height), cpv(s.width, s.height), 0.0);
    //left
    m_walls = cpSegmentShapeNew(m_space->staticBody, cpv(0, 0), cpv(0, s.height), 0.0);
    //right
    m_walls = cpSegmentShapeNew(m_space->staticBody, cpv(s.width, 0), cpv(s.width, s.height), 0.0);

    for (int i = 0; i < 4; i++)
    {
        m_walls*->e = 1.0;  //弹性
        m_walls*->u = 1.0;  // 摩擦力
        m_walls*->collision_type = 0;
        cpSpaceAddStaticShape(m_space, m_walls*);
    }

    m_debugLayer = PhysicsDebugNode::create(m_space);  //添加调试层
    this->addChild(m_debugLayer, 100);
}
void ChipmunkTest::addSpriteAtPos(Point Pos)
{
    
    SpriteBatchNode* parent = SpriteBatchNode::create("blocks.png");
    m_texture = parent->getTexture();
    this->addChild(parent);

    int Posx = CCRANDOM_0_1() * 200;
    int Posy = CCRANDOM_0_1() * 200;
    Posx = (Posx % 2) * 32;
    Posy =( Posy % 2 )* 32;

    int num = 4;
    cpVect verts] = {
        cpv(-16, -16),
        cpv(-16, 16),
        cpv(16, 16),
        cpv(16, -16)
    };
    cpBody* body = cpBodyNew(1.0, cpMomentForPoly(1.0, num, verts, cpvzero));
    body->p = cpv(Pos.x, Pos.y);
    cpSpaceAddBody(m_space, body);

    cpShape* shape = cpPolyShapeNew(body, num, verts, cpvzero);
    shape->e = 0.5;  //弹性系数
    shape->u = 1.0;   //摩擦系数
    shape->collision_type = 1;//碰撞类型
    cpSpaceAddShape(m_space, shape);

    PhysicsSprite* sprite1 = PhysicsSprite::createWithTexture(m_texture, Rect(Posx, Posy, 32, 32));
    
    parent->addChild(sprite1);
    sprite1->setCPBody(body);
    sprite1->setPosition(Point(Pos.x, Pos.y));

    shape->data = sprite1; //shape中用于存储用户的数据,在碰撞回调函数中有用
    //为碰撞事件设定回调函数
    cpSpaceAddCollisionHandler(m_space,      //空间
        1,                                   //参与碰撞的类型
        1,                                   //参与的碰撞的类型
        beginCollision,                      //开始碰撞时执行的回调函数
        preSolCollision,                     //碰撞结束前执行的回调函数
        postSolCollision,                    //碰撞结束后回调函数
        separtCollision,                     //分离回调函数
        NULL);                               //传递的用户自定义数据
    
}
void ChipmunkTest::update(float dt)
{
    int steps = 2;
    float delta = Director::getInstance()->getAnimationInterval()/2;
    for (int i = 0; i < steps; i++)
    {
        cpSpaceStep(m_space, delta);
    }
}



```
*****