cocos2d-x 菜鸟学习笔记十四(简单的碰撞检测 进阶篇)

来源:互联网 发布:中华软件股份公司 编辑:程序博客网 时间:2024/04/19 22:42

上一篇记录了chipmunk的使用流程,其实还算不上是碰撞检测,但在游戏中需要利用这些碰撞事件来执行对应的动作,这就涉及到另一部分的内容了,即怎样在发生碰撞事件的时候调用对应的工作代码。

首先是为碰撞事件设定回调函数:

在chipmunk中有两种设定碰撞回调函数的方法,一种是cpSpaceSetDefaultCollisionHandler,另一种是cpSpaceAddCollisionHandler。

cpSpaceSetDefaultCollisionHandler是为物理空间设定默认的碰撞回调函数,它的设置是针对全局的,也就是物理空间里任何对象的碰撞都会执行设定的回调函数:

void cpSpaceSetDefaultCollisionHandler(cpSpace *space,cpCollisionBeginFunc begin,cpCollisionPreSolveFunc preSolve,cpCollisionPostSolveFunc postSolve,cpCollisionSeparateFunc separate,void *data);

cpSpaceAddCollisionHandler用来设定自定义的碰撞回调规则,比上面多出了两个参数,用来指定物理空间中哪类对象碰撞时执行回调函数:

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);}

通过上面添加的代码,就可以实现碰撞事件产生时获取需要的信息,并且在不需要时释放掉,自己改装一下就可以做出一个子弹碰撞怪物时的kill事件。

碰撞检测进阶篇源码:http://download.csdn.net/detail/cyistudio/5522053



原创粉丝点击