1

我正在开发一个将使用平铺地图的平台游戏,我不知道这是否是个好主意!

我用设置生成点等工具制作了一个简洁的瓷砖地图编辑器,但现在我希望能够在编辑地图后测试玩游戏并为将来使用我当然需要整合我已经完成的物理LibGDX 附带的 Box2D!

我正在创建一种方法来从瓦片地图创建碰撞地图,如果瓦片是否可碰撞,该地图具有数据!

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

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

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

但是你知道,代码能说出超过 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();
    }

}

低效?

然而,这个门槛似乎相当低效,因为由于某些原因,它仍然创造了比可能的更小的固定装置,例如在右上角

它还在中心矩形的角落创建了单个固定装置,我不知道为什么!

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

最初,每个瓷砖都是自己的固定装置,这会在其边缘造成奇怪的错误,如预期的那样

4

1 回答 1

3

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

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

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

所以一旦你为你的地图建立了一个更好的系统,我会从面向对象的角度来看待这个问题。由于您想使用 box2d 物理,每个collidableTile都有 一个 body。因此,您需要做的就是为每个 collidableTile 分配一个物理体,并根据您的标准 tile 大小设置大小。

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

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

于 2013-07-15T20:22:37.730 回答