0
\$\begingroup\$

this question is for LibGdx geeks. I want to make transparent screen in my game. For example, when level completes I want a new transparent screen pop up and show player's high score, buttons to navigate on next level etc like in angry birds kind of screen.

This type of screen can also use, when user click on pause button, to show pause screen. Please guide me to design this kind of screen.

Or if I am going wrong to make transparent screens for this kind of situation. Please guide me for better one.

\$\endgroup\$
1
  • \$\begingroup\$ Check scene2d ui. I would add a stage for the ui. Add a table to your stage and when the game is finished (or the player hits pause) you can call table.setVisible(true) . \$\endgroup\$ Commented Jun 1, 2014 at 23:47

3 Answers 3

3
\$\begingroup\$

I use a screen stack system to handle this kind of thing. Think of your screens as objects containing individual update and render logic that can be stacked on top of each other. These screens are then updated top -> bottom so that the most recent screen always has control. They are rendered bottom -> top so that overlays (pause screens/transparent screens as you say) and other effects can be implemented.

I do this using two classes:

ScreenService.java (handles individual screen objects):

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Disposable;
import org.jetbrains.annotations.NotNull;

import java.util.Stack;

/**
 * The screen service class.
 */
public class ScreenService implements Disposable {
    private final Stack<Screen> screenStack;

    /**
     * Constructs a ScreenService instance.
     */
    public ScreenService() {
        screenStack = new Stack<>();
    }

    /**
     * Adds the specified screen to the service.
     *
     * @param screen
     *         The screen.
     */
    public void add(@NotNull final Screen screen) {
        screen.create();
        screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        screenStack.push(screen);
    }

    /** Releases all resources of this object. */
    @Override public void dispose() {
        for(Screen screen : screenStack) {
            if(screen == null) continue;
            screen.dispose();
        }
        screenStack.clear();
    }

    /**
     * Draws all screens in the service.
     */
    public void draw() {
        for(Screen screen : screenStack) {
            if(screen == null) continue;
            screen.draw();
        }
    }

    /**
     * Pauses all screens in the service.
     */
    public void pause() {
        for(Screen screen : screenStack) {
            if(screen == null) continue;
            screen.pause();
        }
    }

    /**
     * Called when the game window is resized.
     *
     * @param width
     *         The new game window width (in pixels).
     * @param height
     *         The new game window height (in pixels).
     */
    public void resize(final int width, final int height) {
        for(Screen screen : screenStack) {
            if(screen == null) continue;
            screen.resize(width, height);
        }
    }

    /**
     * Resumes all screens in the service.
     */
    public void resume() {
        for(Screen screen : screenStack) {
            if(screen == null) continue;
            screen.resume();
        }
    }

    /**
     * Updates the screen service.
     *
     * @param tt
     *         The total amount of time, in seconds, since the game started.
     * @param dt
     *         The total amount of time, in seconds, since the last update.
     */
    public void update(final float tt, final float dt) {
        boolean coveredByOtherScreen = false;
        for(int i = screenStack.size() - 1; i >= 0; i--) {
            Screen screen = screenStack.get(i);
            if(screen == null) {
                screenStack.remove(i);
                continue;
            }
            screen.update(tt, dt);
            if(coveredByOtherScreen) remove(screen);
            if(!screen.isOverlay()) coveredByOtherScreen = true;
        }
    }

    /**
     * Removes the specified screen from the service.
     *
     * @param screen
     *         The screen.
     */
    private void remove(@NotNull final Screen screen) {
        screen.dispose();
        screenStack.remove(screen);
    }
}

Screen.java (implements individual screen logic):

import com.badlogic.gdx.utils.Disposable;
import com.spacehorde.util.GameServices;
import org.jetbrains.annotations.NotNull;

/**
 * An abstract screen class.
 */
public abstract class Screen implements Disposable {
    private final GameServices gameServices;

    /**
     * Constructs a Screen instance.
     */
    protected Screen(@NotNull final GameServices gameServices) {
        this.gameServices = gameServices;
    }

    /**
     * Called when the screen is created.  Used for initialization.
     */
    protected void create() { }

    /**
     * Draws the screen.
     */
    protected abstract void draw();

    /**
     * Gets the game services.
     *
     * @return The game services.
     */
    protected GameServices getGameServices() {
        return gameServices;
    }

    /**
     * Determines if the screen is an overlay or not.  Overlays will not cause screens below it to automatically exit.
     *
     * @return {@code true} if the screen is an overlay; otherwise, {@code false}.
     */
    protected abstract boolean isOverlay();

    /**
     * Pauses the screen.
     */
    protected void pause() { }

    /**
     * Called when the screen is resized.
     *
     * @param width
     *         The new game window width (in pixels).
     * @param height
     *         The new game window height (in pixels).
     */
    protected void resize(final int width, final int height) { }

    /**
     * Resumes the screen after a pause.
     */
    protected void resume() { }

    /**
     * Updates the screen.
     *
     * @param tt
     *         The total amount of time, in seconds, since the game started.
     * @param dt
     *         The total amount of time, in seconds, since the last update.
     */
    protected abstract void update(final float tt, final float dt);
}
\$\endgroup\$
0
\$\begingroup\$

In the same situation, I've used an ad-hoc game state interface encased in a Screen subclass. This approach is somewhat Lispy in that GameState objects are very small inner classes using a lot of outer class stuff.

    // This is all inside a Screen implementation...

    interface GameState {
            void draw();
            void update(float delta);
    }

    GameState state;

    // And the four states for this example tetris:

    class PausedState implements GameState {
            GameState returnState;
            public PausedState(GameState returnState){
                    this.returnState = returnState;
            }

            public void draw(){
                    returnState.draw();

                    // Draw an overlay...
                    batch.draw(pause_sprite, 0, 0);
            }

            public void update(float delta){
                    // Note 'touched' and 'state' are outer class stuff.
                    if(touched(Assets.pauseResume)){
                            state = returnState;
                    }

                    // et cetera
            }
    }

    class GameOverState implements GameState {
            // Elided, much of the same as PauseState
    }

    class PieceState implements GameState {
            boolean[][] piece = popPiece();

            // et cetera, much of the gameplay is in here
    }

    class ClearingState implements GameState {
            // animated row removal...
    }

    @Override
    public void render(float delta) {
            // set up common drawing stuff....

            state.draw();
            state.update(delta);

            // and tear down drawing stuff.
    }

The intended virtues of this approach are that there is never any "nonsense" state and there is also very little code here versus typical approaches. (The "final" product contains most of the game in this file and it's under 500 lines.) For a very complex game, you might want something designed to split across classes more elegantly (e.g. deadpixelsociety's approach).

\$\endgroup\$
0
\$\begingroup\$

Just make a panel and add component such as label to that panel. Then, show this panel on the top! In other words, draw this panel last. (Thank you @Heckel!)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .