Box2d As3联系人监听器问题

时间:2011-01-26 01:56:37

标签: flash actionscript-3 physics box2d collision

我遇到了box2d as3 b2ContactListener类的问题。我有一个名为ContactListener的类,它扩展了b2ContactListener并覆盖了PostSolve方法。 PostSolve接受2个参数,其中包含有关联系的2个对象的信息,以及包含联系信息的脉冲。我正在使用脉冲参数来决定2个物体击中的难度,然后相应地施加伤害。

问题在于: 如果我制作任何圆形的东西,让它慢慢地在我身上的静态身体上滚动,然后在地面上的任何地方放一个相当大的物体,在运动中的圆圈将获得接触将是重复的冲动,这是通往大而刚刚滚动。它会导致滚动的圆形物体不应该破碎。

它几乎就像摇动静止的身体并对数百米外的物体造成巨大伤害,但它只会影响圆圈。

任何人都可以了解情况吗?这是一个已知的问题?解决方法?

我正在使用Box2DAs3版本2.1a。

更新:一旦身体进入这种奇怪的状态,即施加很大的伤害,任何接触它的圆圈都会产生大量的冲动。一旦非圆形的东西与身体接触,它就不再有问题了。此问题不仅出现在静态对象上,还出现在动态和运动学上。

更新:我已将问题进一步缩小。当大型物体的平坦边缘撞击我的地面物体时,接触式听众会惊慌失措并施加质量冲击。清醒并接触地面的任何物体,不仅仅是圆圈,都会有大量的PostSolve方法调用。我试着将一个尺寸为11像素×11像素的盒子放在地上,同时一个圆圈在地面上滚动。这个错误没有发生。但是,如果框是12乘12,则确实会发生错误。此外,如果我旋转一个大小为12乘12到0.1度的盒子,则不会发生错误。需要有足够大的接触区域才能重现。盒子的密度也不会影响任何东西。此外,如果框是宽度为10且高度为100的矩形,则错误将重现。这几乎就像对象的大小导致了bug,可能不是接触区域的大小。

更新:以下是我制作的Box2D论坛帖子的链接,其中包含一个带源代码的swf示例。

Link

1 个答案:

答案 0 :(得分: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 var是静态的,因此它对于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);
    }
}

就这么简单。