在LibGDX / Box2d中需要帮助缩放屏幕

时间:2018-01-06 22:05:20

标签: android libgdx box2d viewport scaling

我一直在使用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,顾名思义。任何和所有的帮助表示赞赏!

尝试添加backStage后:

    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);
}

1 个答案:

答案 0 :(得分:0)

引自Libgdx wiki

  

多个视口

     

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

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

使用多个阶段时:

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

<强> UPD 即可。几个笔记,与您的问题无关: