2

我正在为我的项目制作类似《愤怒的小鸟》的游戏。除了最基本的:在游戏物理中提供逼真的感觉之外,大多数事情都已完成。我最挣扎的部分是伤害。我正在使用 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;
    }

我最初根据所有身体的大小为所有身体提供健康值,并且每次发生足够强烈的碰撞时,它们都应该受到相应的伤害。

问题是身体以图像中显示的方式排列。每当任何一个方块发生轻微的碰撞,甚至没有使它移动时,整个结构(我认为)开始振动,下面的方块被破坏(因为健康),整个结构倒塌。

在此处输入图像描述

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

谢谢。

4

3 回答 3

2

我认为您在这里错误地使用了 normalImpulses 数组。虽然这个数组总是两个元素长,但它只包含与碰撞流形中的点一样多的有效值,而碰撞流形中的点通常可能只有一个。它持有的冲量值不是针对 bodyA 和 bodyB,而是针对流形的点。

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

我说的是“重”而不是“破坏”,因为即使撞击速度没有改变,对于较重的物体来说,这些冲动也会更高。PreSolve 对所有接触的物体在每一帧都发生,所以即使你有两个物体几乎一动不动地坐着,一个在另一个上面,如果物体很重,你仍然会得到一个很大的 normalImpulse。我想在确定碰撞是否具有破坏性之前,您需要考虑所涉及物体的质量。

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

如果我是你,我会设置一个更简单的场景,比如只有一具尸体坐在地上,然后将另一具尸体放在上面。看看你从那里得到的 normalImpulse 的值,直到身体睡觉。改变它们的质量,改变下落高度等,然后再做一次,看看 normalImpulse 值是如何受到影响的。这应该让您了解在确定碰撞是否造成损坏时使用什么样的阈值,或者仅仅是身体彼此重叠的结果。

于 2012-06-22T11:35:36.380 回答
0

我认为您可以尝试减少较小的伤害,因为通常您真的想在某物撞到某物时施加伤害。我认为这种冲击的力量比物体振动时施加的力量要高得多。所以尝试这样的事情:

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

            if( health < 50 )
                isFlaggedForDelete = true;
    }
于 2012-06-22T04:12:42.167 回答
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


}

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

于 2014-06-29T02:46:18.863 回答