Libgdx 滑动暂停菜单

4
在我的游戏屏幕中,用户可以点击菜单按钮,然后该菜单按钮将暂停游戏并显示菜单。我试图将菜单作为新阶段实现,但那只是打开了一个新屏幕,设置了我想要的菜单图形,而其余部分则保持黑色。这里是图片,您可以看到我在说什么:Image 我想让这个绿色部分平滑地滑入游戏场景,并且我想摆脱屏幕上的这个黑色部分,而是让那一部分透明(我只想显示一个图像的绿色部分)。我尝试找到一些关于暂停菜单的好教程,但没有运气。这是我的暂停屏幕代码:
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);
    }


}

游戏界面如下:
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);
    }
}

我知道我做错了,但是应该怎么做呢?当按钮被按下时绘制一个矩形还是什么?

在这种情况下,你的菜单不应该是游戏中独立的屏幕。将其功能放入GameScreen中。在绘制gameStage之后绘制菜单阶段。使用Actions将你的内容移入和移出屏幕。顺便说一句,stage.act应该在stage.draw之前调用。否则,你的舞台将始终有一个帧的延迟。 - Tenfour04
谢谢回复!我一开始避免在一个屏幕上进行两个阶段,因为我在某个地方读到这样做可能会影响性能,但我会尝试一下。 - DaxHR
如果它们共享相同的Sprite批处理,则不需要。实例化一个单独的Sprite批处理,然后将其传递到每个构造函数中。 - Tenfour04
1个回答

10

我的游戏中,我使用libgdx制作了一个NavigationDrawer,效果如下:

enter image description here


可以使用示例代码来创建这个效果,只需遵循以下几个步骤:

1-NavigationDrawer类复制到您的项目中:

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- 在你的屏幕中编写以下内容:

@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- 示例代码的结果如下:

enter image description here

4- 最后,您可以在导航栏中创建图像、标签等演员,并将它们的位置设置为离屏幕边缘一定距离,即使用负值。享受吧!


更新

这个导航抽屉更加流畅和美观。


@Crowni 我遇到了一个问题,就是有时候timer.scheduleTask(initializeTimerTask..不会被触发。就好像代码停在了startTask()方法中的listener.onStart();处一样。这种情况大多发生在我退出游戏后几秒钟再次打开它的时候。可能是什么问题呢?谢谢。 - Bmbariah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接