【问题标题】:Collision Detection Tmx Maps using libgdx (java)使用 libgdx (java) 的碰撞检测 Tmx 地图
【发布时间】:2013-08-05 01:48:11
【问题描述】:

所以我试图在我的游戏中实现碰撞检测,并且我在 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);

    }

【问题讨论】:

    标签: java libgdx tmx


    【解决方案1】:

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

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

    前几天我在 GameDev 上answered the same question,在网络丛林深处进行了一次认真的狩猎之后。我发现的tutorial 对我来说不太适用,所以稍后我进行了一些编辑,我想出了这个:

    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 World 中进行了设置,以使您的瓷砖尺寸对应于 1 平方米(1 平方单位,如果您愿意的话),则此生成的静态 Bodys 将恰好位于你在 Tiled 中画了它们。看到它启动并运行真是太令人满意了,相信我。

    【讨论】:

    • 谢谢,这太棒了,它与 2d 完美结合!
    【解决方案2】:

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

    一个 TiledMap 包含一个或多个 TiledMapTileSet 实例。一块瓷砖 set 包含许多 TiledMapTile 实例。有多个 瓷砖的实现,例如静态图块、动画图块等。你 也可以创建自己的特殊实现

    瓦片层中的单元格引用这些瓦片。层内的单元格可以 多个图块集的参考图块。不过建议 坚持每层设置一个图块以减少纹理切换。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-02
      • 1970-01-01
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多