Box2D v2.1.0用戶手冊翻譯 - 第07章 物體(Bodies)

原文地址:http://blog.csdn.net/complex_ok/article/details/6723390


第07章 物體(Bodies)

7.1 關於

物體具有位置和速度。你可以將力(forces), 扭矩(torques),衝量(impulses)應用到物體上。 物體可以是靜態的(static), 運動但不受力的(kinematic), 和動態的(dynamic)。這是物體的類型定義:

b2_staticBody

static物體在模擬時不會運動,就好像它具有無窮大的質量。在Box2D內部,會將static物體的質量存儲爲零。static物體可以讓用戶手動移動,它速度爲零,另外也不會和其它static或kinematic物體相互碰撞。

b2_kinematicBody

kinematic物體在模擬時以一定速度運動, 但不受力的作用。它們可以讓用戶手動移動,但通常的做法是設置一定速度。kinematic物體的行爲表現就好像它具有無窮大的質量,Box2D將它的質量存儲爲零。kinematic物體並不會和其它static或kinematic物體相互碰撞。

b2_dynamicBody

dynamic物體被完全模擬。它們可以讓用戶手動移動,但通常它們都是受力的作用而運動。dynamic物體可以和其它所有類型的物體相互碰撞。dynamic物體的質量總是有限大的,非零的。如果你試圖將它的質量設置爲零,它會自動地將質量修改成一千克。

物體是fixtures的骨架,帶着fixture在世界中運動。Box2D中的物體總是剛體(rigid body)。也就是說,同一剛體上的兩個fixture,永遠不會相對移動。

fixture有可碰撞的幾何形狀和密度(density)。物體通常從它的fixture中獲得質量屬性。當物體構建之後,你也可以改寫它的質量屬性。這將在下面討論到。

通常你會保存所有你所創建物體的指針,這樣你就能查詢物體的位置,用於更新圖形實體的位置。另外在不需要它們的時候,你也可以使用指針去摧毀它們。

7.2 物體定義(Body Definition)

在創建物體之前你需要先創建物體定義(b2BodyDef)。物體定義含有初始化物體所需的數據。

Box2D會從物體定義中拷貝出數據, 並不會保存它的指針。這意味着你可以重複使用同一個物體定義去創建多個物體。

讓我們看一些物體定義的關鍵成員。

物體類型(Body Type)

本章開始已經說過,有三種物體類型: static, kinematic, 和dynamic。 你應該在創建時就確定好物體類型,因爲以後再修改的話,代價會很高。

bodyDef.type = b2_dynamicBody;

物體類型是一定要設置的。

位置和角度(Position and Angle)

物體定義爲你提供了一個在創建時初始化位置的機會。這比在world原點下創建物體後再移動到某個位置更高效。

注意

不要在原點創建物體後在移動它。如果你在原點上同時創建了幾個物體,性能會很差。

物體上主要有兩個讓人感興趣的點。第一個是物體的原點。fixture和關節都是相對於原點而依附到物體上面的。第二個是物體的質心。質心由形狀的質量分佈決定,或顯式地由b2MassData設置。Box2D內部許多計算都要使用物體的質心, 例如b2Body會存儲質心的線速度。

當你構造物體定義的時候,可能你並不知道質心在哪裏。你可以會指定物體的原點,也可以會以弧度指定物體的角度, 角度並不受質心位置的影響。如果隨後你改變了物體的質量屬性,那麼質心也會隨之移動,但是原點以及物體上的形狀和關節都不會改變。

bodyDef.position.Set(0.0f, 2.0f);// body的原點

bodyDef.angle = 0.25f * b2_pi;// 弧度制下body的角

阻尼(Damping)

阻尼用於減小物體在世界中的速度。阻尼跟摩擦有所不同,摩擦僅在物體有接觸的時候纔會發生。阻尼並不能取代摩擦,往往這兩個效果需要同時使用。

