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的。
- 玩家用手指頭觸摸移動的白球我們建了一個Player的類,因為它是主動的,所以它的位置由觸摸點決定,但會影響b2Body位置。
- 紅球,我們建立一個Ball的類,因為它是被動的,所以它的位置由b2Body決定
- 紅色的6根線段是b2Body,它的Fixture的形狀是 b2EdgeShape,邊的意思,球會跟它碰撞
- 我們還建立了兩個球門,就是圖中兩端黑色矩形,因為與它相碰時,我們不需要改變球的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