LibGDX如何获取世界坐标系下的鼠标坐标?解决Y轴翻转问题
问题根源
你之前手动翻转Y轴不生效的核心原因是取值错误:Toolkit.getDefaultToolkit().getScreenSize().height获取的是物理显示器的总高度,但Gdx.input.getY()返回的是游戏窗口渲染区域的相对坐标(原点在窗口左上角,Y轴向下),当窗口非全屏、存在标题栏、系统开启窗口缩放时,物理屏幕高度和窗口渲染区高度完全不匹配,计算结果自然错误。
另外注意:LibGDX自带的camera.unproject()、Viewport.unproject()方法本身已经内置了Y轴翻转逻辑,要求输入的就是Gdx.input返回的原生窗口坐标,不需要提前手动做Y值翻转,提前翻转再传入会导致两次翻转,结果完全颠倒。
正确实现方案
标准写法(推荐)
LibGDX项目中相机一般都会绑定Viewport做分辨率适配,直接调用视口的unproject方法即可自动处理Y轴翻转、视口黑边偏移等所有逻辑,不需要额外计算:
// 声明为类成员,避免每帧创建新对象 private final Vector3 tmpVec = new Vector3(); // 假设你已经初始化了绑定orthographicCamera的Viewport实例,比如fitViewport、extendViewport等 public Vector2 getWorldPositionFromScreen(float screenX, float screenY){ tmpVec.set(screenX, screenY, 0); gameViewport.unproject(tmpVec); return new Vector2(tmpVec.x, tmpVec.y); }
调用时直接传入输入的原生坐标即可:
// 调用示例 Vector2 worldPos = getWorldPositionFromScreen(Gdx.input.getX(), Gdx.input.getY());
无Viewport的裸相机写法
如果你没有使用Viewport,直接操作OrthographicCamera,不需要额外手动计算Y值翻转,直接传入原生输入坐标即可:
private final Vector3 tmpVec = new Vector3(); public Vector2 getWorldPositionFromScreen(float screenX, float screenY){ tmpVec.set(screenX, screenY, 0); orthographicCamera.unproject(tmpVec); return new Vector2(tmpVec.x, tmpVec.y); }
如果上述写法仍然存在Y翻转,检查相机初始化参数:如果你调用setToOrtho()时传入了yDown=true,会把世界坐标Y轴设置为向下,和屏幕坐标方向一致,此时需要把相机up参数改回默认Y向上:
// 正确的正交相机初始化(Y轴向上,和LibGDX默认渲染逻辑一致) orthographicCamera.setToOrtho(false, worldWidth, worldHeight);
排查注意点
- 窗口尺寸相关的取值全部从
Gdx.graphics接口获取,不要用Java AWT、Swing相关的API,这类API不兼容LibGDX跨平台特性,取值也不符合游戏窗口的实际渲染范围。 - 窗口大小改变时要同步更新相机/视口参数:桌面端拖拽窗口改变尺寸时,需要调用
viewport.update(width, height)或者更新相机的viewport宽高后调用camera.update(),否则投影矩阵计算错误会导致坐标转换偏差。 - 不要重复做Y轴翻转:
unproject系列方法已经处理了屏幕坐标到世界坐标的Y轴方向转换,提前手动计算height - y再传入会导致方向错误。

内容的提问来源于stack exchange,提问作者user19296869
相关产品推荐
相关产品推荐

