Libgdx: 用于碰撞的Tiled对象层

3

先生们,您好:

我现在正在尝试通过使用Tiled Object层来执行玩家的碰撞检测,更具体地说,我希望它能够检测到我在平铺地图中绘制的折线。当我在谷歌上搜索有关Tiled碰撞检测的信息时,我发现了这个简单的示例TiledmapLayer的superkoala示例。在我对代码的理解中(如果我错了,请纠正我),为了检测碰撞,玩家将读取某个图层的每个瓦片,例如包含地面和其他对象的前景层。

基本上,我在我的Object层中所做的是将我的折线命名为Wall,并根据我使用了多少条折线来放置数字类型。因此,未来我可以调用这些墙体编号进行碰撞。

有人可以给我提供一个关于读取对象并将其用于碰撞检测的示例代码吗?或者只是一个简单的提示或想法,我该如何解决这个问题?任何帮助都将不胜感激。

2个回答

1
我建议您不要使用对象层,而是使用特定瓷砖的属性。比如说,在'Tiled'中有一个瓷砖,您确定只将其用作墙壁。点击该特定瓷砖并添加属性“blocked”。然后,在您的代码中,您可以检查玩家旁边的每个单元格,如果它包含属性“blocked”,则不允许玩家朝那个方向前进。以下是我如何做的伪代码:
private boolean isCellBlocked(float x, float y) {
    Cell cell = null;
    boolean blocked = false;

    try {
        cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
    } catch (Exception e) {
        e.printStackTrace();
    }

    if (cell != null && cell.getTile() != null) {
        if (cell.getTile().getProperties().containsKey("blocked")) {
            blocked = true;
        }
    }
    return blocked;
}

并且您可以使玩家每次更新时调用isCellBlocked(x, y)

我还为每个方向创建了一个collidesSide(float x, float y)collidesTop(float x, float y)等)。

希望这能对您有所帮助,即使它没有使用您想要的系统。如果需要更多关于此方面的帮助,我在一个大项目中大量使用libGDX进行碰撞检测,所以请不要犹豫与我联系!


我想知道为什么你建议不要使用对象层。这将减少需要相交的矩形数量。虽然你的解决方案无疑是可行的,但更多地是展示了你的做法,而没有探索使用对象层来大大简化属性编辑的用法。 - RichieHH
@RichieHH 我发现在TileD中使用属性而不是处理对象图层更容易。 - Ferdz
为什么?如果您使用瓦片,您需要为每个瓦片添加和解析属性。当您可以在对象层上拥有一个具有完全相同属性的单个对象,并在许多情况下导致单个B2D体时,为什么要这样做呢?https://gist.github.com/anonymous/a2c61d04572455c75fcd - RichieHH
好的,这是一篇一年前的帖子。如果您更喜欢自己的答案,请发布一个新的回答。 - Ferdz
帖子的年龄并不重要,但公平起见,我的答案更适用于使用box2d的情况,这在上面并不清楚:解析对象层并创建box2d物体-让box2d处理碰撞检测-移动时无需轮询周围环境,并且所有内容都在box2d世界坐标中,这是一个额外的好处。 - RichieHH

0

我看到了这个问题/答案,想分享一下我使用的方法。虽然我还没有完全弄清楚所有细节,但它对我来说已经很有效了:

    void buildMap() {
        MapLayer collisionLayer = (MapLayer) map.layers.find { it.name == 'collision' }
        collisionLayer.objects.each { MapObject mapObject ->
            Body body = null

            if(mapObject instanceof RectangleMapObject) {
                Rectangle rectangle = adjustRectangleDimensions(mapObject.rectangle)
                body = bodyFactory.makeBoxPolyBody(
                        rectangle.x,
                        rectangle.y,
                        rectangle.width,
                        rectangle.height,
                        BodyFactory.STONE,
                        BodyDef.BodyType.StaticBody
                )
            }

            if(mapObject instanceof PolygonMapObject) {
                Polygon polygon = adjustPolygonDimensions(mapObject.polygon)
                body = bodyFactory.makePolygonShapeBody(
                        polygon.vertices,
                        polygon.x,
                        polygon.y,
                        BodyFactory.STONE,
                        BodyDef.BodyType.StaticBody
                )
            }


            body.fixtureList.first().filterData.categoryBits = GROUND_BIT
            body.fixtureList.first().filterData.maskBits = PLAYER_BIT // can combine with | if multiple i.e. GROUND_BIT | PLAYER_BIT
        }
    }

    static Rectangle adjustRectangleDimensions(Rectangle rectangle) {
        rectangle.x = rectangle.x * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.y = rectangle.y * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.width = rectangle.width * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.height = rectangle.height * RenderingSystem.PIXELS_TO_METRES * 2 as float
        return rectangle
    }

    static Polygon adjustPolygonDimensions(Polygon polygon) {
        float x = polygon.x * RenderingSystem.PIXELS_TO_METRES as float
        float y = polygon.y * RenderingSystem.PIXELS_TO_METRES as float
        polygon.setPosition(x, y)

        float[] vertices = polygon.vertices //might need to get transformedVertices at some point, seems to work now
        def adjustedVertices = []
        vertices.each {
            adjustedVertices.add(it * RenderingSystem.PIXELS_TO_METRES as float)
        }

        polygon.vertices = adjustedVertices

        return polygon
    }

在这种情况下,RenderingSystem.PIXELS_TO_METRES是我用于OrthogonalTiledMapRenderer的单位比例尺。
我使用的bodyFactory可以在https://github.com/lifeweaver/learningGames/blob/master/core/src/net/stardecimal/game/BodyFactory.groovy中找到。
另请参见https://github.com/yichen0831/Pacman_libGdx/blob/master/core/src/com/ychstudio/builders/WorldBuilder.java以获取另一个示例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接