1. 程式人生 > >Box2D C++ 教程-力和衝量

Box2D C++ 教程-力和衝量

  • 力和衝量(Forces and impulses)

讓物體移動,需要對其施加力或者衝量。可以通過時間的不斷積累對物體施加力的作用來改變物體的運動,然而衝量作用於物體則會立刻改變物體的速度。舉個例子,想象一下現在你的車壞了,你想推車,可以選擇驅動另外一輛車緩慢開向這輛壞了的車,當兩輛車的保險槓接觸之後,繼續對這輛車施加推力,然後通過時間不斷的積累慢慢的讓其移動。或者也可以用衝量,驅動一輛完好的車全速駛向這輛壞了車。具體使用哪種方法取決於你。

也可以通過簡單設定物體的位置來瞬間‘曲速(參見Warp drive)’物體。在遊戲中你可能想有一個瞬移的特性,但是你要知道在真正的物理世界當中並不存在這樣一種特性!Box2D的全部側重點是讓所模擬的物體看起來更真實,基於這一點考慮我會建議你儘量使用力和衝量來移動物體。大多數時候這麼做看起來貌似過於嚴謹,但是在真實的世界裡所有事情的發生都是通過力和衝量的,除非你就是想建立一個不是真實世界裡的特性(瞬移,等等),要三思!而且如果你這麼做下去的話,可能會給你帶來更多的麻煩。

角運動也可以通過力和衝量來控制,效果就像上面提到的緩慢/瞬間的線性版本一樣。角力矩也稱為扭矩(torque)。可以想象成轉動強度,就像你擰瓶蓋兒一樣-瓶蓋不會跑出去,而且你可以持續對瓶蓋施加作用力(扭矩,torque)。

本次話題,我們將建立三個物體,使用上面提到的兩種力來分別作用於它們平移或扭曲(twist)它們。讓我們設定一個和定製器(fixtures)話題中類似的場景,不同的是所有物體的形狀都一樣。

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
//class member variable to keep track of three bodies
b2Body* bodies[3]; FooTest() { //body definition b2BodyDef myBodyDef; myBodyDef.type = b2_dynamicBody; //shape definition b2PolygonShape polygonShape; polygonShape.SetAsBox(1, 1); //a 2x2 rectangle //fixture definition b2FixtureDef myFixtureDef; myFixtureDef.shape = &
polygonShape;
myFixtureDef.density = 1; //create identical bodies in different positions for (int i = 0; i < 3; i++) { myBodyDef.position.Set(-10+i*10, 20); bodies[i] = m_world->CreateBody(&myBodyDef); bodies[i]->CreateFixture(&myFixtureDef); } //a static floor to drop things on myBodyDef.type = b2_staticBody; myBodyDef.position.Set(0, 0); polygonShape.SetAsEdge( b2Vec2(-15,0), b2Vec2(15,0) ); m_world->CreateBody(&myBodyDef)->CreateFixture(&myFixtureDef); }

pic

  • 線性運動(Linear movement)

我們需要一個不使用滑鼠就能影響物體運動的方法。現在是考驗testbed框架中鍵盤輸入特性的時候了。覆蓋Test類中Keyboard方法,為每個物體定義不同的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Keyboard(unsigned char key)
{
    switch (key)
        {
            case 'q':
                //apply gradual force upwards
                bodies[0]->ApplyForce( b2Vec2(0,50), bodies[0]->GetWorldCenter() );
                break;
            case 'w':
                //apply immediate force upwards
                bodies[1]->ApplyLinearImpulse( b2Vec2(0,50), bodies[1]->GetWorldCenter() );
                break;
            case 'e':
                //teleport or 'warp' to new location
                bodies[2]->SetTransform( b2Vec2(10,20), 0 );
                break;
            default:
                //run default behaviour
                Test::Keyboard(key);