简体   繁体   中英

LibGDX: How to make tiled map tiles clickable?

如何为平铺地图中的切片添加单击侦听器,以便在使用鼠标选择切片时它会突出显示?

That's not supported directly by libGDX as the TiledMap stuff is only for rendering.

You could easily create a Stage though, which will act as some kind of overlay-input-layer for your TiledMap. Just create an Actor for each tile which has the same size as position as that tile. Then you are able to add EventListener s to those actors to be able to recognize things like clicks on those actors.

Those actors should keep a reference to their "origin", namely TiledMapTileLayer.Cell . So you are able to go back from the actor to the cell anytime when processing those events.

The following shows how you might do it:

This Actor is responsible to catch the events and keep the information about the tile it's based on:

public class TiledMapActor extends Actor {

    private TiledMap tiledMap;

    private TiledMapTileLayer tiledLayer;

    private TiledMapTileLayer.Cell cell;

    public TiledMapActor(TiledMap tiledMap, TiledMapTileLayer tiledLayer, TiledMapTileLayer.Cell cell) {
        this.tiledMap = tiledMap;
        this.tiledLayer = tiledLayer;
        this.cell = cell;
    }

}

This little listener can be attached to one of those actors and will do any kind of logic:

public class TiledMapClickListener extends ClickListener {

    private TiledMapActor actor;

    public TiledMapClickListener(TiledMapActor actor) {
        this.actor = actor;
    }

    @Override
    public void clicked(InputEvent event, float x, float y) {
        System.out.println(actor.cell + " has been clicked.");
    }
}

The following class actually creates the actors from a given map and wires them to the listeners:

public class TiledMapStage extends Stage {

    private TiledMap tiledMap;

    public TiledMapStage(TiledMap tiledMap) {
        this.tiledMap = tiledMap;

        for (MapLayer layer : tiledMap.getLayers()) {
            TiledMapTileLayer tiledLayer = (TiledMapTileLayer)layer;
            createActorsForLayer(tiledLayer);
        }
    }

    private void createActorsForLayer(TiledMapTileLayer tiledLayer) {
        for (int x = 0; x < tiledLayer.getWidth(); x++) {
            for (int y = 0; y < tiledLayer.getHeight(); y++) {
                TiledMapTileLayer.Cell cell = tiledLayer.getCell(x, y);
                TiledMapActor actor = new TiledMapActor(tiledMap, tiledLayer, cell);
                actor.setBounds(x * tiledLayer.getTileWidth(), y * tiledLayer.getTileHeight(), tiledLayer.getTileWidth(),
                        tiledLayer.getTileHeight());
                addActor(actor);
                EventListener eventListener = new TiledMapClickListener(actor);
                actor.addListener(eventListener);
            }
        }
    }
}

Now the TiledMapStage will do all work for you. All you need to do is the following:

Stage stage = new TiledMapStage(tiledMap);
Gdx.input.setInputProcessor(stage);

And in render(...) you need to call stage.act() . Remember to use the same Viewport for the stage as you are using to render the TiledMap. Otherwise the input and your rendered map won't be aligned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM