LibGDX:如何从主游戏屏幕重复显示/隐藏覆盖弹出菜单

Posted

技术标签:

【中文标题】LibGDX:如何从主游戏屏幕重复显示/隐藏覆盖弹出菜单【英文标题】:LibGDX: How to show/hide an overlay popup menu from the main game screen repetitively 【发布时间】:2020-05-02 07:30:52 【问题描述】:

我正在做一个名为 Fuego Peligro 的游戏(基于 nfantone 的另一个名为 Ninja Rabbit 的 LibGDX“教程”项目,https://github.com/nfantone/ninja-rabbit)作为我大学 BIT 课程的论文,我想要一个叠加菜单以某种方式显示/隐藏在主游戏屏幕上。

弹出菜单就像一个检查点,显示来自主要平台游戏的简单琐事型小游戏。它通过 Telegraph (handleMessage) 方法调用。唯一的问题是当消息重复时,如果弹出窗口之前已经显示过,它不想再次重新显示。

所有文件和其他详细信息都在此链接中:https://github.com/NinjaSiren/FuegoPeligro

所有 .java 文件都在这里:https://github.com/NinjaSiren/FuegoPeligro/tree/master/core/src/com/mygdx/fuegopeligro

这是调用所有游戏内叠加层进行渲染的java类:LevelGraphicsProcessor.java

public class LevelGraphicsProcessor implements GraphicsProcessor, Telegraph 
    private final LevelRenderer mapRenderer;
    private final GameOverOverlay gameOver;
    private final LevelEndOverlay levelEnd;
    private MultipleChoice multipleChoice;
    private FourPicsOneWord fourPicsOneWord;
    private LetterPuzzle letterPuzzle;
    private Wordscapes wordscapes;

    private boolean renderGameOver;
    private boolean renderLevelEnd;
    private boolean minicamSelection;
    private final CurrentPlayerStatus status;
    private final NinjaRabbit ninja;
    private final Entity entity;

    public LevelGraphicsProcessor(final AssetManager assets, final LevelRenderer mapRenderer,
                                  final FuegoPeligro game, final NinjaRabbit ninjaRabbit,
                                  final CurrentPlayerStatus player) 
        status = player;
        ninja = ninjaRabbit;
        if (ninjaRabbit == null) 
            throw new IllegalArgumentException("'character' cannot be null"); 
        this.entity = ninjaRabbit;

        gameOver = new GameOverOverlay(game.getBatch(), assets, game);
        levelEnd = new LevelEndOverlay(game.getBatch(), assets, game);
        multipleChoice = new MultipleChoice(assets, game, ninjaRabbit);
        fourPicsOneWord = new FourPicsOneWord(assets, game, ninjaRabbit);
        letterPuzzle = new LetterPuzzle(assets, game, ninjaRabbit);
        wordscapes = new Wordscapes(assets, game, ninjaRabbit);
        this.mapRenderer = mapRenderer;
        MessageManager.getInstance().addListeners(this, MessageType.GAME_OVER.code());
        MessageManager.getInstance().addListeners(this, MessageType.FINISH_LEVEL.code());
        MessageManager.getInstance().addListeners(this, MessageType.COLLECTED.code());
    

    @Override
    public void update(final Entity character, final Camera camera) 
        mapRenderer.render((OrthographicCamera) camera);
    

    /*
     * (non-Javadoc)
     *
     * @see com.mygdx.fuegopeligro.graphics.GraphicsProcessor#draw(com.mygdx.fuegopeligro.entity.Entity,
     * com.badlogic.gdx.graphics.g2d.Batch)
     */
    @Override
    public void draw(final Entity entity, final Batch batch) 
        mapRenderer.update();

        if (renderGameOver) 
            gameOver.render(Gdx.graphics.getDeltaTime());
         else if (renderLevelEnd) 
            levelEnd.render(Gdx.graphics.getDeltaTime());
         else if (minicamSelection) 
            multipleChoice.render(Gdx.graphics.getDeltaTime());
            wordscapes.render(Gdx.graphics.getDeltaTime());
            letterPuzzle.render(Gdx.graphics.getDeltaTime());
            fourPicsOneWord.render(Gdx.graphics.getDeltaTime());

            entity.changeState(NinjaRabbitState.IDLE);
            byte worldValue = status.getCurrentWorld();
            //short levelValue = status.getCurrentLevel();
            short mgValue = status.getMGValue();

            if (worldValue == 1) 
                //short easyValue = status.getEqaValue();
                if (mgValue == 1) 
                    multipleChoice.setVisible(true);
                    Gdx.input.setInputProcessor(multipleChoice.stage);
                    if (multipleChoice.enterAnswer.isPressed()) 
                        multipleChoice.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 2) 
                    wordscapes.setVisible(true);
                    Gdx.input.setInputProcessor(wordscapes.stage);
                    if (wordscapes.enterAnswer.isPressed()) 
                        wordscapes.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 3) 
                    letterPuzzle.setVisible(true);
                    Gdx.input.setInputProcessor(letterPuzzle.stage);
                    if (letterPuzzle.enterAnswer.isPressed()) 
                        letterPuzzle.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 4) 
                    fourPicsOneWord.setVisible(true);
                    Gdx.input.setInputProcessor(fourPicsOneWord.stage);
                    if (fourPicsOneWord.enterAnswer.isPressed()) 
                        fourPicsOneWord.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                
             else if (worldValue == 2) 
                //short hardValue = status.getHqaValue();
                if (mgValue == 1) 
                    multipleChoice.setVisible(true);
                    Gdx.input.setInputProcessor(multipleChoice.stage);
                    if (multipleChoice.enterAnswer.isPressed()) 
                        multipleChoice.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 2) 
                    wordscapes.setVisible(true);
                    Gdx.input.setInputProcessor(wordscapes.stage);
                    if (wordscapes.enterAnswer.isPressed()) 
                        wordscapes.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 3) 
                    letterPuzzle.setVisible(true);
                    Gdx.input.setInputProcessor(letterPuzzle.stage);
                    if (letterPuzzle.enterAnswer.isPressed()) 
                        letterPuzzle.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                 else if (mgValue == 4) 
                    fourPicsOneWord.setVisible(true);
                    Gdx.input.setInputProcessor(fourPicsOneWord.stage);
                    if (fourPicsOneWord.enterAnswer.isPressed()) 
                        fourPicsOneWord.setVisible(false);
                        Gdx.input.setInputProcessor(new NinjaRabbitInputProcessor(ninja));
                    
                
            
        
    

    @Override
    public boolean handleMessage(final Telegram msg) 
        renderGameOver = msg.message == MessageType.GAME_OVER.code();
        renderLevelEnd = msg.message == MessageType.FINISH_LEVEL.code();
        minicamSelection = msg.message == MessageType.COLLECTED.code();
        return true;
    

    @Override
    public void resize(final int width, final int height) 
        gameOver.resize(width, height);
        levelEnd.resize(width, height);
        multipleChoice.resize(width, height);
        wordscapes.resize(width, height);
        letterPuzzle.resize(width, height);
        fourPicsOneWord.resize(width, height);
    

    @Override
    public void dispose() 
        gameOver.dispose();
        levelEnd.dispose();
        multipleChoice.dispose();
        wordscapes.dispose();
        letterPuzzle.dispose();
        fourPicsOneWord.dispose();
    

这是我想在收到消息时显示的弹出小游戏之一,并在单击按钮时隐藏。:MultipleChoice.java

public class MultipleChoice implements Disposable 
    private static final String QUESTION_LABEL = "CHECKPOINT: MULTIPLE CHOICE";
    private static final String ENTER_ANSWER = "ENTER";
    private static final String HINT_ANSWER = "HINT";

    public final Stage stage;
    private final NinjaRabbit ninja;
    private final Label QuestionLabel;
    private final Label QuestionText;
    private final TextButton answer1;
    private final TextButton answer2;
    private final TextButton answer3;
    private final TextButton answer4;
    public final TextButton enterAnswer;
    private final TextButton enterHints;
    private final Table table;

    public MultipleChoice(final AssetManager assets, final FuegoPeligro game,
                          final NinjaRabbit ninjaRabbit) 
        stage = new Stage(new ScreenViewport(), game.getBatch());
        ninja = ninjaRabbit;

        Label.LabelStyle style = new Label.LabelStyle();
        AssetManager assetManager = new AssetManager();
        assetManager.load(Assets.GAME_UI_SKIN);
        assetManager.finishLoading();
        Skin skin = assetManager.get(Assets.GAME_UI_SKIN);

        style.fontColor = Color.WHITE;
        style.font = assets.get(Assets.HUD_FONT);
        QuestionLabel = new Label(QUESTION_LABEL, style);

        style.fontColor = Color.WHITE;
        style.font = assets.get(Assets.HUD_FONT);
        QuestionText = new Label("", style);

        answer1 = new TextButton("", skin);
        answer1.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );
        answer2 = new TextButton("", skin);
        answer2.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );
        answer3 = new TextButton("", skin);
        answer3.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );
        answer4 = new TextButton("", skin);
        answer4.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );

        // enter answer
        enterAnswer = new TextButton(ENTER_ANSWER, skin);
        enterAnswer.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );

        // enter hints
        enterHints = new TextButton(HINT_ANSWER, skin);
        enterHints.addListener(new ClickListener() 
            @Override
            public void clicked(final InputEvent event, final float x, final float y) 

            
        );

        table = new Table();
        table.setFillParent(true);
        table.setDebug(true);

        table.add(QuestionLabel).expand(true, false).center();
        table.row().pad(20, 0, 0, 10);
        table.add(QuestionText).expand(true, false);
        table.row().pad(10, 0, 0, 20);
        table.add(answer1).expand(true, false);
        table.add(answer2).expand(true, false);
        table.row().pad(10, 0, 0, 20);
        table.add(answer3).expand(true, false);
        table.add(answer4).expand(true, false);
        table.row().pad(10, 0, 0, 20);
        table.add(enterAnswer).expand(true, false);
        table.add(enterHints).expand(true, false);
        table.setVisible(false);

        stage.addActor(table);
        stage.setKeyboardFocus(table);
    

    public void render(final float delta) 
        Gdx.gl20.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

        Gdx.gl20.glDisable(GL20.GL_BLEND);
        stage.getBatch().end();
        stage.act(delta);
        stage.draw();
        stage.getBatch().begin();
    

    public void resize(final int width, final int height)  stage.getViewport().update(width, height); 

    @Override
    public void dispose() 
        stage.dispose();
    

    public void setVisible(boolean value) 
        table.setVisible(value);
    

