【发布时间】:2018-09-03 21:31:26
【问题描述】:
我正在尝试构建一个样本,该样本包含一些相互移动和碰撞的圆圈。由于所有圆圈都具有相同的属性以及restitution = 1 和friction = 0,我希望它们应该永远以相同的速度弹跳。但是,相反,一些物体会减慢:
世界创造:
World.setVelocityThreshold(0);
world = new World(new Vector2(0, 0), true);
边界:
EdgeShape edge = new EdgeShape();
FixtureDef wallFixtureDef = new FixtureDef();
wallFixtureDef.shape = edge;
wallFixtureDef.density = 0;
wallFixtureDef.friction = 0;
wallFixtureDef.restitution = 1;
BodyDef wallBodyDef = new BodyDef();
wallBodyDef.type = BodyDef.BodyType.StaticBody;
Body wallsBody = world.createBody(wallBodyDef);
// Bottom
edge.set(1, 1, WIDTH - 1, 1);
wallsBody.createFixture(wallFixtureDef);
// Top
edge.set(1, HEIGTH - 1, WIDTH - 1, HEIGTH - 1);
wallsBody.createFixture(wallFixtureDef);
// Left
edge.set(1, 1, 1, HEIGTH - 1);
wallsBody.createFixture(wallFixtureDef);
// Right
edge.set(WIDTH - 1, 1, WIDTH - 1, HEIGTH - 1);
wallsBody.createFixture(wallFixtureDef);
圈子:
CircleShape circleShape = new CircleShape();
circleShape.setRadius(24);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circleShape;
fixtureDef.density = 1;
fixtureDef.friction = 0;
fixtureDef.restitution = 1;
for (int i = 1; i <= 10; i++) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(i * 70, HEIGTH / 2);
Body ballBody = world.createBody(bodyDef);
ballBody.createFixture(fixtureDef);
ballBody.setBullet(true);
ballBody.setLinearVelocity(300, 120);
}
我也尝试过不使用:World.setVelocityThreshold(0); 和不使用 ballBody.setBullet(true);,但效果相同。
那么,我该如何实现呢?如果restitution = 1 和friction = 0,是什么导致了这种行为?
更新:
终于按预期工作了。主要有两个问题:float精度和初速度太大(box2d有最大速度限制)。
我已经复制了这个例子,但单位要小得多:
radius = 10
density = 0.1f
velocity = (10, 10)
这并不能防止圆圈位置的精度误差,最终无法完美对齐。但它可以防止系统失去速度。
使用这些值,一旦圆没有对齐,取决于它们碰撞的角度,如果一个减速另一个加速。也就是说,系统的动量保持不变。
在原始示例中,问题是我使用了大单位。 Circles 的初始速度被限制为 box2d 允许的最大值。在这种情况下,当圆圈在没有对齐的情况下发生碰撞时,一个可能会减速,但另一个不能加速(因为它已经处于最大速度),因此系统会失去速度。系统的动量没有保持。
第一个修正是使用更小的单位,这样精度误差会更低,数值不会超过box2d的限制。
第二个,只对这个具体的例子有效,是在物理模拟完成后纠正圆圈的位置。
world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
float y = bodies[0].getPosition().y;
for (Body body : bodies) {
body.setTransform(body.getPosition().x, y, body.getAngle());
}
【问题讨论】:
标签: java libgdx box2d game-physics