【问题标题】:LibGDX How do I update Actor positions after resizing window?LibGDX 调整窗口大小后如何更新 Actor 位置?
【发布时间】:2019-07-20 23:32:32
【问题描述】:

我正在尝试将工具栏按钮粘贴到屏幕的右上角,但每当我调整窗口大小时,按钮都会保持在相同的绝对位置(相对于左下角)。

调整大小之前:

调整大小后:

这是生成UI按钮的方法(目前只在Screen的构造函数中调用):

private void generateUiToolbar(){
    // Toolbar Table
    Table table = new Table();
    table.setFillParent(true);
    table.top();
    table.right();

    // Menu button
    table.row();
    Texture myTexture = new Texture(Gdx.files.internal("ui/stamp.png"));
    TextureRegion myTextureRegion = new TextureRegion(myTexture);
    TextureRegionDrawable myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
    ImageButton menuButton = new ImageButton(myTexRegionDrawable);
    menuButton.addListener( new ClickListener() {
        @Override
        public void clicked(InputEvent event, float x, float y) {
            stage.clear();
            generateUiMenu();
        }
    });
    table.add(menuButton).size(60,60).padTop(10).padRight(10);

    stage.addActor(table);
}

这是 resize() 方法:

public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);
    stage.getCamera().viewportWidth = width;
    stage.getCamera().viewportHeight = height;
    stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
    stage.getCamera().update();
}

变量阶段在构造函数中以stage = new Stage();启动

出于某种原因,stage.getViewport().update(width, height, true); 没有做任何事情。当我在调整大小后打印stage.getWidth() 时,它将返回相同的数字。一般来说,更新按钮或演员位置的好方法是什么?简单地清除舞台并再次生成 UI 对我来说是行不通的,因为有时当您调整大小时,当前会显示不同的演员。如果我遗漏了任何信息,请告诉我。

编辑 1: 如答案中所述添加了table.setFillParent(true);,但这也没有解决。

编辑 2: 在阅读了答案和 cmets 之后,我删除了 stage.getCamera() 操作,但我仍然没有得到正确的结果。当我仅使用代码行 stage.getViewport().update(width, height, true); 调整大小时会发生这种情况:

【问题讨论】:

    标签: java user-interface libgdx position


    【解决方案1】:

    我认为您误解了 Viewport 的用法。 在您的调整大小方法中,您可以:

    stage.getViewport().update(width, height, true);
    stage.getCamera().viewportWidth = width;
    stage.getCamera().viewportHeight = height;
    stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
    stage.getCamera().update();
    

    但是stage.getViewport().update(width, height, true); 已经完成了你在接下来的四行中所做的事情。

    viewport.update(width, height) 为相机设置新的宽度和高度并更新相机。所以:

    viewport.update(width, height)
    
    is equal to
    
    camera.viewportWidth = width;
    camera.viewportHeight = height;
    camera.update();
    

    唯一的区别是视口的纵横比取决于您使用的视口。

    第三个参数:stage.getViewport().update(width, height, true); 是一个布尔值,表示相机是否居中。因此,如果第三个参数为 true,则视口将执行以下操作:

    camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
    

    在您的 resize 方法中,您会覆盖视口的工作,因为使用 viewport.update(width, height, true) 您已经完成了所有的调整大小,并且不需要其他四行。

    在 resize 方法中这就足够了:

    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }
    

    您可以阅读本文以更好地了解 Viewport:How Camera works in Libgdx and together with Viewport

    【讨论】:

    • 感谢您解决这个问题。你提到的一个区别可能是导致我结果好坏参半的原因。但是这两个选项都没有解决我的问题,所以这还不是解决方案。 stage.getViewport().update(width, height, true); 使按钮粘在右上角,但它会随着屏幕延伸(检查问题,我将为此添加屏幕截图)。相机操作解决方案使它不会拉伸,但也不会粘在右上角。它与我添加的屏幕截图一样位于同一位置。
    • 是因为我没有使用正确的视口吗​​?启动阶段时我没有指定视口。这意味着它会自动使用 ScalingViewport。使用 ExtendViewport 也不起作用。你知道我应该使用什么视口吗?
    • @Tipsi 要注意纵横比,您应该使用 FitViewport 或 ExtendViewport。通过 FitViewport 或 ExtendViewport,您必须定义世界宽度和世界高度。这将帮助您了解什么是世界单位:stackoverflow.com/questions/51993577/libgdxs-world-units/…
    • @Tipsi FitViewport 会将 BlackBars 添加到侧面。如果屏幕尺寸与纵横比不匹配,那么您的游戏将适合较长的一面。 ExtendViewport 正好相反,适合较短的一侧。你不会有黑条,但如果纵横比与声明的不同,你会看到更少的世界
    • 啊,ExtendViewport 确实有效。我猜它以前没有用,因为我使用了相机操作方法而不是viewport.update()。但是,现在菜单按钮在调整大小时不会保持相同的大小,这正是我想要的。但我想你的回答确实解决了我的问题。
    【解决方案2】:

    Viewport 对象是一个相机平截头体管理器。当您开始修改相机的参数(位置除外)时,您正在撤消调用viewport.update() 所做的操作。

    如果您希望表格自动填满屏幕,以便在调整大小后右上角的内容保持不变,请不要在表格上设置宽度和高度。相反,请调用table.setFillParent(true),以便它会自动更新其大小以匹配视口大小。

    【讨论】:

    • 感谢您的解释。所以你是说我应该删除viewport.update()?或者我应该做一些不同的事情。相机的变化就在那里,所以当我开始调整大小时,演员不会开始伸展。当我做table.setFillParent(true) 时,它也不会在调整大小时自动更新......我错过了什么吗?我认为这是因为视口没有更新?
    • 通常您会使用与您想要的行为相匹配的视口(IMO 在 95% 的情况下应该是 ExtendViewport),或者编写自定义视口类并从那里管理您的相机尺寸。由于您的相机操作,表格可能无法正确调整大小,但还要确保删除 setSize() 调用。
    • 是的,我删除了setSize()。不过,我需要在前面提到的原因为你操作相机。明天早上我再次使用 PC 时,我将尝试使用 ExtendViewport,看看是否有任何改变。
    • ExtendViewport 没有改变任何东西,很遗憾。有没有办法操纵相机并将视口更新为屏幕的大小?
    • 您可以操作相机视口,但正确的操作位置是在 Viewport 的子类中。但是,如果还没有可以满足您需要的视口,我会感到惊讶。如果它没有做任何事情,那么您可能错过了删除在某处修改 camera.viewportWidth 或 Height 的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    相关资源
    最近更新 更多