- 精通Cocos2d-x游戲開發(進階卷)
- 王永寶
- 1249字
- 2020-11-28 22:37:06
9.2 工作流程
這里直接從Box2d自帶的HelloWorld示例開始,從Box2d官網下載的源碼包中可以找到這個例子,這是一個沒有圖形顯示的HelloWorld,正因為如此,呈現的內容更加精簡,后面的內容會介紹怎樣把Box2d的模擬效果顯示在Cocos2d-x上面,現在先把渲染拋到腦后吧。首先需要了解一下最純粹的Box2d。
Box2d的運行流程大致如圖9-1所示,首先是初始化Box2d,然后可以執行各種操作,如創建對象,操作對象、在循環中更新物理世界,Box2d會自動執行碰撞處理,并觸發碰撞監聽。需要注意的是,創建對象等操作不能在碰撞監聽回調中執行。

圖9-1 運作流程
Box2d的物理模擬全部發生在b2World這個類中,其表示整個物理世界,使用Box2d的第一步就是要把b2World創建出來,構造函數很簡單,只有一個參數,表示這個世界的重力加速度,地球的重力加速度是-9.8f,一般可以取近似值-10.0f(月球上的重力為地球的1/6大約為1.63f)。Box2d用b2Vec2來描述一個向量,重力也是一個向量,其結構等于一個Vec2,下面這段代碼創建了一個世界。
b2Vec2 gravity(0.0f, -9.8f); b2World world(gravity);
有了世界之后,需要在世界里面添加各種各樣的對象,這些對象不需要并且不允許使用new來創建,應該直接調用World的Create系列函數,由World來創建。
Box2d中使用了SOA(小對象分配器)來快速有效地使用內存(能夠高效地創建大量50~300字節大小的對象), Box2d每創建一個對象,都需要先填充一個對象的描述結構(這點和PhysX非常相似,這里使用一個b2BodyDef結構來填充描述。
b2BodyDef groundBodyDef; groundBodyDef.position.Set(0.0f, -10.0f); b2Body* groundBody = world.CreateBody(&groundBodyDef);
有了一個b2Body對象之后,還需要描述這個對象的形狀,Box2d提供一個b2PolygonShape對象來描述一個多邊形,調用它的SetAsBox()函數傳入寬和高可以得到一個四邊形,調用它的Set()函數傳入一個頂點數組,可以得到一個N邊形,把這個形狀直接設置到b2Body對象中。
//創建一個寬為50.0f,高為10.0f的四邊形,并設置到groundBody b2PolygonShape groundBox; groundBox.SetAsBox(50.0f, 10.0f); groundBody->CreateFixture(&groundBox, 0.0f);
上面設置了地板的形狀,它的質量為0,默認是一個靜態的物體,靜態的物理在物理世界中不會移動,但在游戲中,還需要創建一些動態的物體。要創建動態剛體的話,需要更多的設置,首先需要設置b2BodyDef的type,默認為b2_staticBody,動態物體需要將它設置為b2_dynamicBody。動態物體的形狀描述也需要更多的內容,如質量、摩擦力……Box2d提供b2FixtureDef結構體來描述這些內容。
//定義動態Body并創建 b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(0.0f, 4.0f); b2Body* body = world.CreateBody(&bodyDef); //定義另外一個四邊形 b2PolygonShape dynamicBox; dynamicBox.SetAsBox(1.0f, 1.0f); //定義動態Body的配置 b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; //動態對象的密度不為0 fixtureDef.density = 1.0f; //設置摩擦力 fixtureDef.friction = 0.3f; //將形狀配置到Body body->CreateFixture(&fixtureDef);
初始完一個World以及相關的對象之后,需要讓整個世界動起來,這需要調用World對象的Step()方法,其需要幾個參數,第一個是從上一次調用到現在的時間間隔,這個參數可以直接使用Cocos2d-x在Update()函數中傳入的參數。一般情況下,在每一幀的Update()調用一次Step。Box2d當運行比較復雜的運算的時候,需要一定的迭代次數來保證模擬的精度,Step要求傳入兩個迭代次數,即需要傳入速度迭代數和位置迭代數,Box2d給出的默認值是8和3,如果對精度要求比較高,可以適當地增加這兩個值,該值越大,相應地性能越低。velocityIterations表示速度約束的遍歷次數,positionIterations表示位置約束的遍歷次數,可以根據游戲的具體情況來設置這兩個值。
world.Step(dt, velocityIterations, positionIterations);
在游戲更新的過程中,會不斷地創建新的對象到世界中,也會不斷地刪除一些舊的對象,不管怎樣,在World被析構的時候,這個世界的一切,都會從內存中被釋放。