阻尼參數的範圍可以在0到無窮大之間, 0表示沒有阻尼,無窮大表示滿阻尼。通常來說,阻尼的值應 該在0到0.1之間。通常我不使用線性阻尼, 因爲它會使物體看起來有點漂浮。

bodyDef.linearDamping = 0.0f;

bodyDef.angularDamping = 0.01f;

阻尼類似穩定性與性能, 在值較小的時候阻尼效應幾乎不依賴於時間步, 值較大的時候阻尼效應將隨着時間步而變化。如果你使用固定的時間步(推薦)這就不是問題了。

休眠參數(Sleep Parameters)

休眠是什麼意思? 模擬物體的成本是高昂的,所以如果物體更少,那模擬的效果就能更好。當物體停止了運動時, 我們會希望停止模擬它。

當Box2D確定一個物體(或一組物體)已停止移動時,物體就會進入休眠狀態。休眠物體只消耗很小的 CPU開銷。如果一個醒着的物體接觸到了一個休眠中的物體,那麼休眠中的物體就會醒過來。當物體上的關節或觸點被摧毀的時候,它們同樣會醒過來。你也可以手動地喚醒物體。

通過物體定義,你可以指定一個物體是否可以休眠,或者創建一個休眠的物體。

bodyDef.allowSleep = true;

bodyDef.awake = true;

固定旋轉(Fixed Rotation)

你可能想一個剛體,比如某個角色,具有固定的旋轉角。這樣物體即使在負載下,也不會旋轉。 你可以設置fixedRotation來達到這目的:

bodyDef.fixedRotation = true;

固定旋轉標記使得轉動慣量被設置成零。

子彈(Bullets)

遊戲模擬通常以一定幀率(frame rate)產生一系列的圖片。這就是所謂的離散模擬。在離散模擬中,在一個時間步內剛體可能移動較大距離。如果一個物理引擎沒有處理好大幅度的運動,你就可能會看見一些物體錯誤地穿過了彼此。這被稱爲隧穿效應(tunneling)。

默認情況下,Box2D會通過連續碰撞檢測(CCD)來防止動態物體穿越靜態物體。這是通過掃描形狀從舊 位置到新位置的過程來完成的。引擎會查找掃描中的新碰撞,併爲這些碰撞計算碰撞時間 (TOI)。物體會先被移動到它們的第一個TOI,然後一直模擬到原時間步的結束。

一般情況下,dynamic物體之間不會應用CCD,這是爲了保持性能。在一些遊戲環境中你需要在動態物體上也使用CCD。比如,你可能想用一顆高速的子彈去射擊一塊動態的磚頭。沒有CCD,子彈就可能會隧穿磚頭。

在Box2D中,高速移動的物體可以標記成子彈(bullet)。子彈跟static或者dynamic物體之間都會執行CCD。你需要按照遊戲的設計來決定哪些物體是子彈。如果你決定一個物體應該按照子彈去處理,使用下面的設置。

bodyDef.bullet = true;

子彈標記隻影響dynamic物體。

Box2D執行連續碰撞檢測,所以子彈也有可能會錯過快速移動的物體。

活動狀態(Activation)

你可能希望創建一個物體並不參與碰撞和動態模擬。這狀態跟休眠有點類似,但並不會被其它物體喚醒,它上面的fixture也不會 被放到broad-phase中。也就是說,物體不會參於碰撞檢測,光線投射(ray casts)等等。

你可以創建一個非活動的物體,之後再激活它。

bodyDef.active = true;

關節也可以連接到非活動的物體。但這些關節並不會被模擬。你要小心,當激活物體時,它的關節不會被扭曲(distorted)。

用戶數據(User Data)

用戶數據是個void指針。它讓你將物體和你的應用程序關聯起來。你應該保持一致性,所有物體的用戶數據都指向相同的對象類型。

b2BodyDef bodyDef;

bodyDef.userData = &myActor;

7.3 物體工廠(Body Factory)

物體使用world類提供的工廠來創建和摧毀。這讓world可以通過一個高效的分配器來創建物體,並且把物體加入到world的數據結構中。

