如何在LibGDX中实现世界单位与鼠标输入的匹配?
解决LibGDX中世界单位下鼠标输入与UI显示不匹配的问题
你当前的核心问题是直接混用屏幕像素坐标与世界单位坐标:Gdx.input.getX()/getY()返回的是屏幕像素坐标(原点在左上角),而UI绘制使用的是自定义世界单位,屏幕尺寸变化时两者映射关系混乱,必然导致输入偏移。以下是针对性的解决方法:
一、正确初始化Viewport与相机
Viewport是LibGDX处理屏幕适配和坐标映射的核心,必须将其与相机绑定,确保世界单位和屏幕像素的正确对应。推荐使用FitViewport(保持世界宽高比,黑边填充剩余空间),初始化示例:
@Override public void show() { // 初始化正交相机 camera = new OrthographicCamera(); // 绑定Viewport,传入世界宽高与相机 viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera); // 将相机原点居中(根据UI布局需求调整) camera.position.set(WORLD_WIDTH / 2f, WORLD_HEIGHT / 2f, 0); camera.update(); // 加载按钮纹理 playButtonActive = new Texture("play_active.png"); playButtonInactive = new Texture("play_inactive.png"); playButtonClicked = new Texture("play_clicked.png"); } // 屏幕尺寸变化时更新Viewport,维持映射关系 @Override public void resize(int width, int height) { viewport.update(width, height); }
二、将鼠标像素坐标转换为世界单位坐标
通过viewport.unproject()方法,将鼠标的屏幕像素坐标转换为世界单位坐标,该方法会自动处理Y轴原点差异(鼠标Y轴原点在左上角,世界坐标Y轴通常在左下角):
// 在render方法中执行坐标转换 Vector2 mouseWorldPos = new Vector2(Gdx.input.getX(), Gdx.input.getY()); viewport.unproject(mouseWorldPos); // 此时mouseWorldPos.x和mouseWorldPos.y就是世界单位下的鼠标位置
三、统一用世界单位处理UI绘制与输入判断
所有UI布局、输入判断都基于世界单位,彻底摒弃对屏幕像素值的依赖,示例代码:
@Override public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); game.batch.setProjectionMatrix(camera.combined); // 转换鼠标坐标到世界单位 Vector2 mouseWorldPos = new Vector2(Gdx.input.getX(), Gdx.input.getY()); viewport.unproject(mouseWorldPos); // 用世界单位定义按钮位置与尺寸 float buttonX = WORLD_WIDTH / 9f; float buttonY = WORLD_HEIGHT / 2f; float buttonWidth = playButtonActive.getWidth(); float buttonHeight = playButtonActive.getHeight(); // 判断鼠标是否在按钮范围内(世界单位) boolean isHover = mouseWorldPos.x > buttonX && mouseWorldPos.x < buttonX + buttonWidth && mouseWorldPos.y > buttonY && mouseWorldPos.y < buttonY + buttonHeight; game.batch.begin(); if (isHover) { game.batch.draw(playButtonInactive, buttonX, buttonY); if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) { game.batch.draw(playButtonClicked, buttonX, buttonY); game.setScreen(new GameScreen(game)); } } else { game.batch.draw(playButtonActive, buttonX, buttonY); } game.batch.end(); }
关键注意事项
- 全程统一使用世界单位:绘制、输入判断、布局定位都不要混用像素值,所有坐标转换交给Viewport处理。
- 必须重写
resize方法:屏幕尺寸变化时,viewport.update()是维持坐标映射正确的核心步骤。
内容的提问来源于stack exchange,提问作者Mehrbod Mehrabi
相关产品推荐
相关产品推荐

