上一篇记录了chipmunk的使用流程,其实还算不上是碰撞检测,但在游戏中需要利用这些碰撞事件来执行对应的动作,这就涉及到另一部分的内容了,即怎样在发生碰撞事件的时候调用对应的工作代码。
首先是为碰撞事件设定回调函数:
在chipmunk中有两种设定碰撞回调函数的方法,一种是cpSpaceSetDefaultCollisionHandler,另一种是cpSpaceAddCollisionHandler。
cpSpaceSetDefaultCollisionHandler是为物理空间设定默认的碰撞回调函数,它的设置是针对全局的,也就是物理空间里任何对象的碰撞都会执行设定的回调函数:
void cpSpaceSetDefaultCollisionHandler( cpSpace *space, cpCollisionBeginFunc begin, cpCollisionPreSolveFunc preSolve, cpCollisionPostSolveFunc postSolve, cpCollisionSeparateFunc separate, void *data );
void cpSpaceAddCollisionHandler( cpSpace *space, cpCollisionType a, cpCollisionType b, cpCollisionBeginFunc begin, cpCollisionPreSolveFunc preSolve, cpCollisionPostSolveFunc postSolve, cpCollisionSeparateFunc separate, void *data );
//碰撞开始时的回调 static int beginCollision(cpArbiter *arb, cpSpace *space, void *data); //单次碰撞准备结束时的回调 static int preSolveCollision(cpArbiter *arb, cpSpace *space, void *data); //单次碰撞结束时的回调 static void postSolveCollision(cpArbiter *arb, cpSpace *space, void *data); //碰撞对象分离后的回调 static void seperateCollision(cpArbiter *arb, cpSpace *space, void *data);
int HelloWorld::beginCollision(cpArbiter *arb, cpSpace *space, void *data){
CCLog("begin collision");
//返回值为false时,碰撞对象会只在初次碰撞时执行回调函数,两个碰撞对象会重叠在一起
return false;
}
int HelloWorld::preSolveCollision(cpArbiter *arb, cpSpace *space, void *data)
{
CCLog("preSolve collision");
//当返回值为false时将会一直调用此回调函数,直到碰撞对象分离,两个碰撞对象会重叠在一起
return true;
}
void HelloWorld::postSolveCollision(cpArbiter *arb, cpSpace *space, void *data)
{
CCLog("PostSolve collision");
}
void HelloWorld::seperateCollision(cpArbiter *arb, cpSpace *space, void *data){
CCLog("Seperate collision");
}
指定两类对象在碰撞时执行设定的回调函数:
shape->collision_type=1; //为shape设定碰撞类型标识参数
cpSpaceAddShape(m_pSpace, shape);
cpSpaceAddCollisionHandler(m_pSpace,1,1,beginCollision,preSolveCollision,postSolveCollision,seperateCollision,NULL);
当发生碰撞时,我们有时会想要取得碰撞对象的信息,比如判断是哪个对象被碰撞、碰撞对象所在的位置……这就需要在添加精灵时加一句:
//这里用于将精灵的数据装载进shape中的data里待后面需要时调用对应数据 shape->data=sprite
int HelloWorld::beginCollision(cpArbiter *arb, cpSpace *space, void *data){ //获取碰撞的shape,a代表用cpSpaceAddCollisionHandler添加碰撞回调时的碰撞对象类型a,b亦然 CP_ARBITER_GET_SHAPES(arb, a, b); CCLog("begin collision p_x:%1.1f p_y:%1.1f",a->body->p.x,a->body->p.y); //设置物理空间在结束当前动作时的回调函数,用于安全释放对象,此调用只会在完成当前动作后调用一次 cpSpaceAddPostStepCallback(space,(cpPostStepFunc)postStepRemove,a,NULL); //返回值为false时,碰撞对象会只在初次碰撞时执行回调函数,两个碰撞对象会重叠在一起 return true; }
在上面,我在碰撞开始时我通过CP_ARBITER_GET_SHAPES获取了碰撞对象类型为1(即碰撞形状代号为a)的刚体的坐标数据并输出到日志,并调用了一个用于销毁碰撞对象a的回调函数postStepRemove,看看里面的对应代码:
void HelloWorld::postStepRemove(cpSpace *space, cpShape *shape, void *unused){ //CCLog("postStep p_x:%1.f p_y:%1.f",shape->body->p.x,shape->body->p.y); CCPhysicsSprite *sprite = (CCPhysicsSprite*)shape->data; //CCLog("%1d",sprite->getTag()); //释放碰撞的对象,这里释放时要注意顺序 //先释放形状 cpSpaceRemoveShape(space, shape); cpShapeFree(shape); //释放刚体 cpSpaceRemoveBody(space, sprite->getCPBody()); cpBodyFree(sprite->getCPBody()); //移除精灵 sprite->removeFromParentAndCleanup(true); }
碰撞检测进阶篇源码:http://download.csdn.net/detail/cyistudio/5522053