1.物理空间初始化
CC_ENABLE_CHIPMUNK_INTEGRATION 这个宏要在预编译的时候设置为1,默认已经设置好了,cpSpaceNew 创建一个物理空间,通过cpSpaceAddCollisionHandler设定碰撞的回调函数,同事指定哪两个类型的sprite的可以产生碰撞。
-
void GameLayer::initPhysics()
-
{
-
#if CC_ENABLE_CHIPMUNK_INTEGRATION
-
-
//创建一个物理空间
-
m_pSpace = cpSpaceNew();
-
//设定空间的加速度,xy方向都是0,没有重力影响
-
m_pSpace->gravity = cpv(
0,
0);
-
-
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
-
-
m_pWalls[
0] = cpSegmentShapeNew( m_pSpace->staticBody,
-
cpv(pEGLView->getVisibleOrigin().x,pEGLView->getVisibleOrigin().y - pEGLView->getVisibleSize().height),
-
cpv(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width,
-
<span> </span>pEGLView->getVisibleOrigin().y - pEGLView->getVisibleSize().height),
-
2.0f);
-
-
// top
-
m_pWalls[
1] = cpSegmentShapeNew( m_pSpace->staticBody,
-
cpv(pEGLView->getVisibleOrigin().x,pEGLView->getVisibleOrigin().y + pEGLView->getVisibleSize().height *
2),
-
cpv(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width,
-
<span> </span>pEGLView->getVisibleOrigin().y + pEGLView->getVisibleSize().height *
2),
-
2.0f);
-
-
for( int i=
0;i<
2;i++) {
-
m_pWalls[i]->e =
1.0f;
-
m_pWalls[i]->u =
1.0f;
-
//设定碰撞类型标识
-
m_pWalls[i]->collision_type=COLLISIONTYPE_WALL;
-
m_pWalls[i]->group = CP_GROUP_WALL;
-
//添加墙体到物理空间
-
cpSpaceAddStaticShape(m_pSpace, m_pWalls[i] );
-
}
-
…
-
//子弹和敌机 设置碰撞的回调函数 EnemyCollision
-
cpSpaceAddCollisionHandler(m_pSpace,COLLISIONTYPE_ENEMY,COLLISIONTYPE_BULLET,EnemyCollision,
NULL,
NULL,
NULL,
NULL);
-
…
-
-
// Physics debug layer
-
// m_pDebugLayer = CCPhysicsDebugNode::create(m_pSpace);
-
// this->addChild(m_pDebugLayer, Z_PHYSICS_DEBUG);
-
#endif
-
-
}
2.刚体创建过程
cpBodyNew创建刚体,cpPolyShapeNew创建形状,分别通过cpSpaceAddBody和cpSpaceAddShape加入到空间里,body和shape是有关联的,通过shape可以找到对应关联body,但是不能通过body找到对应的shape,没找到对应的关系,哪位知道,麻烦告知。我是通过一个 map记录了他们的对应关系,以便在需要的时候使用,就是sp_sh一个sprite到shape的指针映射。
-
bool GameLayer::assembleCPSprite(CCSprite* sprite, CCPoint &pos, cpCollisionType
-
-
collision_type, cpGroup group, bool isplane, cpBodyPositionFunc position_func)
-
{
-
#if CC_ENABLE_CHIPMUNK_INTEGRATION
-
CCSize spriteSize=sprite->getContentSize() * sprite->getScale();
-
int num =
4, length =
0;
-
if (isplane)
-
length = spriteSize.width/
5;
-
else
-
length = spriteSize.width/
3;
-
cpVect verts[] = {
-
cpv(
0-length,
0-length),
-
cpv(
0-length, length),
-
cpv(length, length),
-
cpv(length,
0-length),
-
};
-
cpBody *body = cpBodyNew(
1.0f, cpMomentForPoly(
1.0f, num, verts, cpvzero));
-
body->p = cpv(pos.x, pos.y);
-
body->data = (void *)sprite;
-
if(position_func)
-
body->position_func = position_func;
-
cpSpaceAddBody(m_pSpace, body);
//创建刚体
-
cpShape* shape = cpPolyShapeNew(body, num, verts, cpvzero);
-
shape->e =
0.5f; shape->u =
0.5f;
-
shape->collision_type=collision_type;
-
shape->group = group;
-
shape->data=sprite;
-
cpSpaceAddShape(m_pSpace, shape);
-
((CCPhysicsSprite*)sprite)->setCPBody(body);
-
#endif
-
//设置位置一定要在setCPBody(body)之后
-
sprite->setPosition(pos);
-
sp_sh.insert(std::make_pair(sprite, shape));
-
return
true;
-
}
3.回调函数
通过CP_ARBITER_GET_SHAPES获得了两个刚体的shape,然后通过cpSpaceAddPostStepCallback设置回调函数postStepRemove,把shape传进去,这样就能找到对应的body,已经对应的sprite,进行分别消除。。。这个地方如果传入的是 body,就无法找到shape了…
-
int GameLayer::EnemyCollision(cpArbiter *arb, cpSpace *space,
void *data)
-
{
-
#if CC_ENABLE_CHIPMUNK_INTEGRATION
-
//获取碰撞的shape,a代表用cpSpaceAddCollisionHandler添加碰撞回调时的碰撞对象类型a,b亦然
-
CP_ARBITER_GET_SHAPES(arb, a, b);
-
//设置物理空间在结束当前动作时的回调函数,用于安全释放对象,此调用只会在完成当前动作后调用一次
-
cpSpaceAddPostStepCallback(space,(cpPostStepFunc)postStepRemove,a,
NULL);
-
cpSpaceAddPostStepCallback(space,(cpPostStepFunc)postStepRemove,b,
NULL);
-
#endif
-
//返回值为false时,碰撞对象会只在初次碰撞时执行回调函数,两个碰撞对象会重叠在一起
-
return
true;
-
}
4.刚体销毁
销毁要注意顺序,顺序不对,可能会程序崩溃还有并不是什么时候都可以销毁的,一定要在结束当前动作时销毁,不然会有各种锁的问题导致程序崩溃,试试就知道了
-
void GameLayer::postStepRemove(cpSpace *space, cpShape *shape, void *unused)
-
{
-
CCPhysicsSprite *sprite = (CCPhysicsSprite*)shape->data;
-
-
//释放碰撞的对象,这里释放时要注意顺序
-
//先释放形状
-
cpSpaceRemoveShape(space, shape);
-
cpShapeFree(shape);
-
//释放刚体
-
cpSpaceRemoveBody(space, sprite->getCPBody());
-
cpBodyFree(sprite->getCPBody());
-
-
//移除精灵
-
sprite->removeFromParentAndCleanup(
true);
-
sp_sh.erase(sprite);
-
}
</div>