【问题讨论】:

【参考方案1】:

在使用 LibGDX 时,UI 的标准约定是使用 Scene2D,并且 Scene2D 对象必须包含在 Stage 中 - 要使用类似覆盖的窗口,可以使用特殊的 Table 派生词:Window类。

您希望在叠加层中的任何Actors 都可以添加到Window 实例中,并像它自己的StageTable 一样定位,并且Window 可以添加到场景中并从场景中移除 - 甚至使用 fade(In/Out) 操作淡入和淡出(而不是像以下示例中那样直接添加和移除):

public class ExampleClass 

    ...
    private Stage stage = new Stage(...);
    private Window popUp = new Window("...");
    private TextButton windowButton1 = ..., windowButton2 = ...;
    ...

    public ExampleClass() 
        ...

        Gdx.setInputProcessor(stage); //Allows input to Scene2D components - important!
        //Register click listeners to buttons to close window when clicked
        windowButton1.addListener(new CloseButtonListener(this));
        windowButton2.addListener(new CloseButtonListener(this));
        ...
        //Add buttons to window
        popUp.add(windowButton1);
        popUp.add(windowButton2);
        ...
    

    //Run when message is received
    public void messageReceived() 
        ...
        stage.add(popUp); //Add window to stage you want to overlay
        ...
    

    ...

    public Stage getStage() 
        return stage;
    

    public Window getPopUp() 
        return popUp;
    

    ...


class CloseButtonListener implements ClickListener  //Inner class for handling button clicks, multiple can be created for different button types with different logic when window is closed.

    private ExampleClass exampleInstance;

    public CloseButtonListener(ExampleClass exampleInstance) 
        this.exampleInstance = exampleInstance;
    

    //Remove the window from the stage when the button is clicked, handles any other logic too depending on button.
    @Override
    public void clicked(InputEvent event, float x, float y) 
        ...
        exampleInstance.addAction(Actions.removeActor());
        ...
    



【讨论】:

我正在使用 LibGDX 1.9.6 beta 5 的修改版本。我在舞台上找不到 .removeActor。仅 removeCaptureListener、removeListener 和 removeTouchFocus。 @JohnDanielEsguerra 修正了我的答案,抱歉!

以上是关于LibGDX:如何从主游戏屏幕重复显示/隐藏覆盖弹出菜单的主要内容,如果未能解决你的问题,请参考以下文章

如何更改我的 android 游戏的图片/标志? - libGDX [重复]

libgdx getHeight() 没有覆盖整个屏幕

Java - Libgdx:保存和加载屏幕

LibGDX:安卓游戏安全

防止在presentViewController上隐藏键盘(显示弹出窗口)

libGDX:如何在按键后逐行读取和显示.txt文件中的文本?