【问题标题】:LibGDX: How to make tiled map tiles clickable?LibGDX:如何使平铺地图图块可点击?
【发布时间】:2014-07-27 15:09:55
【问题描述】:

如何为瓦片地图中的瓦片添加点击侦听器,以便当您用鼠标选择瓦片时,它会突出显示?

【问题讨论】:

  • 首先您需要将鼠标屏幕坐标转换为世界图块坐标。那里有大量资源告诉你如何做。然后当用户点击 -> 检查磁贴 -> 运行代码时执行您的操作。

标签: java libgdx tiled


【解决方案1】:

libGDX 不直接支持,因为 TiledMap 仅用于渲染。

不过,您可以轻松地创建一个Stage,它将充当您的 TiledMap 的某种覆盖输入层。只需为每个与该图块具有相同大小的图块创建一个Actor。然后,您可以将 EventListeners 添加到这些演员,以便能够识别点击这些演员等内容。

那些演员应该保留对他们“起源”的引用,即TiledMapTileLayer.Cell。因此,在处理这些事件时,您可以随时从演员返回到单元格。

下面展示了你可以如何做到这一点:

此 Actor 负责捕获事件并保留有关它所基于的图块的信息:

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;
    }

}

这个小监听器可以附加到其中一个演员身上,并且会执行任何类型的逻辑:

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.");
    }
}

以下类实际上是从给定的地图创建演员并将它们连接到侦听器:

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);
            }
        }
    }
}

现在TiledMapStage 将为您完成所有工作。您需要做的就是:

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

在 render(...) 中你需要调用stage.act()。请记住在舞台上使用与渲染 TiledMap 相同的Viewport。否则输入和渲染的地图将不会对齐。

【讨论】:

  • 我无法为舞台设置相机,以便输入图层与平铺图层对齐...我该如何解决这个问题?
  • 通常你会通过stage.getViewport().setCamera(camera) 来做这件事,camera 是你用来绘制 TiledMap 的那个。
  • @noone 很抱歉让您失去了 10101 的良好代表分数,但 stage.getViewport().setCamera(camera) 正是我错过的,并导致我大量时间来回走动。你摇滚。
  • 对于那些使用带有比例的 OrthogonalTiledMapRenderer 的用户,您需要将 actor.setBounds... 行调整为 actor.setBounds(x, y , 1, 1);。在我的例子中,我为我的 10x10 tilemap 设置了 32f 的比例,并且使用示例中的逻辑,总是会得到 0,0 tile。我对 libGDX 完全陌生,所以我完全愿意听到其他/更好的方法来实现这一点。
  • @Caketray 我会说这是半高效的。如果您自己检查每个图块的坐标,则与Stage 检查Actors 时所做的几乎相同。但是,如果您能够根据坐标直接计算匹配图块,则效率会更高,并且不受地图大小的影响。
猜你喜欢
  • 1970-01-01
  • 2016-01-24
  • 2014-10-23
  • 1970-01-01
  • 2020-08-24
  • 2016-07-08
  • 1970-01-01
  • 2016-06-04
  • 2019-02-19
相关资源
最近更新 更多