Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Libgdx sliding pause menu

So in my Gameplay screen user has posibillity to click on menu button and then that menu button will pause the game and show the menu.

I tried to impelement menu as a new stage, but that just opens a new screen, sets the graphics of the menu like I want to and leaves the rest of the screen black.

Here's the image so you can see what I'm talking about:

Image

I want this green part to smoothly slide into Gameplay scene and I wan't to get rid of this black part of the screen and instead leave that part transparent (I want it to show only the green part of a Image).

Tried to find some good tutorials about pause menus, but no luck.

Here's the code of my pause screen:

public class Menu implements Screen{

    Stage menuStage = null;
    private Image menu_bg = null;

    private Main game = null;

    public Menu(Main gm){
        game = gm;
    }



    @Override
    public void show() {
        menuStage = new Stage(new StretchViewport(1920, 1080));
        Gdx.input.setInputProcessor(menuStage);
        menu_bg = new Image(new Texture(Gdx.files.internal("menuProba.png")));
        menuStage.addActor(menu_bg);

        menuButtons();
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        menuStage.draw();
        menuStage.act();
    }

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

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {

    }


    private void menuButtons(){
        Table menuButtons = new Table();
        menuButtons.setFillParent(true);

        final Image resumeGame = new Image(new Texture(Gdx.files.internal("playbutton.png")));
        final Image retryGame = new Image(new Texture(Gdx.files.internal("retrybutton.png")));
        final Image homeButton = new Image(new Texture(Gdx.files.internal("homebutton.png")));
        final Image exitButton = new Image(new Texture(Gdx.files.internal("exitbutton.png")));

        resumeGame.addListener(new InputListener() {
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
                resumeGame.addAction(Actions.scaleTo(1, 1.1f,.1f));
                return true;
            }

            public void touchUp (InputEvent event, float x, float y, int pointer, int button){
                resumeGame.addAction(Actions.scaleTo(1, 1,.1f));
            }
        });


        retryGame.addListener(new InputListener() {
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
                retryGame.addAction(Actions.scaleTo(1, 1.1f,.1f));
                return true;
            }

            public void touchUp (InputEvent event, float x, float y, int pointer, int button){
                retryGame.addAction(Actions.scaleTo(1, 1,.1f));
            }
        });


        homeButton.addListener(new InputListener() {
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
                homeButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
                return true;
            }

            public void touchUp (InputEvent event, float x, float y, int pointer, int button){
                homeButton.addAction(Actions.scaleTo(1, 1,.1f));
                game.setScreen(new MainMenu(game));
            }
        });


        exitButton.addListener(new InputListener() {
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
                exitButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
                return true;
            }

            public void touchUp (InputEvent event, float x, float y, int pointer, int button){
                exitButton.addAction(Actions.scaleTo(1, 1,.1f));
            }
        });


        /*HorizontalGroup horizontalGroup = new HorizontalGroup();
        horizontalGroup.addActor(resumeGame);
        horizontalGroup.addActor(retryGame);
        horizontalGroup.addActor(homeButton);
        horizontalGroup.addActor(exitButton);
        menuButtons.add(horizontalGroup);*/
        menuButtons.add(resumeGame).expand().left().padLeft(40);
        menuButtons.row();
        menuButtons.add(retryGame).expand().left().padLeft(40);
        menuButtons.row();
        menuButtons.add(homeButton).expand().left().padLeft(40);
        menuButtons.row();
        menuButtons.add(exitButton).expand().left().padLeft(40);
        menuStage.addActor(menuButtons);
    }


}

And the Gameplay screen:

public class GameScreen implements Screen, InputProcessor {

    boolean menuScreen;
    private Texture menuImage = null;

    public boolean buttonMenuTouched = false;
    public InputMultiplexer multiplexer = null;
    BitmapFont font;


