.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);
}
}
```
*****