I have been fighting with placing two small viewports, the main one which uses the entire screen space, and a secondary with is just at top right (as the idea is to draw a FPS counter there)
The problem is that I can’t understand how exactly it works, I have been talking with the AI, and after some changes the viewports just work…. But I need to understand why my first implementation doesn’t work, as the AI answer is quite bad “Sometimes you just have to use manual viewport placing, because sometimes setScreenPosition may not work as expected”
The NOT working code:
public class TestViewportGame extends Game {
private SpriteBatch batch;
private OrthographicCamera mainCamera;
private OrthographicCamera smallCamera;
private Viewport mainViewport;
private Viewport smallViewport;
private ShapeDrawerHack shapeDrawerHack;
@Override
public void create() {
batch = new SpriteBatch();
// Main camera setup
mainCamera = new OrthographicCamera();
mainViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), mainCamera);
mainViewport.apply();
mainCamera.position.set(mainViewport.getWorldWidth() / 2, mainViewport.getWorldHeight() / 2, 0);
mainCamera.update();
// Small camera setup
smallCamera = new OrthographicCamera();
smallViewport = new FitViewport(200, 150, smallCamera);
smallViewport.setScreenPosition(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight() - 150);
smallViewport.apply();
smallCamera.position.set(smallViewport.getWorldWidth() / 2, smallViewport.getWorldHeight() / 2, 0);
smallCamera.update();
// Initialize ShapeDrawer
shapeDrawerHack = new ShapeDrawerHack(new ShapeDrawer(batch));
shapeDrawerHack.load();
}
@Override
public void render() {
ScreenUtils.clear(Color.BLACK);
// Render main scene
mainViewport.apply();
mainCamera.update();
batch.setProjectionMatrix(mainCamera.combined);
batch.begin();
// Draw main scene elements here
batch.end();
// Render small viewport
smallViewport.apply();
smallCamera.update();
batch.setProjectionMatrix(smallCamera.combined);
batch.begin();
shapeDrawerHack.getShapeDrawer().filledRectangle(0, 0, smallViewport.getWorldWidth(), smallViewport.getWorldHeight(), Color.RED);
batch.end();
}
@Override
public void resize(int width, int height) {
mainViewport.update(width, height);
smallViewport.update(width, height);
}
@Override
public void dispose() {
batch.dispose();
shapeDrawerHack.dispose();
}
}
The working code:
public class TestGame extends Game {
private SpriteBatch batch;
private OrthographicCamera mainCamera;
private OrthographicCamera smallCamera;
private Viewport mainViewport;
private Viewport smallViewport;
private ShapeDrawerHack shapeDrawerHack;
@Override
public void create() {
batch = new SpriteBatch();
// Main camera setup
mainCamera = new OrthographicCamera();
mainViewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), mainCamera);
mainViewport.apply();
mainCamera.position.set(mainViewport.getWorldWidth() / 2, mainViewport.getWorldHeight() / 2, 0);
mainCamera.update();
// Small camera setup
smallCamera = new OrthographicCamera();
smallViewport = new FitViewport(200, 150, smallCamera);
smallCamera.position.set(smallViewport.getWorldWidth() / 2, smallViewport.getWorldHeight() / 2, 0);
smallCamera.update();
// Initialize ShapeDrawer
shapeDrawerHack = new ShapeDrawerHack(new ShapeDrawer(batch));
shapeDrawerHack.load();
}
@Override
public void render() {
ScreenUtils.clear(Color.BLACK);
// Render main scene
mainViewport.apply();
mainCamera.update();
batch.setProjectionMatrix(mainCamera.combined);
batch.begin();
// Draw main scene elements here
batch.end();
// Render small viewport
Gdx.gl.glViewport(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight() - 150, 200, 150);
smallCamera.update();
batch.setProjectionMatrix(smallCamera.combined);
batch.begin();
shapeDrawerHack.getShapeDrawer().filledRectangle(0, 0, smallViewport.getWorldWidth(), smallViewport.getWorldHeight(), Color.RED);
batch.end();
// Reset viewport to main camera
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
@Override
public void resize(int width, int height) {
mainViewport.update(width, height);
smallViewport.update(width, height);
}
@Override
public void dispose() {
batch.dispose();
shapeDrawerHack.dispose();
}
}
Notice:
- The only difference is the use of manual viewport positioning, instead of using the viewPort apply method
- The only custom class is ShapeDrawerHack, which is just a wrapper around ShapeDrawer texture loading and disposal