2011-01-26 130 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); 
    } 
} 

就这么简单。