我正在为我的项目制作一款像野鸟一样的游戏。除了最基本的东西之外,大多数事情都已完成:在游戏物理中给出一种逼真的感觉。我最挣扎的部分是伤害。我正在使用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>
我已将b2VelocityThreshold设置为最大值(进一步增加它会引入游戏中物体的不良行为)。 postSolve方法还设置了足够高的阈值。我的方法出了什么问题?
感谢。
答案 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
}
由于你知道盒子的设置,你可能能够找到多个盒子。