gpt4 book ai didi

java - 从 tilemap 高效地生成 Box2D body(collision map)

转载 作者:行者123 更新时间:2023-11-29 05:49:31 28 4
gpt4 key购买 nike

我正在开发一款将使用瓦片 map 的平台游戏,我不知道这是否是个好主意!

我已经制作了一个简洁的 map 编辑器,其中包含用于设置重生点等的工具。但现在我希望能够在编辑 map 后测试玩游戏,为了将来使用,我当然需要整合物理,我'已经完成了 LibGDX 附带的 Box2D!

我正在创建一种方法来从瓦片 map 创建碰撞 map ,该 map 包含瓦片是否可碰撞的数据!

所以我想出了这个好主意:

循环遍历 map ,如果我们找到一个碰撞的瓦片,循环遍历它的相邻瓦片,看看它们是否也发生碰撞,并在我们为碰撞矩形设置宽度和高度时这样做,直到找到非碰撞的瓦片

在我们得到一堆矩形之后,我按照从最大正方形到最小正方形的顺序对它们进行排序,这样我们就得到了最大的部分,然后我将矩形添加到最终列表中,并检查最终矩形是否与当前主体重叠,所以我不没有重叠的 body

但是您知道,代码可以说明 1000 多个单词,对吗?

    public void createBody() {
List<Rectangle> allRects = new ArrayList<Rectangle>();
for(int x = 0; x < info.getWidth(); x++) {
for(int y = 0; y < info.getHeight(); y++) {
if(tiles[x][y].getInfo().isColliding()) {
int width = 1;
int height = 1;

//loop through neighbors horizontally
for(int i = 0; i < info.getWidth() - x; i++) {
if(!tiles[x + i][y].getInfo().isColliding()) {
//if tile is not clipped, we set width to i which is current x offset


width = i;
break;
}
}


//only if width is bigger than zero can the rect have any tiels..
if(width > 0) {
boolean breakingBad = false;
//loop through neighbors horizontally
for(int j = 0; j < info.getHeight() - y; j++) {
//loop though neigbors vertizally
for(int i = 0; i < width; i++) {
//check if tile is not colliding
if(!tiles[x + i][y + j].getInfo().isColliding()) {
//and if so, we set height to j which is current y offset
height = j;

//breaking bad aka leaving both loops
breakingBad = true;
break;
}
}
if(breakingBad) {
break;
}
}
}
if(width * height > 0)
allRects.add(new Rectangle(x, y, width, height));
}
}
}

Collections.sort(allRects, new Comparator<Rectangle>() {

@Override
public int compare(Rectangle o1, Rectangle o2) {
Integer o1Square = o1.width * o1.height;
Integer o2Square = o2.width * o2.height;
return o2Square.compareTo(o1Square);
}
});

List<Rectangle> finalRects = new ArrayList<Rectangle>();
mainloop:
for(Rectangle rect: allRects) {
for(Rectangle finalRect: finalRects) {
if(finalRect.contains(rect)) {
continue mainloop;
}
}
finalRects.add(rect);
}

for(Rectangle rect: finalRects) {
PolygonShape polyShape = new PolygonShape();
polyShape.setAsBox((float)rect.getWidth() / 2, (float)rect.getHeight() / 2, Vector2.tmp.set((float)rect.getCenterX(), (float)rect.getCenterY()), 0f);

mapBody.createFixture(polyShape, 1);
polyShape.dispose();
}

}

inefficient?

但是这个窗台看起来效率很低,因为出于某些原因它仍然创建了比它可能的更小的固定装置,例如在右上角

还在中心矩形的角上创建单个固定装置,我不明白为什么!

整个想法是否效率低下,我应该使用其他方法还是手动创建碰撞贴图,或者什么才是最好的想法?

最初每个瓷砖都是自己的固定装置,这会在它们的边缘产生奇怪的错误,正如预期的那样

最佳答案

首先,自定义图 block 映射工具表面上是个好主意,但您正在重新发明轮子。

libGDX 内置了对 TMX map 的支持。 http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/maps/tiled/TmxMapLoader.html

除了使用自制编辑器,您还可以使用功能齐全的编辑器,例如 Tiled - http://www.mapeditor.org/

因此,一旦您的 map 有了更好的系统,我就会从面向对象的角度来看待它。既然你想使用 box2d 物理,每个 collidableTile HAS A body。因此,您需要做的就是为每个 collidableTile 分配一个物理体,并根据您的标准图 block 大小设置大小。

不要忘记 box2d 世界和您的游戏屏幕之间存在差异,其中 box2d 以公制单位测量,而您的屏幕以像素测量。所以你需要做一些数学运算来正确设置位置和大小。如果你想让一组瓦片共享一个body,你可能想在构造每个collidableTile时将body作为参数传入,然后根据你能找到多少个相邻的瓦片来调整body的大小。物理体的更复杂形状可能更复杂。

您还可以通过将这些图 block 设置为“ sleep ”来节省资源,其中 box2d 在检测到碰撞之前对这些物体进行简化模拟。如果您只使用 box2d 进行地形碰撞检测,您可能需要考虑其他选项,例如使用形状库检测交叉点,然后在玩家角色 body 上设置 box2d 物理以在有接触时停止向下加速,或者某物。

关于java - 从 tilemap 高效地生成 Box2D body(collision map),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14464523/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com