2012-06-22 89 views
2

我正在爲我的項目製作一款類似遊戲的憤怒的小鳥。除了最基本的東西外,大部分的事情都完成了:在遊戲物理學中給人一種現實的感覺。我最掙扎的部分是傷害。我正在使用libgdx,它提供了Box2d的包裝,因此代碼不應該與任何知道Box2d的人有任何關係。 這是postSolve方法Box2d傷害物理

@Override 
    public void postSolve(Contact contact, ContactImpulse impulse) {  
     float[] forces = impulse.getNormalImpulses(); 

     int index1 = (Integer) contact.getFixtureA().getBody().getUserData(); 
     int index2 = (Integer) contact.getFixtureB().getBody().getUserData(); 

     if(forces[0] > 0.3) 
      bodies.get(index1).handleCollision(forces[0]); 

     if(forces[1] > 0.3) 
      bodies.get(index2).handleCollision(forces[1]); 
    } 

這翻出被碰撞的機構,並傳遞給它們的正常碰撞衝動,使得他們能夠處理損害。現在,這是機構

@Override 
    public void handleCollision(float impulse) { 
      health -= impulse; 

      else if(health < 50) 
       isFlaggedForDelete = true; 
    } 

我給健康值,根據它們的大小最初所有機構之一的破壞處理函數和他們應該每一個足夠強大的碰撞發生時獲得相應的損壞。

問題是,圖像中顯示的方式排列的身體。每當任何一個街區發生輕微碰撞時,甚至不會移動,整個結構(我假設)開始振動,下面的街區被破壞(因爲健康),整個結構都會倒塌。

enter image description here

我已經設置了b2VelocityThreshold爲最大值(進一步增加它引入了遊戲中的機構的不良行爲)。 postSolve方法還設置了足夠高的閾值。我的方法有什麼問題?

謝謝。

回答

2

我認爲你正在使用的normalImpulses陣列錯誤在這裏。雖然這個數組總是兩個元素長,但它只能保存與碰撞流形中的點一樣多的有效值,這通常只有一個。它所持有的脈衝值不是針對bodyA和bodyB,而是針對歧管的點。

爲了得到一個正確的值來確定碰撞的'重度'是多少,你需要檢查碰撞實際存在多少個碰撞點,如果有兩個碰撞點,那麼你可以取衝量的平均值,或者最大值也許。

我說「沉重」而不是「損害」,因爲即使撞擊速度沒有變化,這些衝動對於較重的身體來說也會更高。 PreSolve爲所有接觸身體發生每一幀,所以即使你有兩個身體幾乎靜止不動,一個在另一個之上,如果身體沉重,你仍然會得到一個大的正常脈衝。我想你在決定碰撞是否破壞之前需要考慮所涉及的物體的質量。

PostSolve被稱爲每幀,而兩個燈具接觸,除非他們的身體睡着。當你說整個結構受到振動的破壞時,我猜想這只是身體在睡覺,直到它們的一部分結構被碰撞,而所有的PostSolve突然開始累積起來。

如果我是你,我會設置一個更簡單的場景,比如說只有一個身體坐在地上,然後放下另一個身體。看看你從中得到的normalImpulse的值,直到身體入睡。改變他們的質量,改變下落高度等等,並且再次觀察正常脈衝值如何受到影響。這應該讓你知道在判定碰撞是否造成損害時使用什麼樣的閾值,或者僅僅是身體相互重疊的結果。

+0

所以你說normalImpulses數組會給我屬於單個夾具的點的正常衝動? – wirate

+0

你也說「所以即使你有兩個身體幾乎一動不動,一個在另一個上面,如果身體很重,你仍然會得到一個大的正常脈衝」我想我實際上必須考慮到另一個的動量身體。 – wirate

+0

接觸點並不屬於固定裝置,它們只是應用衝動推動固定裝置分開的最佳位置。 – iforce2d

0

我認爲你可以嘗試削減小傷害,因爲通常情況下你真的想在遇到某物時施加傷害。我認爲這種影響的力量要比震動時施加在身體上的力量高得多。因此,嘗試這樣的事情:

@Override 
    public void handleCollision(float impulse) { 
      if (impulse > SOME_VALUE) 
       health -= impulse; 

      if(health < 50) 
       isFlaggedForDelete = true; 
    } 
+0

if(forces [0]> 0.3)在postSolve中執行相同的操作。我不能進一步增加它。不管怎樣,身體在振動時的正常衝動比其他身體以速度撞擊時的衝動更大。也許這是因爲他們的體重? – wirate

+0

@wirate:嘗試添加阻尼。你用什麼平均密度? – Andrew

+0

密度各不相同。他們就像4,6.5和30一樣。問題解決了。感謝:) – wirate

0

要篩選出引起自重衝動,下面的代碼可能會有所幫助:

public void postSolve(Contact contact, ContactImpulse impulse) {  

    Fixture upperFixture = fixtureA; 
    if(fixtureA.getBody().getPosition().y<fixtureB.getBody().getPosition().y) 
     upperFixture = fixtureB; 

    // don't count body weight when calculating impulse 
    float weightImpulse = 
    -upperFixture.getBody().getMass()*gravityY*worldStep; 
    // if your fps is 60, worldstep would be 1/60 


    // finally we deduct impulse caused by weight from total impulse 
    float absImpulse = Math.abs(impulse.getNormalImpulses()[0]) - weightImpulse; 
    // this 'absImpulse' should be zero if you put a box on the ground 
    // and don't have anything on top of the box 


} 

既然你知道你的箱子的設置,你可以弄明白多箱。