cocos2d-x 物理引擎
你的遊戲進展的很順利。遊戲中添加了精靈物件、遊戲機制,你努力編碼還是有回報的。你現在開始覺得:“嗯,這是一個能讓人玩的遊戲了”。當你意識到你的遊戲需要模擬現實世界的物理環境時,你該怎麼做呢?你會猜:應該會涉及到碰撞檢測、重力、彈力和摩擦力。沒錯,猜對了!這一章就來講物理引擎和如何使用物理引擎。讓我們來探討一下,我們什麼時候、什麼地點、為什麼會使用物理引擎吧。
物理引擎很可怕,我真的需要它麼?請告訴我不是這樣的!
別逃走啊,物理引擎其實也不是個藏在你床下準備把你嚇個半死的怪物。或許你的需求很簡單,簡單到並不需要使用物理引擎。或許節點物件、update()函式、Rect物件、containsPoint()函式或intersectsRect()函式這些就夠你用的了。例如:
1 2 3 4 5 6 7 8 9 10 |
void
update( float
dt)
{
auto
p = touch->getLocation();
auto
rect = this ->getBoundingBox();
if (rect.containsPoint(p))
{
//
do something, intersection
}
}
|
上面這套系統能滿足簡單的需求,但卻無法擴充套件。假如你有100個精靈,而所有的這些精靈都需要不斷地更新,以檢測與其他物件的重疊狀況,那該怎麼辦呢?用上面的系統,這也是可以實現的,但是會嚴重消耗CPU的使用率並影響幀速率。你的遊戲就沒辦法繼續玩下去了。物理引擎(PhysicsEngine)幫我們解決了這些問題,並且它是可擴充套件的,還也不會對CPU造成過大壓力。這或許看起來有點陌生,我們還是來看一個簡單的例子。之後,我們還是來看一個簡單的例子,力求將概念、術語以及實踐結合起來。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//
create a static PhysicsBody
auto
physicsBody = PhysicsBody::createBox(Size(65.0f , 81.0f ), PhysicsMaterial(0.1f, 1.0f, 0.0f));
physicsBody->setDynamic( false );
//
create a sprite
auto
sprite = Sprite::create( "whiteSprite.png" );
sprite->setPosition(Vec2(400,
400));
//
sprite will use physicsBody
sprite->setPhysicsBody(physicsBody);
//add
contact event listener
auto
contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin
= CC_CALLBACK_1(onContactBegin, this );
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,
this );
|
雖然上面這個例子已經很簡單了,但你可能還是覺得它複雜得有點嚇人?沒關係,讓我們來更仔細地分析一下它,我們會發現也沒那麼複雜的。程式碼中的建立步驟為:建立PhysicsBody物件。建立Sprite精靈。Sprite精靈物件應用PhysicsBody物件的屬性。建立了一個監聽器以響應onContactBegin事件。
一旦我們一步步地來分析,這些概念都變得容易理解了。理解下面這些術語和概念,會有利於你更好地瞭解物理引擎的所有細節:
物理引擎術語和概念
剛體
PhysicsBody物件包含了一個物件的物理屬性。這些屬性包括:質量、位置、自旋度、速度和衰減度。PhysicsBody物件是形狀的核心。當你把形狀和PhysicsBody關聯後,PhysicsBody物件才能具有形狀。
材質
材質描述了材料的以下屬性:
- 密度:它被用於計算母體的質量屬性。
- 摩擦:它被用於進行物體間的相對運動。
- 恢復係數:它被用於使物體反彈。恢復係數一般設為0到1之間。0說明不反彈,1說明完全反彈。
形狀
形狀描述了碰撞的幾何屬性。將形狀繫結到剛體,就定義了一個剛體的形狀。如果必要,你可以為一個剛體關聯無數的形狀,這是一種定義複雜形狀的方式。每個形狀都與一個PhysicsMaterial物件相關,並且擁有以下的屬性:type(種類), area(面積), mass(質量), moment(轉矩), offset(偏移量/重心)和tag(標籤)。可能你還對它們中的某些還感到陌生:
- type:描述了一系列的形狀,例如圓形,矩形,多邊形等。
- area:用於計算剛體的質量。密度和體積決定了剛體的質量。
- mass:剛體所含的物質的量,可以用兩種方式進行測量:物體在給定的力下獲得的加速度大小,或者在一個引力場中物體受到力的大小。
- moment:決定了獲得特定角加速度所需要的轉矩。
- offset:在剛體的當前座標中,相對於剛體的重心所偏移的量。
- tag:用以使開發者較容易地確定形狀。你大概還能記得把?你可以為所有的節點都分配一個標籤,以進行辨識和實現更容易的訪問。
我們這樣來描述不同的形狀:
- PhysicsShape:shapes(形狀)實現了PhysicsShape的基類。
- PhysicsShapeCircle:圓是實心的。你無法用圓(circle)形狀來實現空心圓。
- PhysicsShapePolygon:多邊形(Polygon)形狀是指實心的且外凸的多邊形。
- PhsicsShapeBox:矩形(Box)形狀是外凸的多邊形的一種。
- PhysicsShapeEdgeSegment:一種線段的形狀。
- PhysicsShapePolygon:空心多邊形。一種由多個線段構成的多邊形的邊緣。
- PhysicsShapeEdgeBox:空心矩形形狀。一種由四個線段組成的矩形的邊緣。
- PhysicsShapeEdgeChain鍊形形狀(chain shape)可以有效地把許多邊緣聯結起來。
連線/關節
連線(contacts)和關節(joint)物件描述了剛體相互關聯的方式。
World 世界
物理剛體被新增到一個叫世界(World)的容器裡,這也是它們被模擬的場所。將bodies,shapes,constraints這些物件新增到物理世界中,將整個物理世界作為一個整體進行更新。物理世界決定了所有這些部件在一起的互動方式。其中,用物理API實現的許多互動都是與PhysicsWorld這個物件有關的。
此處有許多需要記住的東西。請把這些術語記在身邊,待會用到的時候以便隨時查閱。
物理世界和物理剛體
物理世界
物理世界(PhysicsWorld)物件是進行物理模擬時的一個核心部件。物理世界(PhysicsWorld)與場景(Scene)緊密整合在一起。讓我們來看一個我們都會涉及到的例子吧。你住的房子裡有廚房嗎?你想這個問題的時候,就像是在想你的物理世界一樣!現在,你的世界裡擁有一些物理剛體(PhysicsBody)物件,就跟食物、刀具、電器這些東西一樣!在這個世界中,這些剛體相互作用。它們相互接觸,並且對相互的接觸做出反應。例如:用刀子切開食物,並把它放到電器中。刀子切到食物了嗎?可能切到了。也可能還沒有。還可能這個刀子根本就不適合做這個。
你可以用下面的方式建立一個包含有PhysicsWorld的Scene物件: