Box2D C++ 教程-跳躍

轉載文章:原貼地址:http://ohcoder.com/blog/2012/11/30/jumping/

  • 跳躍(Jumping)

水平滾軸遊戲中的角色可以進行跳躍,是吧?現在就讓我們看看幾種不同實現跳躍的方法。我們已經在之前力和衝量(force and impulses)的話題中進行過相關問題的討論,但是現在就讓我們考慮一下如何把這些方法整合到遊戲中。我們可以從勻速運動(moving at constant speed)這個話題開始,在一定範圍內左/右控制移動一個動態物體。

pic

  • 直接設置速度

當玩家跳躍的時候他們的速度就會改變,讓我們以此爲起點。首先在Keyboard()方法中添加一個case分支,來獲得玩家的跳躍輸入:

1
2
3
4
5
6
7
case 'j': //jump
{
    b2Vec2 vel = body->GetLinearVelocity();
    vel.y = 10;//upwards - don't change x velocity
    body->SetLinearVelocity( vel );
}
break;

現在按下鍵盤j就會直接改變物體的速度,當然我們知道,這種方式並不是真實世界裏的物理方法。對於橫屏遊戲中的跳躍使用這種方法可能不太合適,這裏有幾點需要注意的地方。首先這樣做物體自身的動量沒有考慮其中,當玩家快速掉落的時候可以用相等的力跳起。玩家可以在半空中進行跳躍-也許這種現象正是你想要的,美其名曰‘連跳’特性。接下來我們會解決這個半空跳躍的問題,稍後我們會討論玩家跳躍之後是否着地。

  • 使用力

現實生活中,當你真正跳躍的時候,你會在自己身體上施加一個向上的力,那麼讓我們看看對物體連續幾幀施加強力能否達到此效果。在Keyboard()方法中我們將簡單做一個跳躍開始的標記,在Step()方法中完成力的施加。使用一個類的成員變量來記錄每次的每次應該施加多少幀的力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//class member variable
int remainingJumpSteps;

//in constructor
remainingJumpSteps = 0;

//keyboard function
case 'k': //jump
    remainingJumpSteps = 6;// 1/10th of a second at 60Hz
    break;

//in Step() function
if ( remainingJumpSteps > 0 ) {
    body->ApplyForce( b2Vec2(0,500), body->GetWorldCenter() );
    remainingJumpSteps--;
}

現在嘗試着按下k鍵。和之前類似,但是這次當物體下落的時候,因爲下降的動量考慮在內,所以跳躍效果會減小很多。這裏使用的力只是一個看起來差不多的數值。如果你想指定物體產生起飛(take-off)的速度,需要使用之前推算力矩的公式,根據你想讓物體左/右移動的速度推算出相應的力矩(f=mv/t),在每一幀中對物體施加此作用力:

1
2
3
4
5
6
7
8
if ( remainingJumpSteps > 0 ) {
    //to change velocity by 10 in one time step
    float force = body->GetMass() * 10 / (1/60.0); //f = mv/t
    //spread this over 6 time steps
    force /= 6.0;
    body->ApplyForce( b2Vec2(0,force), body->GetWorldCenter());
    remainingJumpSteps--;
}
  • 使用衝量

這種方法可能會是你經常用到的,本質上是使用上面相同的力,只在一個時間步長中完全實現相應的效果。正如之前話題中提到的那樣我們可以忽略時間部分:

1
2
3
4
5
6
7
case 'l':
{
    //to change velocity by 10
    float impulse = body->GetMass() * 10;
    body->ApplyLinearImpulse(b2Vec2(0, impulse),body->GetWorldCenter());
}
break;

這種方法比施加作用力更接近直接改變速度的效果,因爲每一幀都會有力對物體的作用,重力起到了下降的作用。其實,如果你離近點仔細觀看,會發現直接使用作用力來實現跳躍並不能和另外兩種方法那樣跳的一樣高。然而,如果你想實現一種緩慢跳起的效果,來取代直接跳起,那麼作用力方法會更有用。

  • 其它方法

在真實世界裏,每一個動作都會產生一個大小相等,方向相反的作用。如果你使用腿推動身體跳向空中,無論你站在哪裏,都會產生一個相等的向下推力。上面的所提到的方法都沒有把這一點考慮在內,然而大部分遊戲裏也不需要考慮這些。但是如果你需要模擬這種情況,這裏有兩種可以實現的方法,這兩種方法需要我們再多學習一點才能實現,所以現在我只是順帶提一下。

當確定玩家站在什麼物體上之後,如果此物體是動態物體,那麼你應該對此物體施加相同的力/衝量。這就像你站在鞦韆橋(swing bridge)上進行跳躍一樣,比如說,當玩家跳起的時候,橋會瞬間得到一個取代玩家重力的向下推力。爲了達到這種效果,我們需要知道如何告訴玩家接觸到了什麼。

使用棱鏡(滑動)連接器(prismatic(sliding)joint)把兩個物體連接起來能更快的模擬物體跳躍的效果。使用這種方法,玩家需要擁有一個主物體,比如我們正在使用的這個,另一個連接着的是可以上下滑動的小物體。連接器馬達(joint motor)可以向下推小物體,就像是你用腿進行起跳一樣。這麼做有一個好的優點是我們不用很麻煩的去檢查,物體到底站在一個什麼樣的地方,因爲如果玩家所站立的下方不能保證‘腿’能將身體推向上方,那麼玩傢什麼也不發生。此外,如果玩家站立的地方比較‘軟’,就像鞦韆橋一樣,那麼玩家的跳起效果將會減小,就像真實世界一樣。當然除了能夠完成更多效果以外,還是會有它自身需要考慮的問題的。我希望這個話題可以放到連接器以及馬達連接器講解之後再進行深入探討。

  • 讓物體從旋轉中停止

你可能已經注意到那個讓被我們看做玩家的物體不停的在一定區域內自由的做旋轉。一個簡單而又奏效的方法是把物體設置成固定旋轉體:

1
body->SetFixedRotation(true);

發佈了36 篇原創文章 · 獲贊 5 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章