You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LibGDX问题:Tilemap中按坐标放置纹理显示异常

问题:LibGDX中Tilemap对象层坐标与相机正交模式不匹配导致渲染错位

我正在做一个学校Java游戏项目,使用Tiled工具创建的Tilemap显示正常。为了在地图上实现瀑布动画,我在Tilemap中添加了对象层,并能在Java代码中获取这些对象的坐标、尺寸等信息。

核心问题

加载制作Tilemap时使用的纹理图,分割后将对应瓦片放置到对象坐标处,但纹理显示在地图之外。测试时尝试将纹理放在鼠标坐标位置,发现camera.unproject()方法仅在未调用setToOrtho时有效。

我判断这是缩放问题:移除camera.setToOrtho语句后,纹理能正确跟随鼠标,但添加该语句后,坐标比例似乎被放大了2、3甚至4倍。

相关代码片段

public class MyGdxGame extends ApplicationAdapter {

    private static final int TILESET_COLS = 26, TILESET_ROWS = 15, TILE_WIDTH = 32, TILE_HEIGHT = 32;

    private AssetManager assetManager;

    private TiledMap map;

    private Texture tileSheet;

    private OrthogonalTiledMapRenderer tilemapRenderer;

    // Camera
    private OrthographicCamera camera;

    private SpriteBatch batch;
    private BitmapFont font;

    // 瀑布动画
    private Animation<TextureRegion> waterFallAnimation;
    private List<Rectangle> waterFallRectangles = new LinkedList<Rectangle>();
    private float _waterFallStateTime = 0;

    @Override
    public void create() {
        batch = new SpriteBatch();

        // 资源管理器
        assetManager = new AssetManager();
        assetManager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
        assetManager.load("Map.tmx", TiledMap.class);

        // 加载32x32纹理图
        assetManager.setLoader(Texture.class, new TextureLoader(new InternalFileHandleResolver()));
        assetManager.load("Tiles/32x32.png", Texture.class);

        assetManager.finishLoading();

        map = assetManager.get("Map.tmx");
        tileSheet = assetManager.get("Tiles/32x32.png");

        // 设置场景相机
        camera = new OrthographicCamera();
        camera.setToOrtho(false);
        camera.update();

        // 渲染地图
        tilemapRenderer = new OrthogonalTiledMapRenderer(map);

        // 设置全屏模式
        Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());

        // 窗口可调整大小
        Gdx.graphics.setResizable(true);

        // 初始化瀑布动画
        TextureRegion[][] waterFallTmp = TextureRegion.split(tileSheet, TILE_WIDTH, TILE_HEIGHT);
        TextureRegion[] waterFallFrames = new TextureRegion[3];

        waterFallFrames[0] = waterFallTmp[10][14];
        waterFallFrames[1] = waterFallTmp[10][15];
        waterFallFrames[2] = waterFallTmp[10][16];

        waterFallAnimation = new Animation<TextureRegion>(0.150f, waterFallFrames);

        // 获取对象层组
        MapGroupLayer objectsGroupLayer = (MapGroupLayer) map.getLayers().get("ObjectsLayers");

        // 获取瀑布对象层
        MapLayer waterFallLayer = objectsGroupLayer.getLayers().get("Waterfall");

        // 获取瀑布对象层中的所有对象
        MapObjects waterFallObjects = waterFallLayer.getObjects();

        batch.begin();
        for (MapObject object : waterFallObjects) {
            // RectangleMapObject rectangleMapObject = (RectangleMapObject) object;
            // waterFallRectangles.add(rectangleMapObject.getRectangle());

            batch.draw(waterFallFrames[0], object.getProperties().get("x", Float.class),
                    object.getProperties().get("y", Float.class),
                    object.getProperties().get("width", Float.class),
                    object.getProperties().get("height", Float.class));
        }
        batch.end();
    }

    @Override
    public void render() {
        ScreenUtils.clear(0, 0, 0, 1);

        camera.update();
        // batch.setProjectionMatrix(camera.combined);

        tilemapRenderer.setView(camera);
        tilemapRenderer.render();

        // 处理瀑布动画
        _waterFallStateTime += Gdx.graphics.getDeltaTime();

        TextureRegion currentFrame = waterFallAnimation.getKeyFrame(_waterFallStateTime, true);

        // 鼠标位置
        Vector3 mousePosition = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
        Vector3 vc = camera.unproject(mousePosition);

        batch.begin();
        batch.draw(currentFrame, vc.x, vc.y);
        batch.end();

        // batch.begin();

        // for (Rectangle rectangle : waterFallRectangles)
        // batch.draw(currentFrame, rectangle.x / 4, rectangle.y / 3, rectangle.width /
        // 2, rectangle.height / 2);

        // batch.end();
    }

    /**
     * Application销毁时调用,调用前会先执行pause()
     * <p>
     * LibGDX推荐在此方法中释放资源
     * </p>
     */
    @Override
    public void dispose() {
        map.dispose();
        tilemapRenderer.dispose();

        batch.dispose();

        tileSheet.dispose();
    }
}

内容的提问来源于stack exchange,提问作者BREBION Mathis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:55:54