2011-01-26 127 views
3

我遇到了box2d as3 b2ContactListener類的問題。我有一個名爲ContactListener的類,它擴展了b2ContactListener並覆蓋了PostSolve方法。 PostSolve需要2個參數,聯繫人保存有關聯繫人的2個對象的信息,以及包含聯繫人信息的衝動。我使用脈衝參數來決定2個物體擊中的難度,然後我相應地施加傷害。Box2d As3聯繫人監聽器問題

問題出在這裏: 如果我做出任何圓形的東西,讓它慢慢地在靜止的身體上滾動,我將它作爲地面,然後在地面上的任何地方放一個相當大的物體,獲取聯繫人將會產生重複的衝動,這種衝動對於僅僅滾動而言是很大的。它導致滾動的圓形物體在不應該時破碎。它幾乎就像震動靜止的身體,並在數百米遠的物體上造成巨大傷害,但它隻影響圓圈。

任何人都可以看到一些情況?這是一個已知的問題?解決方法?

我正在使用Box2DAs3版本2.1a。

更新:一旦身體進入這種怪異的狀態,造成很大的傷害,任何接觸它的圈子都會產生大量的巨大沖動。一旦非圓形的東西接觸到身體,它不再有問題。此外,這個問題不僅在靜態物體上,而且在動態和運動學上也是如此。

更新:我已經進一步縮小了問題的範圍。當一個大物體的平坦邊緣撞擊我的地面物體時,接觸者傾聽者大聲疾呼並施加質量衝動。任何醒目並觸及地面的物體(不僅僅是圓圈)都會得到大量的PostSolve方法調用。我試着將一個尺寸爲11像素×11像素的盒子放在地上,同時一個圓圈在地面上滾動。該錯誤沒有發生。但是如果這個盒子是12×12的話就會發生錯誤。另外,如果我將大小爲12的盒子旋轉12到0.1度,則不會發生錯誤。需要有足夠大的接觸面積才能重現。盒子的密度也不影響任何東西。此外,如果該框是一個寬度爲10,高度爲100的矩形,並且該bug會重新渲染。這幾乎就像對象的大小造成了錯誤,可能不是觸點大小的區域。

更新:這是一個Box2D論壇帖子的鏈接,我做了一個swf源碼的例子。

Link

+0

我對box2d一無所知,但這實際上會產生一定的物理意義,如果它影響靜止的圓圈以及滾動的圓圈。 – Beta 2011-01-26 16:54:37

回答

0

WOW。所以我終於找出問題所在。

經過幾個小時的努力,通過在ContactListener中做一些奇妙的事情來弄清楚是否有解決方法,我決定查看並查看PostSolve方法被調用的來源。它來自名爲b2Island的類,它來自該類中的Report函數。乍一看,我很容易發現問題。她的功能是:

private static var s_impulse:b2ContactImpulse = new b2ContactImpulse(); 
public function Report(constraints:Vector.<b2ContactConstraint>) : void 
{ 
    if (m_listener == null) 
    { 
     return; 
    } 

    for (var i:int = 0; i < m_contactCount; ++i) 
    { 
     var c:b2Contact = m_contacts[i]; 
     var cc:b2ContactConstraint = constraints[ i ]; 

     for (var j:int = 0; j < cc.pointCount; ++j) 
     { 
      s_impulse.normalImpulses[j] = cc.points[j].normalImpulse; 
      s_impulse.tangentImpulses[j] = cc.points[j].tangentImpulse; 
     } 
     m_listener.PostSolve(c, s_impulse); 
    } 
} 

所以是很明顯的s_impulse變種是靜態的,所以這將是b2Island類的每個實例相同的(如果有一個以上的),也它沒有得到復位在任何點。所有對s_impulse var的引用都可以在上面看到,所以沒有其他事情發生。但是,重點在於,一個圈子只與一個多邊形有一個聯繫,這意味着它只會在報告時設置一個聯繫的衝動。另一個聯繫人,如果沒有被重置,則會有最後一個要報告的對象的衝動。

基本上,在圈子上看到的衝動實際上是留在了剛剛報道的衝動之上。要修復它,請執行以下操作:

private static var s_impulse:b2ContactImpulse = new b2ContactImpulse(); 
public function Report(constraints:Vector.<b2ContactConstraint>) : void 
{ 
    if (m_listener == null) 
    { 
     return; 
    } 

    for (var i:int = 0; i < m_contactCount; ++i) 
    { 
     s_impulse = new b2ContactImpulse(); 

     var c:b2Contact = m_contacts[i]; 
     var cc:b2ContactConstraint = constraints[ i ]; 

     for (var j:int = 0; j < cc.pointCount; ++j) 
     { 
      s_impulse.normalImpulses[j] = cc.points[j].normalImpulse; 
      s_impulse.tangentImpulses[j] = cc.points[j].tangentImpulse; 
     } 
     m_listener.PostSolve(c, s_impulse); 
    } 
} 

就這麼簡單。