1

所以我试图在我的游戏中实现碰撞检测,我在 tmx 文件中有一个名为 Collision 的层。LIBGDX 现场教程不涉及与对象层的交互,而且很难弄清楚如何首先渲染地图。这就是我渲染屏幕的方式,我想学习如何获取我的碰撞层,然后让我的精灵与之交互。

@Override
    public void render(float delta) {
        translateCamera();

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        camera.update();

        renderer.setView(camera);

        renderer.render(bgLayers);
        // renderer.render();

        batch.begin();

        batch.draw(playerDirect, Gdx.graphics.getWidth() / 2,
                Gdx.graphics.getHeight() / 2);

        batch.end();
        renderer.render(fgLayers);

    }
4

2 回答 2

7

有一种方法可以使用对象层。不要放弃希望!

与使用平铺属性相比,此方法的一个主要优点是您可以轻松生成更少、更大的实体,从而提高 Box2d 的效率。另外,更好的是,这些身体可以是你想要的任何形状!我的游戏中的示例关卡现在只有三个基于滑稽形状(看起来更有机)的身体,而不是几十个方形ChainShape的身体。

前几天我在 GameDev 上回答了同样的问题,在网络丛林深处进行了一次认真的狩猎之后。我发现的教程对我来说不太适用,所以稍后我进行了一些编辑,我想出了这个:

public class MapBodyBuilder {

    // The pixels per tile. If your tiles are 16x16, this is set to 16f
    private static float ppt = 0;

    public static Array<Body> buildShapes(Map map, float pixels, World world) {
        ppt = pixels;
        MapObjects objects = map.getLayers().get("Obstacles").getObjects();

        Array<Body> bodies = new Array<Body>();

        for(MapObject object : objects) {

            if (object instanceof TextureMapObject) {
                continue;
            }

            Shape shape;

            if (object instanceof RectangleMapObject) {
                shape = getRectangle((RectangleMapObject)object);
            }
            else if (object instanceof PolygonMapObject) {
                shape = getPolygon((PolygonMapObject)object);
            }
            else if (object instanceof PolylineMapObject) {
                shape = getPolyline((PolylineMapObject)object);
            }
            else if (object instanceof CircleMapObject) {
                shape = getCircle((CircleMapObject)object);
            }
            else {
                continue;
            }

            BodyDef bd = new BodyDef();
            bd.type = BodyType.StaticBody;
            Body body = world.createBody(bd);
            body.createFixture(shape, 1);

            bodies.add(body);

            shape.dispose();
        }
        return bodies;
    }

    private static PolygonShape getRectangle(RectangleMapObject rectangleObject) {
        Rectangle rectangle = rectangleObject.getRectangle();
        PolygonShape polygon = new PolygonShape();
        Vector2 size = new Vector2((rectangle.x + rectangle.width * 0.5f) / ppt,
                                   (rectangle.y + rectangle.height * 0.5f ) / ppt);
        polygon.setAsBox(rectangle.width * 0.5f / ppt,
                         rectangle.height * 0.5f / ppt,
                         size,
                         0.0f);
        return polygon;
    }

    private static CircleShape getCircle(CircleMapObject circleObject) {
        Circle circle = circleObject.getCircle();
        CircleShape circleShape = new CircleShape();
        circleShape.setRadius(circle.radius / ppt);
        circleShape.setPosition(new Vector2(circle.x / ppt, circle.y / ppt));
        return circleShape;
    }

    private static PolygonShape getPolygon(PolygonMapObject polygonObject) {
        PolygonShape polygon = new PolygonShape();
        float[] vertices = polygonObject.getPolygon().getTransformedVertices();

        float[] worldVertices = new float[vertices.length];

        for (int i = 0; i < vertices.length; ++i) {
            worldVertices[i] = vertices[i] / ppt;
        }

        polygon.set(worldVertices);
        return polygon;
    }

    private static ChainShape getPolyline(PolylineMapObject polylineObject) {
        float[] vertices = polylineObject.getPolyline().getTransformedVertices();
        Vector2[] worldVertices = new Vector2[vertices.length / 2];

        for (int i = 0; i < vertices.length / 2; ++i) {
            worldVertices[i] = new Vector2();
            worldVertices[i].x = vertices[i * 2] / ppt;
            worldVertices[i].y = vertices[i * 2 + 1] / ppt;
        }

        ChainShape chain = new ChainShape(); 
        chain.createChain(worldVertices);
        return chain;
    }
}

假设您在 Box2d 中进行了设置,以便瓷砖的大小对应于 1 平方米(如果您愿意,可以使用 1 平方单位),那么它产生World的静态Bodys 将正是您在Tiled中绘制它们的位置。看到它启动并运行真是太令人满意了,相信我。

于 2014-02-18T15:04:59.023 回答
3

我建议将阻止的属性添加到实际的图块本身 - 您可以通过实际图块集上的平铺编辑器添加图块属性。您可以在图块集上检索它们的属性。我将引用文档:

一个 TiledMap 包含一个或多个 TiledMapTileSet 实例。一个瓦片集包含许多 TiledMapTile 实例。瓦片有多种实现方式,例如静态瓦片、动画瓦片等。您也可以为特殊的瓦片创建自己的实现

切片图层中的单元格引用这些切片。层内的单元格可以引用多个瓦片集的瓦片。但是,建议坚持每层使用单个图块集以减少纹理切换。

具体来说,在tileset 中的tile 上调用getProperties。这将检索属性 - 然后您可以与您的自定义属性进行比较,这可以告诉您某个特定图块是否被阻止 - 然后您可以继续实现自己的碰撞逻辑。

于 2013-08-04T04:53:41.863 回答