我一直在使用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);
}
答案 0 :(得分:0)
引自Libgdx wiki:
多个视口
当使用具有不同屏幕尺寸的多个视口(或使用其他设置glViewport的代码)时,您需要在绘制之前应用视口,以便为该视口设置glViewport。
viewport1.apply(); // draw viewport2.apply(); // draw
使用多个阶段时:
stage1.getViewport().apply(); stage1.draw(); stage2.getViewport().apply(); stage2.draw();
<强> UPD 即可。几个笔记,与您的问题无关:
在资源上使用静态引用(例如代码中的AssetLoader.background
)通常被认为是一种不好的做法。例如,请阅读以下内容:https://stackoverflow.com/a/45901466/6836125,https://stackoverflow.com/a/44357810/6836125
SpriteBatches是重型对象,因此最好只有一个SpriteBatch
实例并分享它:
backStage = new Stage(backViewport, batch);