【问题标题】:Need help scaling screen in LibGDX/Box2d需要帮助在 LibGDX/Box2d 中缩放屏幕
【发布时间】:2018-01-06 22:05:20
【问题描述】:

我一直在使用 libGDX 框架为 android/desktop 创建一个简单的游戏。快要完成了,但我很难让它适应不同的屏幕比例。我目前正在使用 FitViewport,它可以很好地保持我想要的屏幕比例,但我想让它使顶部和底部的黑条分别为天空和地面着色。我也尝试过完全不使用视口,然后使用 ShapeRenderer 添加颜色,但它只是拉伸了所有艺术以适应屏幕,不使用我想要的屏幕比例,并且忽略了 ShapeRenderer 形状。

这是我的 GameRenderer 类的构造函数代码:

public GameRenderer (GameWorld gameWorld) {
    this.gameWorld = gameWorld;

    camera = new OrthographicCamera();
    camera.setToOrtho(false, V_WIDTH / PPM, V_HEIGHT / PPM);

    uiCamera = new OrthographicCamera();
    uiCamera.setToOrtho(false, V_WIDTH, V_HEIGHT);

    batch = new SpriteBatch();
    batch.setProjectionMatrix(camera.combined);

    viewport = new FitViewport(V_WIDTH / PPM, V_HEIGHT / PPM, camera);
    viewport.apply();

    shapeRenderer = new ShapeRenderer();
    shapeRenderer.setProjectionMatrix(camera.combined);

    debugRenderer = new Box2DDebugRenderer();
    frog = gameWorld.getFrog();
    jumpRope = gameWorld.getJumpRope();

    score = gameWorld.getScore() + "";
    highScore = AssetLoader.getHighScore() + "";
}

这里是 render() 方法:

    public void render () {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    score = gameWorld.getScore() + "";
    highScore = AssetLoader.getHighScore() + "";

    batch.begin();
    batch.draw(AssetLoader.background, 0, 0, 236 / PPM, 300 / PPM);

    batch.setProjectionMatrix(uiCamera.combined);
    if (gameWorld.isReady() || gameWorld.isTitleScreen() ) {
        AssetLoader.shadow.getData().setScale(0.4f, 0.4f);
        AssetLoader.shadow.draw(batch, "Tap to start!", 23, V_HEIGHT - 60);

        AssetLoader.font.getData().setScale(0.4f, 0.4f);
        AssetLoader.font.draw(batch, "Tap to start!", 22, V_HEIGHT - 61);
    } else {
        if (gameWorld.isGameOver()) {
            AssetLoader.shadow.getData().setScale(0.4f, 0.4f);
            AssetLoader.shadow.draw(batch, "Game Over", 40, V_HEIGHT - 60);

            AssetLoader.font.getData().setScale(0.4f, 0.4f);
            AssetLoader.font.draw(batch, "Game Over", 39, V_HEIGHT - 61);

            AssetLoader.shadow.draw(batch, "High Score: " + highScore, 15, V_HEIGHT - 90);
            AssetLoader.font.draw(batch, "High Score: " + highScore, 14, V_HEIGHT - 91);
        } else {
            AssetLoader.shadow.getData().setScale(0.55f, 0.55f);
            AssetLoader.shadow.draw(batch, score, (V_WIDTH / 2) - (8 * score.length()), V_HEIGHT / 1.25f);

            AssetLoader.font.getData().setScale(0.55f, 0.55f);
            AssetLoader.font.draw(batch, score, (V_WIDTH / 2) - (8 * score.length()) - 1, V_HEIGHT / 1.25f - 1);
        }
    }

    batch.setProjectionMatrix(camera.combined);

    if (jumpRope.getJumpRopeBehindFrog()) {
        jumpRope.draw(batch);
    }

    if (gameWorld.getFrog().getY() > -60 / PPM) {
        frog.draw(batch);
    }

    if (!jumpRope.getJumpRopeBehindFrog()) {
        jumpRope.draw(batch);
    }

    batch.end();

    debugRenderer.render(gameWorld.getWorld(), camera.combined);

    gameWorld.getWorld().step(1/60f, 6, 2);
}

顾名思义,我将主 OrthographicCamera 相机用于我的所有游戏和 Box2D 内容,并将 uiCamera 用于所有 UI。感谢您提供任何和所有帮助!

