Using Dual Stages in libGDX for Android Game Development

In game screeens, it's common to have a static background alongside interactive elements and characters. A typical approach is to group background items into a Group for easier management. How ever, sometimes this design isn't foreseen initially, or the background involves more than a simple image, requiring blending between background and interactive actors across two stages.

Instead of rewriting code, note that both stages ultimately render via SpriteBatch. Implementing dual stages can be achieved by using separate cameras. Let's examine the Stage.draw() method:

/** Renders the stage */
public void draw () {
    camera.update();
    if (!root.visible) return;
    batch.setProjectionMatrix(camera.combined);
    batch.begin();
    root.draw(batch, 1);
    batch.end();
}

Both stages can share the same SpriteBatch. Instantiate the second stage using Stage(width, height, stretch, batch).

Example code:

package com.example.game;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;

public class MyGame implements ApplicationListener {

    Stage backgroundStage;
    Stage foregroundStage;
    float screenWidth;
    float screenHeight;

    @Override
    public void create() {
        screenWidth = Gdx.graphics.getWidth();
        screenHeight = Gdx.graphics.getHeight();
        backgroundStage = new Stage(screenWidth, screenHeight, true);
        foregroundStage = new Stage(screenWidth, screenHeight, true, backgroundStage.getSpriteBatch());

        Image bgImage = new Image(new TextureRegion(new Texture(Gdx.files.internal("sky.jpg")), 50, 50, 480, 320));
        backgroundStage.addActor(bgImage);

        Image character = new Image(new TextureRegion(new Texture(Gdx.files.internal("character.png")), 217, 157));
        character.x = (screenWidth - character.width) / 2;
        character.y = (screenHeight - character.height) / 2;
        foregroundStage.addActor(character);
    }

    @Override
    public void dispose() { }

    @Override
    public void pause() { }

    @Override
    public void render() {
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        backgroundStage.act(Gdx.graphics.getDeltaTime());
        foregroundStage.act(Gdx.graphics.getDeltaTime());
        backgroundStage.draw();
        foregroundStage.draw();
    }

    @Override
    public void resize(int width, int height) { }

    @Override
    public void resume() { }
}

Rendering order matters: the background stage must be drawn first, then foreground elements. Otherwise, the background will overlay the foreground.

For performance optimizaton, consider tuning the SpriteBatch buffer size.

Handling input across both stages cannot be done with simple assignments like:

Gdx.input.setInputProcessor(stage1);
Gdx.input.setInputProcessor(stage2);

Instead, use an InputMultiplexer:

InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(foregroundStage);
inputMultiplexer.addProcessor(backgroundStage);
Gdx.input.setInputProcessor(inputMultiplexer);

Tags: libgdx Android game development Stage dual stage

Posted on Sat, 10 Oct 2026 16:22:35 +0000 by jesushax