与跨越多个图块的对象发生碰撞时如何从图块地图编辑器中删除多个单元格

问题描述

我正在使用 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,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,rect);
        }
    }
}

砖类

public class Brick extends InteractiveTileObject{

    public Brick(World world,Rectangle bounds) {
        super(world,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);
            }
        }

解决方法

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

解决方案可能如下所示:

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 的常量后,您应该能够找到该正文包含的每个单元格。然后你可以像以前一样删除它们。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...