物體可以是dynamic或static的,這取決於質量屬性。兩種類型物體的創建和摧毀方法都是一樣的。

b2Body* dynamicBody =myWorld->CreateBody(&bodyDef);

... do stuff ...

myWorld->DestroyBody(dynamicBody);

dynamicBody = NULL;

注意

永遠不要使用new或malloc來創建物體, 否則世界不會知道這個物體的存在,並且物體也不會被適當地初始化。

static物體不會受其它物體的作用而移動。你可以手動地移動static物體,但你必須小心,不要擠壓到static物體之間的dynamic物體。另外,當你移動static物體的時候,摩擦不會正確工作。static物體不會和其它static或kinematic物體碰撞。在單個static物體上附加數個形狀, 要比多個static物體都只附加單個形狀,有更好的性能。在內部, Box2D會設置static物體的質量爲零。這使得大部分算法都不必把靜態物體當成特殊情況來看待。

Box2D並不保存物體定義的引用,也不保存其任何數據(除了用戶數據指針)。所以你可以創建臨時的 物體定義, 並重複利用它。

Box2D允許你通過刪除b2World對象來摧毀物體,它會爲你做所有的清理工作。然而, 你必須小心地將保存在遊戲引擎的body指針清零。

當你摧毀物體時,依附其上的fixture和joint都會自動被摧毀。瞭解這點,對你如何管理fixture和joint指針有重要意義。

7.4 使用物體(Using a Body)

在創建完一個物體之後,你可以對它進行許多操作。其中包括設置質量,訪問其位置和速度,施加力,以及轉換點和向量。

質量數據(Mass Data)

每個物體都有質量(標量), 質心(二維向量)和轉動慣性(標量)。對於static物體,它的質量和轉動慣性都是零。當物體設置成固定旋轉(fixed rotation),它的轉動慣性也是零。

通常情況下,當fixture添加到物體上時,物體的質量屬性會自動地確定。你也可以在運行時(run-time)調整物體的質量。你有特殊的遊戲方案,需要改變質量時,可以這樣做。

void SetMassData(const b2MassData* data);

直接設置物體的質量後,你可能希望再次使用fixture來指定質量。可以這樣做:

void ResetMassData();

要得到物體的質量數據,可以通過下面的函數:

float32 GetMass() const;

float32 GetInertia() const;

const b2Vec2& GetLocalCenter()const;

void GetMassData(b2MassData* data)const;

狀態信息(State Information)

物體的有多個方面狀態。你可以通過下面的函數高效地訪問狀態數據:

void SetType(b2BodyType type);

b2BodyType GetType();

 

void SetBullet(bool flag);

bool IsBullet() const;

 

void SetSleepingAllowed(bool flag);

bool IsSleepingAllowed() const;

 

void SetAwake(bool flag);

bool IsAwake() const;

 

void SetActive(bool flag);

bool IsActive() const;

 

void SetFixedRotation(bool flag);

bool IsFixedRotation() const;

位置和速度(Position and Velocity)

你可以訪問一個物體的位置和旋轉角, 這在你渲染相關遊戲角色時很常用。通常情況下,你都是使用Box2D來模擬運動,也可以設置位置, 但不怎麼常用。

bool SetTransform(const b2Vec2&position, float32 angle);

const b2Transform&GetTransform() const;

const b2Vec2& GetPosition()const;

float32 GetAngle() const;

你可以訪問本地座標系及世界座標下的質心。許多Box2D的內部模擬都使用質心。通常你不必訪問質心。取而代之, 你一般應該關心物體變換。比如,你有個正方形的物體。物體的原點可能在正方形的一個角點,而質心卻位於正方形的中心點。

const b2Vec2& GetWorldCenter()const;

const b2Vec2& GetLocalCenter()const;

你可以訪問線速度與角速度,線速度是對於質心所言的。所以質量屬性改變了,線速度有可能也會改變


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章