还记得这篇文章吗?cocos2d-x Touch 事件应用的一个例子 球跟球之间的碰撞,球跟壁的碰撞使用了简单的向量。球最终停止下来也是因为向量不断地变小。这次我们要改用物理引擎Box2d来让球碰撞!先下载这个项目,打开Release.win32/Air Hockey.win32.exe先来个试玩吧。
Box2d引擎中核心的是一个叫b2World的东西,它会创建一些b2Body的物体,当然这些物体的形状有多边形,圆形等,属性也各异:比如密度有大有小。创建完后,在游戏的一直调用的update函数里加上b2World->Step(),那些b2Body的物体就会根据你设置的属性有物理反应了,但是他们没有纹理,但他们有position,rotation等属性,我们把这属性应用到我们Cocos2d-x中的Sprite属性时,Sprite就像真的物体一样动起来了。
b2World *_world;//定义一个b2World指针变量,它将设置一些属性,然后一些 //物体比如圆形的方形的都将由它创建 b2Vec2 gravity; gravity.Set(0.0f, 0.0f);//我们是在一个平面上,所以只需要将重力加速度设置为0 _world = new b2World(gravity); _world->SetAllowSleeping(true); _world->SetContinuousPhysics(true); _collisionListener = new CollisionListener();//b2ContactListener,这里可以自定义处理物体碰撞发生的事情 //比如球碰到球门,我们希望重置游戏。 _world->SetContactListener(_collisionListener);
我们主要有3种类型的b2Body, dynamic, static, 和 kinematic,根据名字就知道他们的用途。
b2Body创建需要一个叫b2BodyDef的结构体作为参数,b2BodyDef有一些属性比如type, position,velocity,angle,等。
b2Body还需要创建Fixture,需要一个b2FixtureDef的结构体,它也有一些属性跟这物体相关的,比如:长宽高,半径,还有density,elasticity,friction等属性。下面是一个创建球的例子。
b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody;//设置类型 b2Body *body = world->CreateBody(&bodyDef); b2CircleShape circle;//创建一个圆形 circle.m_radius = 20.0 / PTM_RATIO;//设置半径 //定义fixture b2FixtureDef fixtureDef; fixtureDef.shape = &circle; fixtureDef.density = 1; fixtureDef.restitution = 0.7; fixtureDef.friction = 0.4;//摩擦力 body->CreateFixture(&fixtureDef);
class b2Sprite : public CCSprite{ public: b2Sprite(GameLayer *game, int type); CC_SYNTHESIZE(b2Body*, _body, Body); CC_SYNTHESIZE(GameLayer*, _game, Game); CC_SYNTHESIZE(int, _type, Type); virtual void setSpritePosition(CCPoint position); virtual void update(float dt); virtual void hide(void); virtual void reset(void); virtual float mag(); }; //两个核心方法 //当你为一个精灵设置位置和旋转角度的时候,会同样改变它的b2Body的位置和旋转角度 void b2Sprite::setSpritePosition(CCPoint position){ setPosition(position); if(_body){ _body->SetTransform(b2Vec2( position.x / PTM_RATIO, position.y / PTM_RATIO), _body->GetAngle()); } } //当精灵的b2Body根据碰撞发生位置上的偏移时,会改变它的精灵的位置和旋转角度 void b2Sprite::update(float dt){ if(_body && isVisible()){ setPositionX(_body->GetPosition().x * PTM_RATIO); setPositionY(_body->GetPosition().y * PTM_RATIO); setRotation(CC_RADIANS_TO_DEGREES(-1 * _body->GetAngle())); } }
理解上面提到的4点,我们的游戏就那么回事了。你可以跟没有使用Box2d的进行比较。
http://www.waitingfy.com/?attachment_id=700
http://www.waitingfy.com/?p=696
参考:
《Cocos2d-X by Example Beginner’s Guide》