Box2D 碰撞错误
Box2D collisions error
我目前在 libgx java 中使用 box2d 物理引擎,我遇到了碰撞问题。
问题是 body 停止移动,并且在平坦区域出现碰撞点。
我的工作方式是制作多个物体,每个物体代表一个方块,这些方块是 side-by-side。
看这里的碰撞点:
body应该不会在这里发生碰撞,因为物体的Y坐标相等,而且它们的边也相等。
float PPM = 100;
float side = 45;
for (float i = start; i < end; i++) {
/**
* perlin noise for terrain
*/
def.type = BodyDef.BodyType.StaticBody;
float place = Maths.map(noise.noise(off, off), 0, 1, -10, 50);
if (place < 10) {
place = 0;
} else if (place < 20) {
place = side;
} else if (place < 30) {
place = side * 2;
} else if (place < 40) {
place = side * 3;
} else if (place <= 50) {
place = side * 4;
}
place += side / 2;
float posx = (i * side);
float posy = place;
float size = side / 2f;
def.position.set(posx / PPM, posy / PPM);
b = world.createBody(def);
shape.setAsBox(size / PPM, size / PPM);
fdef.shape = shape;
fdef.isSensor = false;
b.createFixture(fdef);
off += 0.01;
toSetLast = posx + side;
GrassBlock grass = new GrassBlock(b, new
Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
//dirt under grass
for (float j = (place / side) - 1; j >= -1; j--) {
posy = j * side;
def.position.set(posx / PPM, posy / PPM);
b = world.createBody(def);
shape.setAsBox(size / PPM, size / PPM);
fdef.isSensor = false;
fdef.shape = shape;
b.createFixture(fdef);
DirtBlock dirt = new DirtBlock(b, new
Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
addBlock(dirt.getLocation(), dirt);
}
addBlock(grass.getLocation(), grass);
}
我相信您遇到的是 Box2D 库的一个已知缺点。
请参阅 What could cause a sudden stop in Box2D? for another write-up of this problem. See Box2D C++ tutorials - Ghost vertices 以了解正在发生的事情以及您可以采取哪些措施来缓解问题...
基本上,对 ground 使用链形纹理而不是多边形(或在多边形上方),这样您的移动块实际上会在链的顶部移动。假设您正在使用的 java box2d 实现版本具有提供 "ghost vertices" 支持的链形。
后台详细信息...
虽然从用户的角度来看,链形状提供了平滑效果,在幕后,它是用来进行平滑的边缘形状。边缘形状使用两个特殊的额外顶点(除了预期的两个边缘)来执行此操作。当库正在评估链形状和多边形(或圆形)之间的接触时,它通过识别可能发生接触的链段来实现。然后将该链段转换为一条边,其额外顶点设置为链中的相邻顶点。然后在平移的边和多边形(或圆)之间评估接触。这会自动发生在链形状上,链形状中没有用于获得此行为的选项。
用户可以通过将链的所有段的边形状缝合在一起并将所有边的额外顶点设置为逻辑上相邻的顶点来获得与链形状相同的结果。然而,这比链形状使用更多的内存,并且需要用户编写更多代码来完成(至少对于具有两个以上顶点的链)。
虽然 Louis Langholtz 的回答已经很好了,但我还有更多要补充的。
链或幽灵顶点通常是推荐的方法,但是:-
- 实践中很难用。
- 需要编码人员手动将这些 edges/corners 连接在一起。
(在某些情况下很乏味)
我建议将盒子倒角 :-
我已经测试过 (jbox2d) - 它可以显着降低故障的影响。
这种方法的缺点是它需要额外的顶点。
(例如 4 个顶点 -> 8 个顶点)
因此,它需要更多的计算能力。
因此,在实践中,我通常将所有主体分为 2 组 :-
- 可以有小故障(例如碎片)-> 不要修改(便宜)
- 不能有故障(例如字符)-> 使用倒角方法(更昂贵)
就我个人而言,我希望有一种使用 chain/ghost 的简单方法,正如 Louis Langholtz 所推荐的那样。
我目前在 libgx java 中使用 box2d 物理引擎,我遇到了碰撞问题。 问题是 body 停止移动,并且在平坦区域出现碰撞点。 我的工作方式是制作多个物体,每个物体代表一个方块,这些方块是 side-by-side。 看这里的碰撞点:
body应该不会在这里发生碰撞,因为物体的Y坐标相等,而且它们的边也相等。
float PPM = 100;
float side = 45;
for (float i = start; i < end; i++) {
/**
* perlin noise for terrain
*/
def.type = BodyDef.BodyType.StaticBody;
float place = Maths.map(noise.noise(off, off), 0, 1, -10, 50);
if (place < 10) {
place = 0;
} else if (place < 20) {
place = side;
} else if (place < 30) {
place = side * 2;
} else if (place < 40) {
place = side * 3;
} else if (place <= 50) {
place = side * 4;
}
place += side / 2;
float posx = (i * side);
float posy = place;
float size = side / 2f;
def.position.set(posx / PPM, posy / PPM);
b = world.createBody(def);
shape.setAsBox(size / PPM, size / PPM);
fdef.shape = shape;
fdef.isSensor = false;
b.createFixture(fdef);
off += 0.01;
toSetLast = posx + side;
GrassBlock grass = new GrassBlock(b, new
Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
//dirt under grass
for (float j = (place / side) - 1; j >= -1; j--) {
posy = j * side;
def.position.set(posx / PPM, posy / PPM);
b = world.createBody(def);
shape.setAsBox(size / PPM, size / PPM);
fdef.isSensor = false;
fdef.shape = shape;
b.createFixture(fdef);
DirtBlock dirt = new DirtBlock(b, new
Vector2(b.getPosition().x * PPM, b.getPosition().y * PPM));
addBlock(dirt.getLocation(), dirt);
}
addBlock(grass.getLocation(), grass);
}
我相信您遇到的是 Box2D 库的一个已知缺点。
请参阅 What could cause a sudden stop in Box2D? for another write-up of this problem. See Box2D C++ tutorials - Ghost vertices 以了解正在发生的事情以及您可以采取哪些措施来缓解问题...
基本上,对 ground 使用链形纹理而不是多边形(或在多边形上方),这样您的移动块实际上会在链的顶部移动。假设您正在使用的 java box2d 实现版本具有提供 "ghost vertices" 支持的链形。
后台详细信息...
虽然从用户的角度来看,链形状提供了平滑效果,在幕后,它是用来进行平滑的边缘形状。边缘形状使用两个特殊的额外顶点(除了预期的两个边缘)来执行此操作。当库正在评估链形状和多边形(或圆形)之间的接触时,它通过识别可能发生接触的链段来实现。然后将该链段转换为一条边,其额外顶点设置为链中的相邻顶点。然后在平移的边和多边形(或圆)之间评估接触。这会自动发生在链形状上,链形状中没有用于获得此行为的选项。
用户可以通过将链的所有段的边形状缝合在一起并将所有边的额外顶点设置为逻辑上相邻的顶点来获得与链形状相同的结果。然而,这比链形状使用更多的内存,并且需要用户编写更多代码来完成(至少对于具有两个以上顶点的链)。
虽然 Louis Langholtz 的回答已经很好了,但我还有更多要补充的。
链或幽灵顶点通常是推荐的方法,但是:-
- 实践中很难用。
- 需要编码人员手动将这些 edges/corners 连接在一起。
(在某些情况下很乏味)
我建议将盒子倒角 :-
我已经测试过 (jbox2d) - 它可以显着降低故障的影响。
这种方法的缺点是它需要额外的顶点。
(例如 4 个顶点 -> 8 个顶点)
因此,它需要更多的计算能力。
因此,在实践中,我通常将所有主体分为 2 组 :-
- 可以有小故障(例如碎片)-> 不要修改(便宜)
- 不能有故障(例如字符)-> 使用倒角方法(更昂贵)
就我个人而言,我希望有一种使用 chain/ghost 的简单方法,正如 Louis Langholtz 所推荐的那样。