Box2d损坏物理

时间:2012-06-22 01:22:04

标签: box2d physics

我正在为我的项目制作一款像野鸟一样的游戏。除了最基本的东西之外,大多数事情都已完成:在游戏物理中给出一种逼真的感觉。我最挣扎的部分是伤害。我正在使用libgdx,它提供了一个围绕Box2d的包装器,所以代码不应该对任何知道Box2d的人都是陌生的。 这是postSolve方法

@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;
    }

我最初根据它们的尺寸给所有身体赋予健康值,并且每次发生足够强烈的碰撞时它们都会被相应地损坏。

问题在于身体以图像中所示的方式排列。即使在任何一个块上发生轻微碰撞,甚至没有移动,整个结构(我推测)开始振动,下面的块被破坏(因为健康)并且整个结构都掉了下来。 p>

enter image description here

我已将b2VelocityThreshold设置为最大值(进一步增加它会引入游戏中物体的不良行为)。 postSolve方法还设置了足够高的阈值。我的方法出了什么问题?

感谢。

3 个答案:

答案 0 :(得分:2)

我认为你在这里错误地使用了normalImpulses数组。尽管此数组总是两个元素长,但它只保留与碰撞流形中的点一样多的有效值,通常只有一个。它所持有的冲动值不适用于bodyA和bodyB,它们适用于歧管的各个点。

要获得碰撞“重”的正确值,您需要检查碰撞实际存在多少个碰撞点,如果有两个,那么您可以采用脉冲的平均值,或者最大值

我说“沉重”而不是“伤害”,因为即使冲击速度不变,这些冲动对于较重的身体也会更高。 PreSolve发生在所有接触体的每一帧,所以即使你有两个身体几乎一动不动,一个在另一个上面,如果身体很重,你仍然会得到一个很大的正常脉搏。我猜你在确定碰撞是否有害之前需要考虑所涉及的物体的质量。

每个帧都会调用PostSolve,而两个灯具正在接触,除非它们的身体处于睡眠状态。当你说整个结构被振动损坏时,我猜它只是身体正在睡觉,直到它们的部分结构被碰撞,并且所有的PostSolve突然开始加起来。

如果我是你,我会设置一个更简单的场景,比如只有一个身体坐在地上,然后放下另一个身体。看看你从中得到的normalImpulse的值,直到身体睡觉。改变它们的质量,改变掉落高度等,然后再做一次,看看normalImpulse值是如何受到影响的。这可以让您了解在确定碰撞是否造成损害时使用何种阈值,或者只是身体坐在彼此顶部的结果。

答案 1 :(得分:0)

我认为你可以尝试减少小伤害,因为通常你真的想在某些事情发生时施加伤害。我认为这种冲击的力量远远高于它们振动时施加在身体上的力。所以尝试这样的事情:

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

            if( health < 50 )
                isFlaggedForDelete = true;
    }

答案 2 :(得分: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


}

由于你知道盒子的设置,你可能能够找到多个盒子。