物理引擎box2d的學習心得

原文:http://passover.blog.51cto.com/2431658/804566

1 前言

     最近學習libgdx的時候暫時先沒看box2d那部分,昨天想做個物理效果看了一下那部分的封裝,發現沒點概念太難看懂了,還是乖乖的把box2d先系統的學習一遍。這個資料網上很多,最好的自然是官方的用戶手冊,還有熱心網友把翻譯成中文的了。還是老習慣,學完以後留點東西以備忘。

2 基礎知識

    以下內容對理解物理引擎非常重要,摘自用戶手冊,這部分主要是給自己做備忘,強烈建議讀者把《box2d中文手冊》研讀一遍。

2.1 必要知識

質量(mass),力(force),扭矩(torque)和衝量(impulses),這個不懂看看物理知識。

2.2 核心概念

形狀(shape)

2D幾何對象, 比如圓形(circle)或多邊形(polygon)。

剛體(rigid body)

十分堅硬的物質, 堅硬得像鑽石,它上面任意兩點之間的距離都保持不變。在後面的討論中,我們用物體(body)來代替剛體。(這就使得物體本身不會產生形變,那軟軟彈彈的效果應該都是動畫)

夾具(fixture)

fixture將形狀綁定到物體之上, 並有一定的材質屬性, 比如密度(density), 摩擦(friction)和恢復(restitution)。

(譯註:一個物體和另一物體碰撞, 碰撞後速度和碰撞前速度的比值會保持不變,這比值就叫恢復係數。)

約束(constraint)

約束是個物理連接, 用於消除物體的自由度。在2D中, 物體有3個自由度(水平,垂直,旋轉)。如果我們把一個物體釘在牆上(像鐘擺那樣), 那就把它約束到了牆上。這個時候,此物體就只能繞着釘子旋轉, 所以這個約束消除了它2個自由度。

(譯註:簡單的說, 需要用幾個參數來確定物體的空間狀態, 這個物體就有幾個自由度。在二維中,完全沒有約束的條件下, 我們要確定物體的狀態, 要有x座標, y座標, 旋轉角這三個參數, 所以自由度爲3。如果物體被釘在牆上, 只要有旋轉角,就可以完全確定物體的狀態,有了釘子這個約束,物體自由度就變成了1。)

接觸約束(contact constraint)

一種特殊的約束, 設計的目的是爲了防止剛體被穿透, 也用於模擬摩擦和恢復。接觸約束不用你來創建, 它們會自動被Box2D生成。

關節(joint)

關節就是種約束, 用於將兩個或多個body固定到一起。Box2D支持不同的關節類型:轉動(revolute),棱柱(prismatic),距離(distance)等。一些關節可以有限制(limits)和馬達(motors)。

關節限制(joint limit)

關節限制限定了一個關節的運動範圍。例如人類的胳膊肘只能在某一角度範圍內運動。

關節馬達(joint motor)

根據關節的自由度, 關節馬達可以驅動關節所連接的物體。例如, 你可以使用一個馬達來驅動一個肘的旋轉。

世界(world)

一個物理世界就是各種, 剛體(bodies), 夾具(fixtures), 約束(constraints)相互作用的集合。 Box2D支持創建多個世界, 但這通常沒有必要。

box2d的內存是自己管理的,他建立了一個內存池,以減少對內存的頻繁的申請和釋放。所以所有對象都要box2d幫你創建,也就是libgdx中的world。

2.3 模擬物理世界的相關算法

積分器(integrator)的數值算法:在離散的時間點上模擬連續的物理方程它與傳統的遊戲動畫循環一同運行。我們需要爲Box2D選取一個時間步。通常來說用於遊戲的物理引擎需要至少 60Hz 的速度,也就是 1/60 的時間步。你可以使用更大的時間步,但是你必須更加小心地爲你的世界調整定義。我們也不喜歡時間步變化得太大,所以不要把時間步關聯到幀頻(除非你真的必須這樣做)。直截了當地,這個就是時間步:

