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

LibGDX camera.project()异常:Box2D物体上方Label位置偏移

Box2D物体坐标转屏幕坐标显示Label位置偏移问题

我用Box2D管理游戏世界,想在物体(body)上方显示文本,打算用Label实现。但物体在游戏世界中,Label在Stage(UI层),所以尝试用camera.project()方法把世界坐标转成屏幕坐标。不过Label显示位置有偏移,相对目标位置向左下方偏,调整窗口大小后位置还是不对。另外我用相同方式调用camera.unproject()一切正常,搞不懂反向转换没问题,正向就出问题。

代码如下:

this.camera = new OrthographicCamera(ScreenManager.WIDTH * SCALE, ScreenManager.HEIGHT * SCALE);
this.viewport = new FitViewport(ScreenManager.WIDTH, ScreenManager.HEIGHT);
this.stage = new Stage(viewport, batch);
this.world = new World(Vector2.Zero, true);

// ...

Vector3 worldPosition = new Vector3(x, y, 0);
Vector3 screenPosition = camera.project(worldPosition,
    viewport.getScreenX(), viewport.getScreenY(),
    viewport.getScreenWidth(), viewport.getScreenHeight());

label.setPosition(screenPosition.x, screenPosition.y);

resize方法:

@Override
public void resize(int width, int height) {
    viewport.update(width, height, true);
}

我已经在render方法里调用了Stage的act()和draw()方法,请问哪里出错了?


解决方案
  • 修正坐标转换的视口参数使用
    你当前直接用camera.project()传入视口的屏幕参数,但你的Stage已经绑定了FitViewport,而相机的初始化尺寸是ScreenManager.WIDTH * SCALE,这会导致坐标转换时的缩放比例不匹配。正确的做法是直接使用视口的相机来做投影,或者确保投影时的参数和视口的实际变换一致。

替换坐标转换代码为:

Vector3 worldPosition = new Vector3(x, y, 0);
// 直接使用stage的视口相机进行投影,无需手动传入视口参数
viewport.getCamera().project(worldPosition);
// 或者如果坚持用自己的camera,要确保和视口同步
// camera.project(worldPosition, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

label.setPosition(worldPosition.x, worldPosition.y);
  • 调整Label的锚点(Alignment)
    Label默认的锚点是左上角(0,0),而你转换后的坐标是物体的世界坐标点,直接设置位置会导致Label的左上角对齐物体位置,看起来就会向左下方偏移。需要把Label的锚点设为中心或者底部中心,让Label的对应位置对齐物体上方:
// 初始化Label时设置对齐方式
Label.LabelStyle style = new Label.LabelStyle(font, Color.WHITE);
label = new Label("文本内容", style);
// 设置锚点为底部中心,这样Label的底部中心会对齐转换后的坐标
label.setAlignment(Align.center);
label.setPosition(screenPosition.x - label.getWidth()/2, screenPosition.y);
// 或者使用setCenter方法更方便
label.setCenter(screenPosition.x, screenPosition.y);
  • 确保相机和视口同步
    在resize方法中,除了更新视口,还要确保相机的位置和视口保持一致,或者直接使用视口的相机来管理游戏世界:
@Override
public void resize(int width, int height) {
    viewport.update(width, height, true);
    // 如果使用自定义camera,需要同步视口的投影矩阵
    camera.setToOrtho(false, viewport.getWorldWidth(), viewport.getWorldHeight());
    camera.update();
}

另外,unproject正常是因为反向转换时,屏幕坐标的原点和Stage的坐标系统匹配,但正向转换时因为相机缩放和Label锚点的双重问题导致偏移。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:33:37