尝试添加后台后:

    public GameRenderer (GameWorld gameWorld) {
    this.gameWorld = gameWorld;

    camera = new OrthographicCamera();
    camera.setToOrtho(false, V_WIDTH / PPM, V_HEIGHT / PPM);

    uiCamera = new OrthographicCamera();
    uiCamera.setToOrtho(false, V_WIDTH, V_HEIGHT);

    batch = new SpriteBatch();
    batch.setProjectionMatrix(camera.combined);

    // Test code
    backViewport = new ExtendViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

    backStage = new Stage();
    backStage.setViewport(backViewport);
    //

    viewport = new FitViewport(V_WIDTH / PPM, V_HEIGHT / PPM, camera);
    viewport.apply();

    shapeRenderer = new ShapeRenderer();
    shapeRenderer.setProjectionMatrix(camera.combined);

    debugRenderer = new Box2DDebugRenderer();
    frog = gameWorld.getFrog();
    jumpRope = gameWorld.getJumpRope();

    score = gameWorld.getScore() + "";
    highScore = AssetLoader.getHighScore() + "";

    // Test code
    backStage.addActor(new Image(AssetLoader.backgroundColor));
}

public void render () {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    score = gameWorld.getScore() + "";
    highScore = AssetLoader.getHighScore() + "";

    batch.begin();
    batch.draw(AssetLoader.background, 0, 0, 236 / PPM, 300 / PPM);

    batch.setProjectionMatrix(uiCamera.combined);
    if (gameWorld.isReady() || gameWorld.isTitleScreen() ) {
        AssetLoader.shadow.getData().setScale(0.4f, 0.4f);
        AssetLoader.shadow.draw(batch, "Tap to start!", 23, V_HEIGHT - 60);

        AssetLoader.font.getData().setScale(0.4f, 0.4f);
        AssetLoader.font.draw(batch, "Tap to start!", 22, V_HEIGHT - 61);
    } else {
        if (gameWorld.isGameOver()) {
            AssetLoader.shadow.getData().setScale(0.4f, 0.4f);
            AssetLoader.shadow.draw(batch, "Game Over", 40, V_HEIGHT - 60);

            AssetLoader.font.getData().setScale(0.4f, 0.4f);
            AssetLoader.font.draw(batch, "Game Over", 39, V_HEIGHT - 61);

            AssetLoader.shadow.draw(batch, "High Score: " + highScore, 15, V_HEIGHT - 90);
            AssetLoader.font.draw(batch, "High Score: " + highScore, 14, V_HEIGHT - 91);
        } else {
            AssetLoader.shadow.getData().setScale(0.55f, 0.55f);
            AssetLoader.shadow.draw(batch, score, (V_WIDTH / 2) - (8 * score.length()), V_HEIGHT / 1.25f);

            AssetLoader.font.getData().setScale(0.55f, 0.55f);
            AssetLoader.font.draw(batch, score, (V_WIDTH / 2) - (8 * score.length()) - 1, V_HEIGHT / 1.25f - 1);
        }
    }

    batch.setProjectionMatrix(camera.combined);

    if (jumpRope.getJumpRopeBehindFrog()) {
        jumpRope.draw(batch);
    }

    if (gameWorld.getFrog().getY() > -60 / PPM) {
        frog.draw(batch);
    }

    if (!jumpRope.getJumpRopeBehindFrog()) {
        jumpRope.draw(batch);
    }

    batch.end();

    // I put this in front of everything so that I could see what it's doing
    backStage.act();
    backStage.draw();
    //

    debugRenderer.render(gameWorld.getWorld(), camera.combined);

    gameWorld.getWorld().step(1/60f, 6, 2);
}

public void resize (int width, int height) {
    backViewport.update(width, height);
    viewport.update(width, height);
}

【问题讨论】:

  • 我相信this 可能会有所帮助。
  • 不,我在后台添加了我想要的内容到后台,但它不会超过主 FitViewport,也不会缩放到适当的大小,即使我使用 Gdx.graphics 也是如此。获取宽度()/获取高度()
  • 我明白了。您是否像建议的问题一样为backStage 使用单独的ExtendViewport
  • 是的!绝对有可能是我搞砸了,如果您认为有帮助,我可以编辑我的帖子以显示我添加的内容。

标签: android libgdx box2d viewport scaling


【解决方案1】:

引用Libgdx wiki:

多个视口

当使用具有不同屏幕尺寸的多个视口时(或者您使用设置 glViewport 的其他代码),您需要在绘制之前应用视口,以便为该视口设置 glViewport。

viewport1.apply();
// draw
viewport2.apply();
// draw

当使用多个阶段时:

stage1.getViewport().apply();
stage1.draw();
stage2.getViewport().apply();
stage2.draw();

更新。与您的问题无关的几点说明:

【讨论】:

  • 这正是我所需要的!非常感谢!我最终只是完全删除了backStage 并改用ShapeRenderer,因为我只想要颜色而不是TextureRegion。无论哪种方式,在绘图之前应用正确的Viewport 正是我所需要的。
  • 另外,感谢您的注释,我决定让我的 AssetLoader 不是静态的,而是从主类传递它。我需要注意的是那些较小的事情!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多