【问题标题】:LibGDX How to implement scene 2D menu tabs?LibGDX 如何实现场景 2D 菜单选项卡?
【发布时间】:2014-07-29 10:45:48
【问题描述】:

我已经制作了我的 rpg 的 alpha 版本,现在我想实现一个带有多个选项卡的菜单。当您在游戏中并按 Tab 或 Escape 时,我想显示一个用户界面,该界面将有一个带有 3 个按钮(如主菜单、技能树和库存)的顶部栏。问题是,当您切换选项卡时,我需要停止绘制先前选择的选项卡并从中禁用演员,因此当您从当前选项卡中单击某些内容时,它不会同时单击未绘制的选项卡上的按钮,而是它就在那里...如何禁用演员、按钮,这样我就可以绘制一个新选项卡,而不必担心当前选项卡与前一个选项卡重叠?

编辑:我想避免制作多个阶段。我希望有一个单独的阶段来定义每个选项卡。

【问题讨论】:

    标签: java libgdx scene2d


    【解决方案1】:

    不可见的 Actor 不会接收触摸事件,这是完成选项卡式界面的最简单方法,只需适当地设置选项卡内容 Actor 的可见性。

    这是我在 libgdx 中实现选项卡式界面的方法:

    package com.badlogic.gdx.tests.lwjgl;
    
    import com.badlogic.gdx.ApplicationAdapter;
    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
    import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
    import com.badlogic.gdx.scenes.scene2d.Actor;
    import com.badlogic.gdx.scenes.scene2d.InputEvent;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.Button;
    import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
    import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
    import com.badlogic.gdx.scenes.scene2d.ui.Image;
    import com.badlogic.gdx.scenes.scene2d.ui.Skin;
    import com.badlogic.gdx.scenes.scene2d.ui.Stack;
    import com.badlogic.gdx.scenes.scene2d.ui.Table;
    import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
    import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
    import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
    import com.badlogic.gdx.utils.viewport.ScreenViewport;
    
    class Game3 extends ApplicationAdapter {
    
        Skin skin;
        Stage stage;
    
        @Override
        public void create () {
            skin = new Skin(Gdx.files.internal("data/uiskin.json"));
            stage = new Stage(new ScreenViewport());
    
            Table main = new Table();
            main.setFillParent(true);
    
            // Create the tab buttons
            HorizontalGroup group = new HorizontalGroup();      
            final Button tab1 = new TextButton("Tab1", skin, "toggle");
            final Button tab2 = new TextButton("Tab2", skin, "toggle");
            final Button tab3 = new TextButton("Tab3", skin, "toggle");
            group.addActor(tab1);
            group.addActor(tab2);
            group.addActor(tab3);
            main.add(group);
            main.row();
    
            // Create the tab content. Just using images here for simplicity.
            Stack content = new Stack();
            final Image content1 = new Image(skin.newDrawable("white", 1,0,0,1)); 
            final Image content2 = new Image(skin.newDrawable("white", 0,1,0,1));
            final Image content3 = new Image(skin.newDrawable("white", 0,0,1,1));   
            content.addActor(content1);
            content.addActor(content2);
            content.addActor(content3);
    
            main.add(content).expand().fill();
    
            // Listen to changes in the tab button checked states
            // Set visibility of the tab content to match the checked state
            ChangeListener tab_listener = new ChangeListener(){
                @Override
                public void changed (ChangeEvent event, Actor actor) {
                    content1.setVisible(tab1.isChecked());
                    content2.setVisible(tab2.isChecked());
                    content3.setVisible(tab3.isChecked());
                }
            };
            tab1.addListener(tab_listener);
            tab2.addListener(tab_listener);
            tab3.addListener(tab_listener);
    
            // Let only one tab button be checked at a time
            ButtonGroup tabs = new ButtonGroup();
            tabs.setMinCheckCount(1);
            tabs.setMaxCheckCount(1);
            tabs.add(tab1);
            tabs.add(tab2);
            tabs.add(tab3);
    
            stage.addActor(main);       
            Gdx.input.setInputProcessor(stage);
        }
    
        @Override
        public void render () {
            stage.act();
            stage.draw();
        }
    
        @Override
        public void dispose () {
            stage.dispose();
            skin.dispose();
        }
    
        public static void main (String[] args) {
            new LwjglApplication(new Game3(), new LwjglApplicationConfiguration());
        }
    }
    

    【讨论】:

      【解决方案2】:
      • 处理菜单的最佳方法是use different Screen
        1. 易于管理。分开的班级。关注点分离。
        2. 简化的生命周期管理。当另一个屏幕正在运行时暂停一个屏幕。
        3. 其他屏幕被隐藏:(

      • 如果你想保持相同的屏幕,最简单的方法是不同的阶段。
        1. 只需禁用前一阶段的输入侦听器并停止在冻结阶段调用更新。
        2. 手动管理:(

      • 如果您想使用同一阶段,则必须由您实现整个逻辑,因为您拒绝使用框架定义的类。
        1. 完全可定制。
        2. 难以管理。 (需要进行不必要的测试。Libgdx 库类已经过测试。)
        3. 实施起来可能很有趣。

      怎么做:

      • 为菜单和游戏对象使用不同的父顶级组。
      • 一次手动禁用一组事件处理并停止更新。
      • 可能需要覆盖Stage 类中的几个方法。 (不推荐)。

      通常 HUD 和暂停菜单在不同的阶段实现。

      我想避免制作多个阶段

      这一定来自“stages are heavy”。

      相反,stages 不重,但 spritebatches 很重

      如果您制作多个共享一个 spritebatch 的阶段,您可以轻松创建多个阶段而无需太多开销。

      希望这会有所帮助。
      祝你好运。

      【讨论】:

      • 我在考虑使用不同的屏幕,但是当我实现技能树时,我必须链接玩家对象,以便我可以从技能中更新统计数据,并且每次我还需要更换屏幕你想看看技能树。关于使用多个阶段和相同的精灵批处理可能是一个好主意,但是如果我想添加一个批处理参数,我还需要提供一个不是我想要的视口参数......虽然感谢你的想法.也许我会尝试同时实现一个阶段和多个阶段,看看哪一个更适合我的游戏。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-21
      • 2015-04-25
      • 2023-03-18
      • 2016-12-29
      • 1970-01-01
      • 2017-05-18
      相关资源
      最近更新 更多