閱讀336 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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的。

 

 

 

  1. 玩家用手指頭觸摸移動的白球我們建了一個Player的類,因為它是主動的,所以它的位置由觸摸點決定,但會影響b2Body位置。
  2. 紅球,我們建立一個Ball的類,因為它是被動的,所以它的位置由b2Body決定
  3. 紅色的6根線段是b2Body,它的Fixture的形狀是 b2EdgeShape,邊的意思,球會跟它碰撞
  4. 我們還建立了兩個球門,就是圖中兩端黑色矩形,因為與它相碰時,我們不需要改變球的b2Body屬性,但需要處理事件,所以isSensor設置為ture

理解上麵提到的4點,我們的遊戲就那麼回事了。你可以跟沒有使用Box2d的進行比較。

 

5.項目源碼下載(請用7z解壓)

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

 

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

6.遊戲動態圖

 

參考:

《Cocos2d-X by Example Beginner’s Guide》

最後更新:2017-04-03 12:56:09

  上一篇:go 開源數據庫框架greenDAO
  下一篇:go 語音蘭度短信