在cocos2dx v3版以后,官方对Box2d和chipmunk两个物理引擎进行了封装,对于我们开发人员而言,使用物理引擎的难度大大降低。
这里以构建一个小车为例,对封装的方法进行介绍。
如图所示,小车的组成很简单,一个长方形加两个圆形,贴图都使用了同一个图片,只做演示使用。
关键代码:
//添加小车方法,参数为触摸点坐标
void Sence1::addNewCarAtPosition(Vec2 p) {
//获取屏幕大小
Size visibleSize = Director::getInstance()->getVisibleSize();
//获取起点(在cocos2dx中,以屏幕的左下角为坐标原点)
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//创建一个精灵对象,作为长方形的车身
auto boxC = Sprite::create("whiteSprite.png");
//设置触摸点为精灵所在的坐标
boxC->setPosition(origin + p);
//创建物理Body
//以精灵的宽的两倍,精灵的高度为大小创建一个Box Body
auto boxCBody = PhysicsBody::createBox(Size(boxC->getContentSize().width*2,boxC->getContentSize().height));
//为精灵设置物理Body
boxC->setPhysicsBody(boxCBody);
//设置物理Body的类别掩码
boxCBody->setCategoryBitmask(0x01);
//设置物理body的碰撞掩码
boxCBody->setCollisionBitmask(0x01);
//设置物理Body不受重力影响
boxCBody->setGravityEnable(false);
//添加精灵到物理世界
addChild(boxC, 30, 102);
auto boxA = Sprite::create("whiteSprite.png");
//将精灵的位置设置在触摸点向左偏移boxC宽度的一半,向下偏移boxC高度的一半
boxA->setPosition(origin + p +Vec2(-boxC->getContentSize().width/2,-boxC->getContentSize().height/2));
auto boxABody = PhysicsBody::createCircle(boxA->getContentSize().width/2);
// boxABody->setAngularVelocity(2.0f);
boxABody->setCategoryBitmask(0x10);
boxABody->setCollisionBitmask(0x10);
boxA->setPhysicsBody(boxABody);
addChild(boxA, 10, 100);
auto boxB = Sprite::create("whiteSprite.png");
boxB->setPosition(origin + p + Vec2(boxC->getContentSize().width/2, -boxC->getContentSize().height/2));
auto boxBBody = PhysicsBody::createCircle(boxB->getContentSize().width/2);
boxBBody->setAngularVelocity(2.0f);
boxBBody->setCategoryBitmask(0x10);
boxBBody->setCollisionBitmask(0x10);
boxB->setPhysicsBody(boxBBody);
addChild(boxB, 20, 101);
auto world = this->getScene()->getPhysicsWorld();
//使用图钉关节将boxABody与boxCBody连接起来,坐标我认为是相对锚点的偏移
PhysicsJointPin* jointCA = PhysicsJointPin::construct(boxABody,
boxCBody, Vec2(0, 0),Vec2(-boxC->getContentSize().width/2-10,-boxC->getContentSize().height/2));
PhysicsJointPin* jointCB = PhysicsJointPin::construct(boxBBody,
boxCBody, Vec2(0, 0),Vec2(boxC->getContentSize().width/2+10,-boxC->getContentSize().height/2));
// PhysicsJointDistance* jointAB = PhysicsJointDistance::construct(boxABody,
// boxBBody, Vec2(0, 0), Vec2(0,0));
world->addJoint(jointCA);
world->addJoint(jointCB);
// world->addJoint(jointAB);
}