約束求解器(constraint solver):用於解決模擬中的所有約束,一次一個。單個的約束會被完美的求解,然而當我們求解一個約束的時候,我們就會稍微耽誤另一個。要得到良好的解,我們需要多次迭代所有約束。所以就有必要控制迭代計算的次數以防止無限循環,推薦迭代次數爲10能較好的模擬效果。

2.4 fixture中一些有意思的概念

密度(Density)

fixture的密度用來計算父物體的質量屬性。密度值可以爲零或者是整數。你所有的fixture都應該使用相似的密度,這樣做可以改善物體的穩定性。

當你添加一個fixture時,物體的質量會自動調整。

摩擦(Friction)

摩擦可以使對象逼真地沿其它對象滑動。Box2D支持靜摩擦和動摩擦,兩者都使用相同的參數。摩擦在Box2D中會被精確地模擬,摩擦力的強度與正交力(稱之爲庫侖摩擦)成正比。摩擦參數經常會設置在0到1之間, 也能夠是其它的非負數,0意味着沒有摩擦, 1會產生強摩擦。當計算兩個形狀之間的摩擦時,Box2D必須聯合兩個形狀的摩擦參數。

恢復(Restitution)

恢復可以使對象彈起。恢復的值通常設置在0到1之間。想象一個小球掉落到桌子上,值爲0表示着小球不會彈起, 這稱爲非彈性碰撞。值爲1表示小球的速度跟原來一樣,只是方向相反, 這稱爲完全彈性碰撞

傳感器(Sensors)

有時候遊戲邏輯需要判斷兩個fixture是否相交,但卻不應該有碰撞反應。這可以通過傳感器(sensor)來完成。傳感器也是個fixture,但只會偵測碰撞而不產生其它反應。

2.5 body中一些有意思的概念 

阻尼(Damping)

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

休眠參數(Sleep Parameters)

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

固定旋轉(Fixed Rotation)

你可能想一個剛體,比如某個角色,具有固定的旋轉角。這樣物體即使在負載下,也不會旋轉。

子彈(Bullets)

遊戲模擬通常以一定幀率(frame rate)產生一系列的圖片。這就是所謂的離散模擬。在離散模擬中,在一個時間步內剛體可能移動較大距離。默認情況下,Box2D會通過連續碰撞檢測(CCD)來防止動態物體穿越靜態物體。一般情況下,dynamic物體之間不會應用CCD,這是爲了保持性能。

3 libgdx中的box2d

3.1 libgdx的優勢

    有個不得不說的優點,box2d用戶手冊裏面有相當篇幅在說如何管理內存和引用,這個對於java程序而言真的是再不用多考慮了。

    另外,jbox2d版本在性能方面有些問題,但牛逼的是libgdx是通過jni調用的box2d的c++版本。

3.2 如何將actor和body聯繫起來

    這個問題真的有點讓我困擾,我們期望的效果自然是actor能帶上物理特性,但遺憾的是不能直接這麼指定。這就造成了一個是在物理世界移動的物理,一個是動畫世界的圖片,兩者卻沒有了直接關係。所以這就需要將這兩個東西聯繫在一起,然後同步兩者的爲止。

    目前覺得比較好的方式就是在上層再做一次封裝,將actor和相應的body綁定在一起,每幀都先讓body去計算位移,然後再調整actor的位置。

4 總結

    物理引擎真的很強大,能通過對物理定義就變成一個可以按物理邏輯運行的效果,但在這之前對於box2d的概念必須有所瞭解。在libgdx中調用box2d還是比較方便的,就是可惜還要自己去綁定。Loving libgdx ~~

 

參考資料:
1. box2d v2.0.1中文手冊:
http://wenku.baidu.com/view/153e4421af45b307e8719753.html
2. box2d與精靈(sprite)的同步:http://blog.u250.info/?p=121002
3. 使用box2d的注意事項:http://kongweile.iteye.com/blog/978718
4. box2d v2.1.0中文手冊(有譯註,也新一些,推薦):http://blog.csdn.net/complex_ok/article/details/6706982


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