2015-04-03 87 views
0

我正在LibGdx的游戏中工作,我会切换屏幕很多,所以我想我会做我自己的小屏幕管理器。但是要设置屏幕,我需要参考LibGdx Game。我对现在的经理看起来并不满意,我必须通过某种方式实现这一点,而无需发送两次Game对象。Libgdx ScreenManager

我的代码:

public static void setScreen(Screen screen, Game game){ 
     if(currentScreen != null){ 
      currentScreen.dispose(); 
      System.out.println("Screen disposed"); 
     } 
     currentScreen = screen; 
     game.setScreen(currentScreen); 
    } 

我们从另一个屏幕设置屏幕(例如从menuScreen设置gameScreen)身份证需要一个游戏对象发送到屏幕的构造函数,像这样:

ScreenManager.setScreen(new GameScreen(game), game);

在我的完美主义者希望能够以这样称呼它:

ScreenManager.setScreen(new GameScreen(), game

ScreenManager.setScreen(new GameScreen(game)

任何人都可以想办法做到这一点?或者我只是沉迷于我可能会做的事情?

+0

“SceneManager”必须是单身人士吗?一种可能的解决方案可能是允许实例化它,并在构造函数中传入你的'Game'对象,尽管还有一些感觉...... – lealand 2015-04-03 16:35:48

+0

还有一点评论,因为我一直处于类似的情况。看起来你正在开发一系列依赖关系(我认为)游戏取决于场景管理器,场景管理器取决于游戏。试着让它只是一种方式,例如游戏会告诉经理进行更新和渲染,并且经理会告诉当前场景进行更新和渲染。 – lealand 2015-04-03 16:45:27

+0

感谢您的意见:)这实际上是ScreenManager中的唯一方法。我不做任何渲染或类似的东西。我只是设置屏幕并处理旧的。我曾想过创建自己的抽象Screen类,而不是在LibGdx中实现这个类。也许我会这样做,我不必参考'游戏' – WEDEBE 2015-04-03 16:56:21

回答

4

您可以创建自己的屏幕类型,它将返回游戏并实现屏幕方法。

package ***; 

import com.badlogic.gdx.Screen; 
import ***.GameCore; 

public class MyScreen implements Screen { 
    GameCore game; 
    public MyScreen(GameCore game) { 
     this.game = game; 
    } 

    public GameCore getGameCore(){ 
     return this.game; 
    } 
    /* 
    Methods implemented from Screen (render , hide , dispose etc...) 
    */ 
} 

然后创建将扩展自选画面的屏幕类型。

package ***; 

import ***.GameCore; 

public class MenuScreen extends MyScreen{ 

    public MenuScreen (GameCore game) { 
     super(game);   
    } 
    /* 
    Methods implemented from Screen (render , hide , dispose etc...) 
    */ 
} 

在GameCore中创建MenuScreen的一个实例。

MenuScreen menuScreen = new MenuScreen(this); 

然后,你可以做你想要的技巧。

​​

然后,您可以自由设置你的屏幕的方式

ScreenManager.setScreen(new MenuScreen(game)); 

ScreenManager.setScreen(menuScreen);//if you have already created an instance of menu 
0

您可以使用Gdx.app.getApplicationListener()将其转换为游戏来获得游戏实例。此外,你的代码可以变得更清洁,改变setScreen方法:通过实施还我自己的Screen延伸Group

public static void setScreen(Screen screen){ 
    if(currentScreen != null){ 
     currentScreen.dispose(); 
     System.out.println("Screen disposed"); 
    } 
    currentScreen = screen; 
    Game game = (Game)Gdx.app.getApplicationListener(); 
    game.setScreen(currentScreen); 
} 
2

我实现我自己的ScreenManager。我使用的协议是为最小物体实例化设计的:

  • 所有Screen对象应该是单件。我将它们的构造函数封装为私有的,只有ScreenManager可以直接实例化它们。它们存储在哈希映射中。
  • 在实例化时只实例化一次您的Screen的对象,并将它们添加到Screen(因此我的所有组件也都延伸到Actor)。
  • 实现一个方法getInputProcessors(),该方法返回自定义Screen所使用的,不会由阶段隐式触发的自定义处理程序。 (其实我有一组类似的其他对象的功能,但在这里去除清晰度。)
  • ScreenManager电话showhide当需要换出一个画面,这实际上并不需要做什么,但可以重写定制行为。

这种工作方式是,我的屏幕管理器有一个Stage。经理只需清除屏幕之间的舞台对象并添加新舞台,因为它是一个Group(这是一个可包含更多演员的Actor)。如果不涉及太多的细节,这将涉及到在我的框架中解释大量内部类,下面是一些抽象出的功能的一般过程,这些功能可能与您无关(并允许传入外部Screen对象) :

private final AtomicReference<Screen> curScreen = ...; 
... 
public static boolean set(Screen nextScreen) 
{ 
    mutex.lock(); // prevent multi-threading issues 
    try 
    { 
    // ensure the provided screen is valid 
    final Screen cur = curScreen.get(); 
    if (null == nextScreen || nextScreen.equals(cur)) return false; 

    // atomically update the current screen reference 
    if (!curScreen.compareAndSet(cur, nextScreen)) return false; 

    // record the screen for back() operations and add it to the stage 
    if (null != cur) screenStack.push(cur); 
    stage.clear(); 
    stage.add(nextScreen); 

    // grab any custom input processors from the stage and build an input handler 
    final inputProcessors = nextScreen.getInputProcessors(); 
    final InputProcessor[] processors = inputProcessors.toArray(new InputProcessor[inputProcessors.size()+1]); 
    processors [inputProcessors.length-1] = stage; 

    // inform gdx of our new input target 
    Gdx.input.setInputProcessor(new InputMultiplexer(processors)); 

    return true; 
    } 
    catch (Throwable t) { Log.error(t); return false; } 
    finally { mutex.unlock(); } 
} 

请注意,使用AtomicReference定制Mutex对象,这是由于这里的效率可以得到更复杂的情况。您可以将Mutex替换为ReentrantLock,并将AtomicReference直接转换为Screen以获得更简单的应用程序。