{"id":210,"date":"2014-11-13T08:36:37","date_gmt":"2014-11-13T07:36:37","guid":{"rendered":"http:\/\/www.pixnbgames.com\/blog\/?p=210"},"modified":"2015-08-21T23:52:54","modified_gmt":"2015-08-21T22:52:54","slug":"how-to-manage-screens-in-libgdx","status":"publish","type":"post","link":"https:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-manage-screens-in-libgdx\/","title":{"rendered":"How to manage screens in LibGDX"},"content":{"rendered":"<p style=\"text-align: justify;\">When making games, it is common that our application has multiple screens or scenes. Below I will show a way to manage the different scenes in libgdx.<\/p>\n<p style=\"text-align: justify;\">For this example, I will supose the game has three screens: the main menu, the seleccion level screen and the game itself. In order to not do this article so large, I will not use auxiliar classes for constants, utilities, etc. The classes we use are shown in below diagram:<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/LibGDX-Screen-Management.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-medium wp-image-169\" src=\"http:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/LibGDX-Screen-Management-300x225.png\" alt=\"LibGDX - Screen Management\" width=\"300\" height=\"225\" srcset=\"https:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/LibGDX-Screen-Management-300x225.png 300w, https:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/LibGDX-Screen-Management.png 960w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2 style=\"text-align: justify;\">Main class of the game<\/h2>\n<p style=\"text-align: justify;\">At project creation, the main class is called\u00a0<code>MyGdxGame<\/code>\u00a0by default, and it extends from <code>AplicationListener<\/code>. LibGDX has a subclass of <code>AplicationListener<\/code>, the class <code>Game<\/code>, prepared to show \u00a0an implementation of the interface <code>Screen<\/code> at each time.\u00a0That we do is to use the class <code>Game<\/code> as parent of our main class, and each of the screens will be an implementation of <code>Screen<\/code>.<\/p>\n<p style=\"text-align: justify;\">By this, our main game class will be like this:<\/p>\n<pre lang=\"Java\" line=\"54\">public class MyGdxGame extends Game {\r\n...\r\n}<\/pre>\n<p style=\"text-align: justify;\">We will go back to this class later.<\/p>\n<h2 style=\"text-align: justify;\">Game Screens<\/h2>\n<p style=\"text-align: justify;\">To work with class <code>Game<\/code>, each screen of our game has to implement the interface <code>Screen<\/code>. Furthermore, I work normaly with class <code>Stage<\/code>. To combine this two elements I use an abstract class, <code>AbstractScreen<\/code>, that extends <code>Stage<\/code> class and implements <code>Screen<\/code> interface. This own class will be the parent class of our screens.<\/p>\n<pre lang=\"Java\" line=\"10\">public abstract class AbstractScreen extends Stage implements Screen {\r\n \r\n    protected AbstractScreen() {\r\n        super( new StretchViewport(320.0f, 240.0f, new OrthographicCamera()) );\r\n    }\r\n \r\n    \/\/ Subclasses must load actors in this method\r\n    public abstract void buildStage();\r\n\r\n    @Override\r\n    public void render(float delta) {\r\n        \/\/ Clear screen\r\n        Gdx.gl.glClearColor(1, 0, 0, 1);\r\n        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);\r\n \r\n        \/\/ Calling to Stage methods\r\n        super.act(delta);\r\n        super.draw();\r\n    }\r\n\r\n    @Override\r\n    public void show() {\r\n        Gdx.input.setInputProcessor(this);\r\n    }\r\n\r\n    @Override\r\n    public void resize(int width, int height) {\r\n        getViewport().update(width, height, true);\r\n    }\r\n\r\n    @Override public void hide() {}\r\n    @Override public void pause() {}\r\n    @Override public void resume() {}\r\n}<\/pre>\n<h3 style=\"text-align: justify;\">Key issues<\/h3>\n<ul>\n<li style=\"text-align: justify;\">It uses a <a title=\"LibGDX Viewports\" href=\"https:\/\/github.com\/libgdx\/libgdx\/wiki\/Viewpor\" target=\"_blank\">Viewport<\/a> of 320 for width and 240 for height.<\/li>\n<li style=\"text-align: justify;\">It declares an abstract method, <code>buildStage()<\/code>, that will must be implemented by every screen of our game. This method is used to add actors to the scene (<a href=\"https:\/\/github.com\/libgdx\/libgdx\/wiki\/Scene2d\" target=\"_blank\">LibGDX Scene2d<\/a>).<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">We have said that our game will consist of three screens. These will have the following constructors:<\/p>\n<ul>\n<li>First screen: Main Menu\n<pre lang=\"Java\">public MainMenuScreen() {...}<\/pre>\n<\/li>\n<li>Second screen: Level Select\n<pre lang=\"Java\">public LevelSelectScreen() {...}<\/pre>\n<\/li>\n<li style=\"text-align: justify;\">Third screen: Game<br \/>\nCommonly we use the same class for several (or all) levels of our game. To know which is the current level, we have a parameter in the class constructor indicating the level:<\/p>\n<pre lang=\"Java\">public GameScreen(Integer level) {...}<\/pre>\n<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">I will not show the implementation of these classes in order to not do this article so long with code that is not related with the main target of this post. In any case, at the end of this article you can see the link to download the source code used in this example.<\/p>\n<p>&nbsp;<\/p>\n<h2>ScreenEnum:\u00a0list of available screens<\/h2>\n<p style=\"text-align: justify;\">In order to know the available scenes, we create\u00a0an\u00a0Enum java type, called\u00a0<code>ScreenEnum<\/code>, with the list of possible screens. This enum defines an abstract method\u00a0<code>getScreen()<\/code>\u00a0that allow us to get an screen instance of each enum type.<\/p>\n<pre lang=\"Java\" line=\"8\">public enum ScreenEnum {\r\n\r\n    MAIN_MENU {\r\n        public AbstractScreen getScreen(Object... params) {\r\n            return new MainMenuScreen();\r\n        }\r\n    },\r\n    LEVEL_SELECT {\r\n        public AbstractScreen getScreen(Object... params) {\r\n            return new LevelSelectScreen();\r\n        }\r\n    },\r\n    GAME {\r\n        public AbstractScreen getScreen(Object... params) {\r\n            return new GameScreen((Integer) params[0]);\r\n        }\r\n    };\r\n\r\n    publicabstract AbstractScreen getScreen(Object... params);\r\n}<\/pre>\n<h3>Key issues<\/h3>\n<ul>\n<li style=\"text-align: justify;\">The enum defines an abstract method\u00a0(<code>getScreen()<\/code>) for\u00a0get an instance of each screen from its enum type.\u00a0This method supports one variable argument (<code>Object... params<\/code>); this allow to pass params to the screen constructors when it is needed.<\/li>\n<li style=\"text-align: justify;\">Constructor of classes\u00a0<code>MainMenuScreen<\/code>\u00a0and\u00a0<code>LevelSelectScreen<\/code>\u00a0don&#8217;t need parameters.<\/li>\n<li style=\"text-align: justify;\"><code>GameScreen<\/code>, in change, need an argument of type <code>Integer<\/code>. So, for instantiate\u00a0this screen we make casting to <code>Integer<\/code> from the first element of the array\u00a0<code>Object... params<\/code>.<\/li>\n<\/ul>\n<h3>Usage<\/h3>\n<p>If we want to obtain, for example, the screen of main menu we can do this:<\/p>\n<pre>AbstractScreen mainMenuScreen = ScreenEnum.MAIN_MENU.getScreen();<\/pre>\n<p>&nbsp;<\/p>\n<h2>Scenes manager<\/h2>\n<p style=\"text-align: justify;\">The class\u00a0<code>ScreenManager<\/code>\u00a0is the responsible of screens management. This class, in combination with\u00a0<code>ScreenEnum<\/code>, will allow us to change the visible screen in a really easy way:<\/p>\n<pre lang=\"Java\" line=\"7\">public class ScreenManager {\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Singleton: unique instance\r\n\u00a0 \u00a0\u00a0private static ScreenManager instance;\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Reference to game\r\n\u00a0 \u00a0\u00a0private Game game;\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Singleton: private constructor\r\n\u00a0 \u00a0\u00a0private ScreenManager() {\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0super();\r\n\u00a0 \u00a0\u00a0}\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Singleton: retrieve instance\r\n\u00a0 \u00a0\u00a0public static ScreenManager getInstance() {\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0if (instance == null) {\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0instance = new ScreenManager();\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0}\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0return instance;\r\n\u00a0 \u00a0\u00a0}\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Initialization with the game class\r\n\u00a0 \u00a0\u00a0public void initialize(Game game) {\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0this.game = game;\r\n\u00a0 \u00a0\u00a0}\r\n\r\n\u00a0 \u00a0\u00a0\/\/ Show in the game the screen which enum type is received\r\n\u00a0 \u00a0\u00a0public void showScreen(ScreenEnum screenEnum, Object... params) {\r\n\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\/\/ Get current screen to dispose it\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0Screen currentScreen = game.getScreen();\r\n\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\/\/ Show new screen\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0AbstractScreen newScreen = screenEnum.getScreen(params);\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0newScreen.buildStage();\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0game.setScreen(newScreen);\r\n\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\/\/ Dispose previous screen\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0if (currentScreen != null) {\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0currentScreen.dispose();\r\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0}\r\n\u00a0 \u00a0\u00a0}\r\n}<\/pre>\n<h3>Key issues<\/h3>\n<ul>\n<li style=\"text-align: justify;\">It is used the software pattern Singleton. By this we will only have an instance of this class for the whole app. Furthermore, this instance will be accesible from any point of our program. The way to get the instance is:\n<pre lang=\"Java\">ScreenManager.getInstance()<\/pre>\n<\/li>\n<li style=\"text-align: justify;\">To work correctly, the class needs a reference to main class of the game, (subclass of\u00a0<code>Game<\/code>). We pass this reference in the method\u00a0<code>initialize()<\/code>:\n<pre lang=\"Java\">ScreenManager.getInstance().initialize(gameInstance);<\/pre>\n<\/li>\n<li style=\"text-align: justify;\">The method\u00a0<code>showScreen()<\/code>\u00a0allow us to show any screen of the of the game by passing its enum type. We also can pass other params\u00a0needed in the screen constructor. For example:\n<pre lang=\"Java\">ScreenManager.getInstance().showScreen( ScreenEnum.LEVEL_SELECT );\r\nScreenManager.getInstance().showScreen( ScreenEnum.GAME, level);<\/pre>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2>Return to main class of the game<\/h2>\n<p style=\"text-align: justify;\">Once exposed classes\u00a0<code>ScreenEnum<\/code>\u00a0and\u00a0<code>ScreenManager<\/code>, it&#8217;s shown the implementation of the main class of the game:<\/p>\n<pre lang=\"Java\" line=\"7\">public class MyGdxGame extends Game {\r\n    @Override\r\n    publicvoid create () {\r\n        ScreenManager.getInstance().initialize(this);\r\n        ScreenManager.getInstance().showScreen( ScreenEnum.MAIN_MENU );\r\n    }\r\n}<\/pre>\n<p style=\"text-align: justify;\">Here, we simply\u00a0initialize the\u00a0<code>ScreenManager<\/code>\u00a0and we show the main menu screen.<\/p>\n<p>&nbsp;<\/p>\n<h2>Change Screen<\/h2>\n<p style=\"text-align: justify;\">To change between screens we only need to call method\u00a0<code>showScreen()<\/code>\u00a0of the class\u00a0<code>ScreenManager<\/code>. For example, if we want to go from main menu screen to select level screen, we can use below listener in a button:<\/p>\n<pre lang=\"Java\">btnPlay.addListener(\r\n    new InputListener() {\r\n        @Override\r\n        public boolean touchDown(InputEvent event,\r\n                                 float x, float y, int pointer, int button) {\r\n            ScreenManager.getInstance().showScreen( ScreenEnum.LEVEL_SELECT );\r\n            return false;\r\n        }\r\n    });<\/pre>\n<p>&nbsp;<\/p>\n<h2 style=\"text-align: justify;\">Source code<\/h2>\n<p style=\"text-align: justify;\">You can download the source code from my <a title=\"Gdx-Scene-Management en GitHub\" href=\"https:\/\/github.com\/angelnavarro\/Gdx-Scene-Management\" target=\"_blank\">GitHub<\/a> repository. By executing the program, we can surf through the three screens of the game:<\/p>\n<p><a href=\"http:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/Captura-de-pantalla-2014-11-10-a-las-22.21.11.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-203 size-medium\" src=\"http:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/Captura-de-pantalla-2014-11-10-a-las-22.21.11-300x259.png\" alt=\"Main Menu\" width=\"300\" height=\"259\" srcset=\"https:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/Captura-de-pantalla-2014-11-10-a-las-22.21.11-300x259.png 300w, https:\/\/www.pixnbgames.com\/blog\/wp-content\/uploads\/2014\/11\/Captura-de-pantalla-2014-11-10-a-las-22.21.11.png 868w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">I hope this article is helpful for you. Good luck for your projects and regards.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When making games, it is common that our application has multiple screens or scenes. Below I will show a way to manage the different scenes in libgdx. For this example, I will supose the game has three screens: the main <a class=\"more-link\" href=\"https:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-manage-screens-in-libgdx\/\">Seguir leyendo <span class=\"screen-reader-text\">  How to manage screens in LibGDX<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":169,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[15],"language":[4],"_links":{"self":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/210"}],"collection":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/comments?post=210"}],"version-history":[{"count":7,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/210\/revisions"}],"predecessor-version":[{"id":218,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/210\/revisions\/218"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/media\/169"}],"wp:attachment":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/media?parent=210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/categories?post=210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/tags?post=210"},{"taxonomy":"language","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/language?post=210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}