    //SCORE-------------------------------------
    private SpriteBatch batch = null;
    private OrthographicCamera mCamera = null;
    private BitmapFont scoreFont = null;
    private int score = 0;
    //--------------------------------------------

    Main game = null;
    public Texture font_texture;

    public GameScreen(Main gm){
        game = gm;
    }

    Stage gameStage = null;
    private Image game_bg = null, menu_bg = null;

    private GameManager manager = null;

    @Override
    public void show() {

        mCamera = new OrthographicCamera(1920, 1080);
        font_texture = new Texture(Gdx.files.internal("font.png"));
        font_texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
        scoreFont = new BitmapFont(Gdx.files.internal("font.fnt"), new TextureRegion(font_texture), false);
        batch = new SpriteBatch();

        multiplexer = new InputMultiplexer();



        gameStage = new Stage(new StretchViewport(1920, 1080));
        multiplexer.addProcessor(this);
        multiplexer.addProcessor(gameStage);
        Gdx.input.setInputProcessor(multiplexer);

        game_bg = new Image(new Texture(Gdx.files.internal("pozadinaGameScreen.png")));
        gameStage.addActor(game_bg);

        menuImage = new Texture("menuProba.png");

        manager = new GameManager(game, this, gameStage);
        manager.createPlayer();
        manager.createBlueMonster();
        manager.createHUDButtons();
        manager.createGameOverStage();

        gameScreenButtoni();

    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        gameStage.draw();
        gameStage.act();

        manager.checkButtons();
        manager.checkCollisions();

        batch.setProjectionMatrix(mCamera.combined);
        batch.begin();
        this.scoreFont.draw(batch, ""+manager.score, Gdx.graphics.getWidth() - 1070, Gdx.graphics.getHeight() - 580);



        batch.end();


        if (manager.gameOver == true){
            manager.gameOverStage.draw();
            manager.gameOverStage.act();

            Gdx.input.setInputProcessor(manager.gameOverStage);
        }
    }

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

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {
        manager.gameOverStage.dispose();
        gameStage.dispose();
        manager.dispose();
        game.setScreen(game.mainMenu);
    }



    // METODE INPUT PROCESORA

    @Override
    public boolean keyDown(int keycode) {
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        manager.shootBullet();
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        return false;
    }


    public void gameScreenButtoni(){

        //menuImage = new Image(new Texture(Gdx.files.internal("menuProba.png")));
        Table buttoni = new Table();
        buttoni.setFillParent(true);

        final Image menuButton = new Image(new Texture(Gdx.files.internal("menubutton.png")));
        menuButton.addListener(new InputListener(){
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
                menuButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
                buttonMenuTouched = true;
                return true;
            }

            public void touchUp (InputEvent event, float x, float y, int pointer, int button){
                menuButton.addAction(Actions.scaleTo(1, 1,.1f));
                buttonMenuTouched = false;
                game.setScreen(new Menu(game));



            }
        });

        final Image scoreText = new Image(new Texture(Gdx.files.internal("score.png")));


        buttoni.add(menuButton).expand().top().left().padLeft(20).padTop(20);
        buttoni.add(scoreText).expand().top().right().padTop(30).padRight(140);
        gameStage.addActor(buttoni);
    }

    public void menuScreen(){
        Stage menu = new Stage(new StretchViewport(400,400));
        menu_bg = new Image(new Texture(Gdx.files.internal("logoMali.png")));
        menu.addActor(menu_bg);
    }
}

I know that I'm doing this wrong, but how should I do it? Draw a rectangle when button is pressed or what?

like image 290
DaxHR Avatar asked Jan 07 '23 03:01

DaxHR


1 Answers

In my game I make NavigationDrawer in libgdx as you can see:

enter image description here


You can make this with sample code, just follow a few steps:

1- Copy NavigationDrawer class into your project:

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;

/**
 * Created by Crowni on 10/6/2015.
 */
public class NavigationDrawer {
    // this value is suitable
    private static final float INTERVAL_SEC = 0.001f;

