【问题标题】:libgdx Screen - How to set a new Screen by a Stringlibgdx 屏幕 - 如何通过字符串设置新屏幕
【发布时间】:2015-09-23 19:07:18
【问题描述】:

我正在尝试通过字符串设置新屏幕。我可以使用 Class.forName(ScreenString),这很酷,但函数 game.setScreen() 似乎有一些问题。

我在这里做的是:

 Class<?> temp = null;
        if(something) try {
            temp = Class.forName("string1"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if(something else) try {
            temp = Class.forName("string2"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        game.setScreen(new temp());

但我显然有一些语法问题,因为它告诉我找不到“temp”。 我哪里错了?

【问题讨论】:

  • 你的目标是什么?这看起来很老套。

标签: java string class libgdx screen


【解决方案1】:

您需要forName 方法的完全限定名称。你不能打电话给new temp()。该语法表示您想要一个不存在的 temp 类的实例。 temp 是一个变量。如果你的类有一个无参数的构造函数,你可以实例化它:

Screen screen = temp.newInstance();

如果您需要传入一些参数,请创建一个所有级别都扩展的超类:

public class MyScreen extends Screen {

    Game game;

    public void init (Game game){
        this.game = game;
    }
}

现在按名称加载关卡。请注意,forName 需要 完全限定 名称,因此您必须添加包名称。

public void loadLevelScreen (String name) {
    String packageName = getPackage().getName();
    Class<? extends MyScreen> screenClass = null;
    try {
        screenClass = Class.forName(packageName + "." + name).asSubclass(MyScreen.class);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    try {
        MyScreen screen = screenClass.newInstance();
        screen.init(this.game);
        setScreen(screen);
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

【讨论】:

  • 如果它只有带参数的构造函数怎么办?
  • 我正在尝试使用 game.setScreen((Screen) temp.getClass().getDeclaredConstructors(Game.class).newInstance(this.game));但它不像 Game.class 那样是一个正确的论点
  • 简单的解决方案是将代码从构造函数移到方法中,并在实例化类后立即调用该方法。
  • 如果您想按照自己的方式进行操作,请使用 getDeclaredConstructor 而不是 getDeclaredConstructors。后者不带参数并返回它们的数组。
  • 此外,我似乎无法将 Class 对象投射到 Screen。我认为这很奇怪,这是让它发挥作用的最后一个问题
【解决方案2】:

如果你想要一个 ScreenClass 的实例,你必须像这样在类对象上调用 newInstance():

game.setScreen((Screen) temp.newInstance());

【讨论】:

    【解决方案3】:

    发生了什么:

    if (something)
    {
      game.setScreen(somethingScreen);
    }
    else if (somethingElse)
    {
      game.setScreen(somethingElseScreen);
    }
    

    想不出一种方法为什么按你的方式去做。如果您有像“mainScreen”和“optionsScreen”这样的字符串,只需比较语句中的内容即可。

    如果您确实想按照自己的方式进行操作,可以尝试HashMap&lt;String, Screen&gt;

    HashMap<String, Screen> map = new HashMap<>();
    
    map.put("string1", new MainScreen);
    map.put("String2", new OptionScreen);
    
    if (something)
    {
      game.setScreen(map.get("string1"));
    }
    else if (somethingElse)
    {
      game.setScreen(map.get("string2"));
    }
    

    对我来说感觉更自然一些。

    据我所知,如果您有"lvl06",您需要加载级别“06”而不是“16”或“01”。所以你在运行之前就知道什么字符串映射到哪个级别。因此,一个简单的语句就足以将您的LevelScreens 链接到Strings

    【讨论】:

    • 我有很多类叫做 "lv01" "lv02" ... "lv10" "lv11" 等等。我通过在运行时检查的索引获取类名,并且 if 语句在那里,因为我可以有“lv0”+索引或“lv”+索引,具体取决于变量,它可能大于或小于 9。
    • 为什么每个级别都有一个类?你的意思是从同一个类派生的对象吗?无论如何,你已经知道当字符串为"lvl04" 时应该显示什么屏幕了,对吧?那么我的两个例子就足够了,不需要反思。
    • 因为每个级别都不同。我无法理解您的第一个示例,因为 setScreen 需要 Screen 对象而不是 String
    • 你的意思是每个级别都完全不同?就像第一级可能是 FPS,下一个级别可能是 RTS?我通常会有一个类(蓝图)来创建关卡,并有该类的许多对象来表示多个关卡。是的,字符串上的引号不应该存在,已编辑。
    • 我的意思是有些东西总是一样的,有些东西会改变,所以我有我的 Level 类和许多扩展它的类
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多