cocos2dx从3.0开始自己封装了物理引擎,当然是基于chipmunk。相对box2d来讲,chipmunk更轻量。
下面直接上一些运用的规则:
1. 建立物理世界
Scene*HelloWorld::createScene()
{
auto scene =Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
auto layer =HelloWorld::create();
scene->addChild(layer);
return scene;
}
与普通的Scene创建方式不同的是,物理世界调用了Scene的createWithPhysics()方法,其他一样。
为了调试方便,可以给物理世界的刚体开启红边,这样就能直观的看出刚体了。
2.建立边界
Size visibleSize =Director::getInstance()->getVisibleSize();
auto body =PhysicsBody::createEdgeBox( visibleSize,PHYSICSBODY_MATERIAL_DEFAULT, 3);
auto edgeShape = Node::create();
edgeShape->setPhysicsBody( body);
edgeShape->setPosition( visibleSize.width /2, visibleSize.height /2);
addChild( edgeShape);
一般在Scene的init方法里创建物理世界的边界,方法是先调用PhysicsBody::createEdgeBox()创建一个边界刚体,然后再创建一个空的Node,将两个绑定在一起放在Scene中。
这个逻辑我觉得很奇怪,为什么不在第一步创造物理世界的时候指定边界尼?
3.接下来就是创造你需要的刚体了。
一般都是创建好刚体,然后和精灵绑定。为了更符合精灵的形状以便于做碰撞检测,我们可以使用一些物理编辑器。
auto sprite =Sprite::create("sprite.png");
auto box = PhysicsBody::createBox( sprite->getContentSize());
sprite->setPhysicsBody(box);
addChild(sprite);
这一段绑定刚体的代码还是很符合正常人逻辑的。我们也可以设置好多刚体的属性,例如重力等。
4.刚体的三个掩码,都是32位:
categoryBitmask: 定义了分类,只要and操作后非0就可以触发碰撞,默认全打开
contactTestBitmask:定义了是否触发回调函数,默认关掉
collisionBitmask:定义了发生碰撞后是否继续作用物理效果,如果不作用就会穿过去,作用就会摊开,默认全打开
这三个掩码用来定义刚体,方便做碰撞检测。比如说,你肯定不希望英雄和自己发出的子弹做出碰撞检测吧,那就用这三个掩码来定义你的英雄和子弹。
我在实测的时候发现没定义的情况下有问题:只给一个刚体定义了contactTestBitmask,其他没变。按道理来讲,这个时候两个刚体是能碰撞但是不会触发回调的。因为categoryBitmask全打开会碰撞,而一个contactTestBitmask是关掉的,也就是说这个关掉的contactTestBitmask和另一个定义的contactTestBitmask进行and操作后肯定还是0,所以不会触发回调。但是实际情况却是触发回调了。所以使用的时候建议定义下三个掩码。
auto contactListener=EventListenerPhysicsContact::create();
contactListener->onContactBegin =CC_CALLBACK_1(HelloWorld::callback,this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,this);
boolHelloWorld::callback(constPhysicsContact& contact)
{
log("%d == a", contact.getShapeA()->getBody()->getContactTestBitmask());
log("%d == b", contact.getShapeB()->getBody()->getContactTestBitmask());
return true;
}