    // Some attributes for {@link NavigationDrawer}
    private static float CAM_MAIN_POSITION;
    public static float WIDTH;
    public static float SPEED;

    private static OrthographicCamera camera;

    /**
     * To ensure the {@link NavigationDrawerListener#onFinish()} called one time
     **/
    private static boolean isFinish = true;

    private static Task task;
    private static Timer timer = new Timer();

    private static NavigationDrawerListener listener;

    public interface NavigationDrawerListener {
        public void onStart();

        // May be you want to make some Actions here during sliding
        public void onRun();

        public void onFinish(float camX);
    }

    public static void initialize(Stage stage, NavigationDrawerListener listener) {
        NavigationDrawer.listener = listener;
        camera = ((OrthographicCamera) stage.getCamera());
        setNavigationDrawerDefault(stage);
        initializeTimerTask(false);
    }

    private static void setNavigationDrawerDefault(Stage stage) {
        WIDTH = stage.getWidth() - stage.getWidth() / 3;
        CAM_MAIN_POSITION = stage.getWidth() / 2;
        SPEED = 2f;
    }

    private static Task initializeTimerTask(boolean show) {
        task = new Task() {
            public void run() {
                if (!timer.isEmpty()) {
                    if (show)
                        camera.position.x -= SPEED;
                    else
                        camera.position.x += SPEED;

                    listener.onRun();
                } else if (isFinish) {
                    listener.onFinish(setDefaultCameraEndPostion(show));
                }
            }
        };
        return task;
    }

    /**
     * @param show
     *            : I passed it here because I know it is correct choice
     **/
    private static float setDefaultCameraEndPostion(boolean show) {
        isFinish = false;
        if (show)
            return camera.position.x = CAM_MAIN_POSITION - WIDTH;
        else
            return camera.position.x = CAM_MAIN_POSITION;
    }

    private static boolean isOpened() {
        return camera.position.x != CAM_MAIN_POSITION;
    }

    public static void show(boolean show) {
        if ((isOpened() && !show) || (!isOpened() && show))
            startTask(show);
    }

    private static void startTask(boolean show) {
        if (timer.isEmpty()) {
            isFinish = true;
            listener.onStart();
            timer.scheduleTask(initializeTimerTask(show), 0f, INTERVAL_SEC,
                    ((int) (WIDTH / SPEED)));
        }
    }
}

2- In your Screen write the following:

@Override
public void show() {
    stage = new Stage(new StretchViewport(1080, 1920));

    // May be you want to make some Actions with NavigationDrawer state
    NavigationDrawerListener listener = new NavigationDrawerListener() {

        @Override
        public void onStart() {
            System.out.println("onStart");
        }

        @Override
        public void onRun() {
            System.out.println("onRun");
        }

        @Override
        public void onFinish(float camX) {
            System.out.println("onFinish: " + camX);
        }
    };

    // You must be initialize NavigationDrawer Firstly
    NavigationDrawer.initialize(stage, listener);

    // This image is sample to show how navigationDrawer look like on the screen
    Image background= new Image(new Texture(Gdx.files.internal("background.jpg")));
    background.addListener(new ClickListener() {
        private int clicked = 0;
        public void clicked(InputEvent event, float x, float y) {
            if (clicked % 2 == 0) {
                clicked++;
                NavigationDrawer.show(true);
            } else {
                clicked++;
                NavigationDrawer.show(false);
            }
        }
    });
    background.setFillParent(true);
    stage.addActor(background);

    Gdx.input.setInputProcessor(stage);

}

3- The result of sample code look like that:

enter image description here

4- Finally you can create images, labels, ... actors in navigation width which their positions into off-screen i.e. with negative positions. Enjoy!


UPDATE

This Navigation Drawer More performance and beauty sliding.

like image 153
iibrahimbakr Avatar answered Jan 08 '23 18:01

iibrahimbakr