Cocos2d-x 3.x物理引擎概述(1)

引文:http://blog.csdn.net/z104207/article/details/44591197app


下一篇框架


物理引擎很可怕,我真的須要它麼?請告訴我不是這樣的!
dom

別逃走啊,物理引擎其實也不是個藏在你牀下準備把你嚇個半死的怪物。或許你的需求很簡單,簡單到並不須要使用物理引擎。或許節點對象、update()函數、Rect對象、containsPoint()函數或intersectsRect()函數這些就夠你用的了。例如:ide

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事件。this

一旦咱們一步步地來分析,這些概念都變得容易理解了。理解下面這些術語和概念,會有利於你更好地瞭解物理引擎的全部細節:spa

物理引擎術語和概念

剛體

PhysicsBody對象包含了一個對象的物理屬性。這些屬性包括:質量、位置、自旋度、速度和衰減度。PhysicsBody對象是形狀的核心。當你把形狀和PhysicsBody關聯後,PhysicsBody對象才能具備形狀。.net

材質

材質描述了材料的如下屬性:code

  • 密度:它被用於計算母體的質量屬性。orm

  • 摩擦:它被用於進行物體間的相對運動。

  • 恢復係數:它被用於使物體反彈。恢復係數通常設爲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對象:

1

auto scene = Scene::createWithPhysics();

每個物理世界(PhysicsWorld)都具備與之相關的屬性:

-重力(gravity):全局重力,應用於整個物理世界。默認值爲Vec2(0.0f,-98.0f)。 -速度(speed):設定了物理世界的速度。這裏,速度指的是這個模擬世界運動的一種比率。默認值爲1.0。 -刷新率:設定了物理世界的刷新率,這裏刷新率指的是EngineUpdateTimes/PhysicsWorldUpdateTimes的比值。 -子步(substeps):設定了物理世界中每次刷新的子步數量。

刷新物理世界的過程也被稱爲步進(stepping)。按照默認設置,物理世界會不停地進行自動刷新。這被稱爲「自動步進(auto stepping)」,它會自動地進行。你能夠經過設定PhysicsWorld::setAutoStep(false)禁用一個物理世界的auto step,而後經過設定PhysicsWorld::step(time)來手動刷新PhysicsWorld。substeps使用比單一框架更加精確的時間增量來刷新物理世界。使用它,咱們能夠實現更加細緻地實現對步進過程的控制,包括更加流暢的運動。

物理剛體

物理剛體(PhyicsBody)對象具備位置(position)和速度(velocity)兩個屬性。你能夠在PhysicsBody上應用forces、movement、damping和impulses。物理剛體能夠是靜態的,也能夠是動態的。靜態的剛體在模擬世界中不會移動,看起來就像它擁有無限大的質量同樣。動態的剛體則是一種徹底仿真的模擬。它能夠被用戶手動移動,但更常見的是它們受到力的做用而移動。動態剛體能夠與全部的剛體類型發生碰撞。Cocos2d-x提供了Node::setPhysicsbody()來將物理剛體與一個節點對象關聯在一塊兒。

讓咱們來建立一個靜態的物理剛體對象和5個動態的物理剛體對象,而且把它們都設爲矩形:

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
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(s_centre);
addChild(sprite);
 
//apply physicsBody to the sprite
sprite->setPhysicsBody(physicsBody);
 
//add five dynamic bodies
for ( int i = 0; i < 5; ++i)
{
     physicsBody = PhysicsBody::createBox(Size(65.0f, 81.0f),
     PhysicsMaterial(0.1f, 1.0f, 0.0f));
 
     //set the body isn't affected by the physics world's gravitational force
     physicsBody->setGravityEnable( false );
 
     //set initial velocity of physicsBody
     physicsBody->setVelocity(Vec2(cocos2d::random(-500,500),
     cocos2d::random(-500,500)));
     physicsBody->setTag(DRAG_BODYS_TAG);
 
     sprite = Sprite::create( "blueSprite.png" );
     sprite->setPosition(Vec2(s_centre.x + cocos2d::random(-300,300),
     s_centre.y + cocos2d::random(-300,300)));
     sprite->setPhysicsBody(physicsBody);
 
     addChild(sprite);
}

結果是,5個動態的物理剛體對象圍繞在一個靜態的物理剛體對象周圍不停地發生碰撞。 1.gif

下一篇

相關文章
相關標籤/搜索