首页 > 解决方案 > 与跨越多个图块的对象发生碰撞时如何从分块地图编辑器中删除多个单元格

问题描述

我正在使用 libgdx 创建一个破砖游戏,使用 TiledMapEditor 创建我的关卡。我有一个图层用于我的砖图形和一个图层用于我的砖对象。我与我的砖对象发生碰撞,当发生碰撞并工作时,我将砖图形图层中的图块设置为空。太棒了,太棒了……除了我已经将我的边缘创建为多个大小的瓷砖。所以当我与我的砖对象发生碰撞时,它会关闭碰撞并删除该特定的单元格图形。留下一半的砖块仍然显示在屏幕上。我检查了有关 tiledMaps、libdx dox 的文档并搜索了 slack/goodle/youtube/tiled dox。我想创建一种方法来检查周围的单元格是否不为空,然后将它们变为空,但是当我将砖块放在一起时,这将不起作用。任何想法或建议,甚至是在哪里寻找的提示都将不胜感激。或者改变我的砖块尺寸以适应一块瓷砖。我宁愿想办法删除指定对象上的所有单元格

用于创建我的交互式对象的类

    public InteractiveTileObject(World world, TiledMap map, Rectangle rect) {
        this.world = world;
        this.map = map;
        this.rect = rect;

        bDef = new BodyDef();
        fDef = new FixtureDef();
        shape = new PolygonShape();

        bDef.type = BodyDef.BodyType.StaticBody;
        bDef.position.set((rect.getX() * Arma.VSCALE) + (rect.getWidth() * Arma.VSCALE / 2),
                (rect.getY() * Arma.VSCALE) + (rect.getHeight() * Arma.VSCALE / 2));

        body = world.createBody(bDef);

        shape.setAsBox(rect.getWidth() * Arma.VSCALE / 2, rect.getHeight() * Arma.VSCALE / 2);
        fDef.shape = shape;
        fixture = body.createFixture(fDef);
    }

    public abstract void onHit();

    public void setCategoryFilter(short filterBit){
        Filter filter = new Filter();
        filter.categoryBits = filterBit;
        fixture.setFilterData(filter);
    }
    public TiledMapTileLayer.Cell getCell(){
        int column = (int)(body.getPosition().x / Arma.VSCALE / 50);
        int row = (int)(body.getPosition().y / Arma.VSCALE / 50);
        TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(2);
        return layer.getCell(column,row);
    }
}

从 TiledMapEditor 中提取对象的类

public B2WorldCreator(PlayScreen screen) {
        World world = screen.getWorld();
        TiledMap map = screen.getMap();


        BodyDef bDef = new BodyDef();
        PolygonShape shape = new PolygonShape();
        FixtureDef fDef = new FixtureDef();
        Body body;

        //create boundy body/fix
        for (MapObject object : map.getLayers().get(3).getObjects().getByType(RectangleMapObject.class)) {
            Rectangle rect = ((RectangleMapObject) object).getRectangle();
            new Boundary(world, map, rect);
        }
        //create bricks body/fix
        for (MapObject object : map.getLayers().get(4).getObjects().getByType(RectangleMapObject.class)) {
            Rectangle rect = ((RectangleMapObject) object).getRectangle();
            new Brick(world, map, rect);
        }

        //create wall light body/fix
        for (MapObject object : map.getLayers().get(5).getObjects().getByType(RectangleMapObject.class)) {
            Rectangle rect = ((RectangleMapObject) object).getRectangle();
            new Wall(world, map, rect);
        }
    }
}

砖类

public class Brick extends InteractiveTileObject{

    public Brick(World world, TiledMap map, Rectangle bounds) {
        super(world, map, bounds);
        fixture.setUserData(this);
        setCategoryFilter(Arma.BRICK_BIT);
    }

    @Override
    public void onHit() {
        Gdx.app.log("Brick", "Collision");
        setCategoryFilter(Arma.DEYSTROYED_BIT);
        getCell().setTile(null);

    }
}

我创建了这个有效但仍需要输入对象大小的方法,我宁愿让你的方法工作 Tobias。

public void getCells(int width, int height){
        int column = (int)((body.getPosition().x / Arma.VSCALE -25) / 50);
        int row = (int)((body.getPosition().y / Arma.VSCALE -25) / 50 );
        TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(2);
        for (int i = 0; i < width; i++){
            for (int k = 0; k < height; k++){
                if (layer.getCell(column + i, row + k) != null)
                    layer.getCell(column + i, row + k).setTile(null);
            }
        }

标签: javalibgdxtmxtiledmap

解决方案


您正在选择要按其在平铺地图上的位置删除的单元格。您可以对被击中的 Box2D 主体范围内的其他单元格执行相同操作。唯一的区别是,检查被测试的位置是否仍然在身体内部有点困难(目前你只检查身体的位置)。

解决方案可能如下所示:

public class InteractiveTileObject {

    // ... other methods

    public Array<TiledMapTileLayer.Cell> getCells(){
        Array<TiledMapTileLayer.Cell> cells = new Array<>();
        TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(2);
        
        for (int i = 0; i < MAX_NUMBER_OF_CELLS_PER_BODY; i++) {
            for (int j = 0; j < MAX_NUMBER_OF_CELLS_PER_BODY; j++) {
                float x = body.getPosition().x + i * SIZE_OF_A_TILE_CELL;
                float y = body.getPosition().y + j * SIZE_OF_A_TILE_CELL;
                if (doesBodyContainPoint(body, x, y)) {
                    int column = (int)(x / Arma.VSCALE / 50);
                    int row = (int)(y / Arma.VSCALE / 50);
                    cells.add(layer.getCell(column, row));
                }
            }
        }
        
        return cells;
    }

    private boolean doesBodyContainPoint(Body body, float x, float y) {
        // to check whether the body contains a point you need to check whether any of the body's fixtures contains the point:
        for (Fixture fixture : body.getFixtureList()) {
            if (fixture.testPoint(new Vector2(x, y)) {
                return true;
            }
        }
        return false;
    }
}

在你填写了常量之后MAX_NUMBER_OF_CELLS_PER_BODYSIZE_OF_A_TILE_CELL你应该能够找到这个 body 包含的每个单元格。然后你可以像以前一样删除它们。


推荐阅读