cocos2d-x Box2d 入门例子

1.效果图(动态的gif见底部):

 

 

还记得这篇文章吗?cocos2d-x Touch 事件应用的一个例子 球跟球之间的碰撞,球跟壁的碰撞使用了简单的向量。球最终停止下来也是因为向量不断地变小。这次我们要改用物理引擎Box2d来让球碰撞!先下载这个项目,打开Release.win32/Air Hockey.win32.exe先来个试玩吧。

 

2.Box2d如何在cocos2d-x中使用简单介绍

 

Box2d引擎中核心的是一个叫b2World的东西,它会创建一些b2Body的物体,当然这些物体的形状有多边形,圆形等,属性也各异:比如密度有大有小。创建完后,在游戏的一直调用的update函数里加上b2World->Step(),那些b2Body的物体就会根据你设置的属性有物理反应了,但是他们没有纹理,但他们有position,rotation等属性,我们把这属性应用到我们Cocos2d-x中的Sprite属性时,Sprite就像真的物体一样动起来了。

 

2.1 b2World设置

 

Box2d中使用的是一个叫做b2Vec2的向量。

?
1
2
3
4
5
6
7
8
9
10
11
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);

 

2.2 b2Body的创建

 

我们主要有3种类型的b2Body, dynamic, static, 和 kinematic,根据名字就知道他们的用途。

b2Body创建需要一个叫b2BodyDef的结构体作为参数,b2BodyDef有一些属性比如type, position,velocity,angle,等。

b2Body还需要创建Fixture,需要一个b2FixtureDef的结构体,它也有一些属性跟这物体相关的,比如:长宽高,半径,还有density,elasticity,friction等属性。下面是一个创建球的例子。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);

读者可以查看我们项目中Ball.cpp中的initBall,Goal.cpp中的initGoal,细细体会。

3. b2Sprite 类

 

我们建立了一个b2Sprite类它继承了CCSprite,有一个b2Body的属性,所以它拥有CCSprite和b2Body两个类的属性的相加。这不是普通的CCSprite,因为它有b2Body的属性,想象下,CCSprite是负责处理一个精灵的外表,而它的内心,比如位置等方面是由物理引擎来改变的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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的。

 

 

cocos2d-x Box2d 入门例子_第1张图片

 

  1. 玩家用手指头触摸移动的白球我们建了一个Player的类,因为它是主动的,所以它的位置由触摸点决定,但会影响b2Body位置。
  2. 红球,我们建立一个Ball的类,因为它是被动的,所以它的位置由b2Body决定
  3. 红色的6根线段是b2Body,它的Fixture的形状是 b2EdgeShape,边的意思,球会跟它碰撞
  4. 我们还建立了两个球门,就是图中两端黑色矩形,因为与它相碰时,我们不需要改变球的b2Body属性,但需要处理事件,所以isSensor设置为ture

理解上面提到的4点,我们的游戏就那么回事了。你可以跟没有使用Box2d的进行比较。

 

5.项目源码下载(请用7z解压)

 http://www.waitingfy.com/?attachment_id=700

 

http://www.waitingfy.com/?p=696

6.游戏动态图

 

cocos2d-x Box2d 入门例子_第2张图片

参考:

《Cocos2d-X by Example Beginner’s Guide》

你可能感兴趣的:(游戏,cocos2d-x,box2D)