(转载)BOX2D V2.3.0 用户手册中文版(第2章)-Hello Box2D
(轉載)BOX2D V2.3.0 用戶手冊中文版(第2章)-Hello Box2D
Chapter 2 Hello Box2D
Box2D的發(fā)布包中有個Hello World程序。程序創(chuàng)建了一個大大的地面盒(ground box)和一個小小的動態(tài)盒(dynamic box)。代碼沒有涉及到圖形界面,你只能在控制臺中看到隨時間變化的盒子位置的文字輸出。
這是個很好的例子, 展示了怎么學習和使用Box2D。
2.1 創(chuàng)建世界
每個Box2D程序開始時都會創(chuàng)建一個b2World對象。b2World是個物理樞紐(physics hub),用于管理內(nèi)存、對象和模擬。你可以在棧, 堆或數(shù)據(jù)區(qū)中創(chuàng)建出world。
創(chuàng)建Box2D的world很簡單。首先,我們定義重力矢量。
現(xiàn)在可以創(chuàng)建world對象了。注意,我們是在棧中創(chuàng)建world, 所以world不能離開它的作用域。
b2World world(gravity);現(xiàn)在我們已經(jīng)有了自己的物理世界,開始向里面加東西了。
2.2 創(chuàng)建地面盒
body用以下步驟來創(chuàng)建:
1. 用位置(position), 阻尼(damping)等來定義body。
2. 用world對象來創(chuàng)建body。
3. 用形狀(shape), 摩擦(friction), 密度(density)等來定義fixture。
4. 在body上來創(chuàng)建fixture。
第一步,創(chuàng)建ground body。
為此我們需要一個body定義。在定義中,我們指定ground body的初始位置。
b2BodyDef groundBodyDef; groundBodyDef.position.Set(0.0f, -10.0f);第二步,將body定義傳給world對象,用以創(chuàng)建ground body。
world對象并不保留body定義的引用。body默認是靜態(tài)的。靜態(tài)物體和其它靜態(tài)物體之間并沒有碰撞,它們是固定的。
b2Body* groundBody = world.CreateBody(&groundBodyDef);第三步,創(chuàng)建地面多邊形。
我們用簡便函數(shù)SetAsBox使得地面多邊形構成一個盒子形狀,盒子的中心點就是父body的原點。
b2PolygonShape groundBox; groundBox.SetAsBox(50.0f, 10.0f);SetAsBox函數(shù)接收半個寬度和半個高度作為參數(shù)。因此在這種情況下,地面盒就是100個單位寬(x軸),20個單位高(y軸)。Box2D已被調(diào)諧 到使用米,千克和秒做單位。你可以認為長度單位就是米。當物體的大小跟真實世界一樣時,Box2D通常工作良好。例如,一個桶約1米高。由于浮點算法的局 限性,使用Box2D模擬冰川或沙塵的運動并不是一個好主意。
第四步,我們創(chuàng)建shape fixture,以完成ground body。
在這步中,我們有個簡便方法。我們并不需要修改fixture默認的材質(zhì)屬性,可以直接將形狀傳給body而不需要創(chuàng)建fixture的定義。隨后的教程中,我們將會看到如何使用fixture定義來定制材質(zhì)屬性。第二個參數(shù)是形狀密度,單位是千克/平方米。靜態(tài)物體的質(zhì)量定義為0,因此密度對它們是沒有用的。
groundBody->CreateFixture(&groundBox, 0.0f);Box2D并不保存shape的引用。它把數(shù)據(jù)復制到一個新的b2Shape對象中。
注意
每個fixture都必須有一個父body,即使fixture是靜態(tài)的。然而,你可以把所有的靜態(tài)fixture都依附在單個靜態(tài)body之上。
當你使用fixture 向body添加shape的時候,shape的坐標對于body來說就變成本地的了。因此當body移動的時候,shape也一起移動。fixture的世界變換繼承自它的父body。fixture沒有獨立于body的變換。所以我們不需要移動body上的shape。不支持移動或修改body上的shape。原因很簡單:形狀發(fā)生改變的物體不是剛體,而Box2D只是個剛體引擎。Box2D所做的很多假設都是基于剛體模型的。如果這一條被改變的話,很多事情都會出錯。
2.3 創(chuàng)建動態(tài)物體
現(xiàn)在我們已經(jīng)有了一個地面body,我們可以使用同樣的方法來創(chuàng)建一個動態(tài)body。除尺寸之外的主要區(qū)別是,我們必須為動態(tài)body設置質(zhì)量屬性。
首先我們用CreateBody創(chuàng)建body。默認情況下,body是靜態(tài)的,所以在構造時候應該設置b2BodyType,使得body成為動態(tài)的。
注意
如果你想讓body受力的影響而運動, 你必須將body的類型設為b2_dynamicBody。
然后,我們創(chuàng)建一個多邊形shape, 并將它附加到fixture定義上。我們先創(chuàng)建一個box shape:
b2PolygonShape dynamicBox; dynamicBox.SetAsBox(1.0f, 1.0f);接下來,我們使用box創(chuàng)建一個fixture定義。注意, 我們把密度值設置為1,而密度值默認是0。并且,shape的摩擦系數(shù)設置為0.3。
b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; fixtureDef.density = 1.0f; fixtureDef.friction = 0.3f;注意
一個動態(tài)body至少有一個密度不為0的fixture。否則會出現(xiàn)一些奇怪的行為。
使用fixture定義,我們現(xiàn)在就可以創(chuàng)建fixture。這會自動更新body的質(zhì)量。要是你喜歡,你可以為body添加許多不同的fixture。每個fixture都會增加物體的總質(zhì)量。
body->CreateFixture(&fixtureDef);這就是初始化過程。現(xiàn)在我們已經(jīng)做好準備,可以開始模擬了。
2.4 模擬(Box2D的)世界
我們已經(jīng)初始化了地面box和一個動態(tài)box。該讓牛頓來接手了。我們只有少數(shù)幾個問題需要考慮。
Box2D使用了一種名叫積分器(integrator)的數(shù)值算法。 積分器在離散的時間點上模擬物理方程。 它與傳統(tǒng)的游戲動畫循環(huán)一同運行。我們需要為Box2D選取一個時間步(time step)。通常來說用于游戲的物理引擎需要至少 60Hz 的速度,也就是 1/60 秒的時間步。你可以使用更大的時間步,但是你必須更加小心地為你的世界調(diào)整定義。我們也不喜歡時間步變化得太大,一個變化的時間步會導致變化的結果,這會給調(diào)試帶來困難。所以不要把時間步關聯(lián)到幀頻(除非你真的必須這樣做)。直截了當?shù)?這個就是時間步。
除積分器外,Box2D代碼還使用了約束求解器(constraint solver)。約束求解器用于解決模擬中的所有約束,一次一個。單個的約束會被完美的求解,然而當我們求解一個約束的時候,我們就會稍微干擾另一個約束。要得到良好的解,我們需要多次迭代所有約束。
約束求解有兩個階段:速度階段和位置階段。在速度階段,求解器會計算必要的沖量,使得物體正確運動。而在位置階段,求解器會調(diào)整物體的位置,減少物體之間的重疊和關節(jié)的脫節(jié)。每個階段都有自己的迭代計數(shù)。此外,如果誤差已足夠小的話,位置階段的迭代可能會提前退出。
Box2D建議的迭代次數(shù),對于速度是8次,對于位置是3次。你可以按自己的喜好去調(diào)整這個數(shù)字,但要記得它是性能與精度之間的折中。更少的迭代會增加性能但降低精度,同樣地,更多的迭代會降低性能但能提高模擬的質(zhì)量。對于這個簡單示例,我們不需要很多的迭代。這里是我們選擇的迭代次數(shù)。
注意
時間步和迭代數(shù)是完全無關的。一個迭代并不是一個子步。一次迭代就是在時間步之中的單次遍歷所有約束,你可以在單個時間步內(nèi)多次遍歷約束。
現(xiàn)在我們可以開始模擬循環(huán)了,在你的游戲中,模擬循環(huán)和游戲循環(huán)可以合并起來。每次游戲循環(huán)你都應該調(diào)用b2World::Step,通常調(diào)用一次就夠了,這取決于幀頻以及物理時間步。
這個Hello World程序設計得非常簡單,它沒有圖形輸出。代碼會打印出動態(tài)body的位置以及旋轉角。這就是模擬 1 秒鐘內(nèi) 60 個時間步的循環(huán)。
輸出展示了box下降并降落到地面的情況。你的輸出看起來應當是這樣的:
0.00 4.00 0.00
0.00 3.99 0.00
0.00 3.98 0.00
…
0.00 1.25 0.00
0.00 1.13 0.00
0.00 1.01 0.00
2.5 清理
當world對象超出它的作用域,或通過指針將其 delete 時,分配給body、 fixture和 joint使用的內(nèi)存都會被釋放。這能提升性能,并使你的生活變得更簡單。然而,你應該將body、fixture或joint的指針都清零,因為它們已經(jīng)無效了。
2.6 The Testbed
一旦你征服了 HelloWorld 例子,你應該開始看 Box2D 的 testbed 了。testbed 是個單元測試框架,也是個演示環(huán)境,這是它的一些特點:
? 可移動和縮放的攝像機。
? 可用鼠標選中依附在動態(tài)物體上的形狀。
? 可擴展的測試集。
? 通過圖形界面選擇測試,調(diào)整參數(shù),以及設置調(diào)試繪圖。
? 暫停和單步模擬。
? 文字渲染。
在 testbed 中有許多 Box2D 的測試用例,以及框架本身的實例。我鼓勵你通過研究和修改它來學習 Box2D。
注意
testbed 是使用 freeglut 和 GLUI 寫成的,testbed 本身并不是 Box2D 庫的一部分。Box2D本身并不知道如何渲染。就像 HelloWorld 例子一樣,使用 Box2D 并不一定需要渲染。
總結
以上是生活随笔為你收集整理的(转载)BOX2D V2.3.0 用户手册中文版(第2章)-Hello Box2D的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ps 究竟是 aux 还是 ef
- 下一篇: 企业邮箱价格多少钱?邮箱购买价格多少钱?