{"id":238,"date":"2015-03-01T09:25:36","date_gmt":"2015-03-01T08:25:36","guid":{"rendered":"http:\/\/www.pixnbgames.com\/blog\/?p=238"},"modified":"2015-04-11T22:59:27","modified_gmt":"2015-04-11T21:59:27","slug":"how-to-make-a-splash-screen-in-libgdx","status":"publish","type":"post","link":"https:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-make-a-splash-screen-in-libgdx\/","title":{"rendered":"How to make a splash screen in LibGDX"},"content":{"rendered":"<p>An important aspect at\u00a0video game development is\u00a0the splash screen.<\/p>\n<h4>What is the splash screen?<\/h4>\n<p>It is an screen which is shown to the user just when he opens the application. It is usually used to show some information to user while in background the app does the necessary load and preparations to run. We can see the use of splash screen, for example, on\u00a0<a title=\"Eclipse official site\" href=\"http:\/\/www.eclipse.org\/\" target=\"_blank\">Eclipse<\/a> or\u00a0<a title=\"GIMP official site\" href=\"http:\/\/www.gimp.org\/\" target=\"_blank\">GIMP<\/a>.<\/p>\n<h4>Why is it important?<\/h4>\n<p><strong>The more important issue is that the splash screen shows to the user that our app is running.<\/strong>\u00a0If the app needs many resources (common in a video game), it is probably the app spends some seconds on load all it. If we don&#8217;t do anything, our app will seem frozen along those seconds and in the better case it will only show a black screen.\u00a0By using the splash screen the user will know our app is opened and running.<\/p>\n<p>Furthermore, we can take advantage of the splash screen to show our trademark, any message, etc.<\/p>\n<p>&nbsp;<\/p>\n<h3>How to make it in LibGDX<\/h3>\n<p style=\"text-align: justify;\">For this example, I have going to use the class <code>com.badlogic.gdx.Game<\/code> as superclass of the main class of my game, and every scene of the game will be an implementation of the interface <code>com.badlogic.gdx.Screen<\/code>, because this is the way I usually work (see\u00a0<a title=\"How to manage screens in LibGDX\" href=\"http:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-manage-screens-in-libgdx\/\">Scenes management in LibGDX<\/a>). Let&#8217;s go to see the classes implementations:<\/p>\n<h4>SplashScreen<\/h4>\n<p>The code of this class will be like this:<\/p>\n<pre lang=\"Java\" line=\"1\">package com.pixnbgames.splashscreen;\r\n\r\nimport com.badlogic.gdx.Gdx;\r\nimport com.badlogic.gdx.Screen;\r\nimport com.badlogic.gdx.graphics.GL20;\r\nimport com.badlogic.gdx.graphics.Texture;\r\nimport com.badlogic.gdx.graphics.g2d.SpriteBatch;\r\n\r\npublic class SplashScreen implements Screen {\r\n    private SpriteBatch batch;\r\n    private Texture ttrSplash;\r\n \r\n    public SplashScreen() {\r\n        super();\r\n        batch = new SpriteBatch();\r\n        ttrSplash = new Texture(\"splash-screen.png\");\r\n    }\r\n \r\n    @Override\r\n    public void render(float delta) {\r\n        Gdx.gl.glClearColor(0, 0, 0, 1);\r\n        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);\r\n \r\n        batch.begin();\r\n        batch.draw(ttrSplash, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());\r\n        batch.end();\r\n    }\r\n \r\n    @Override\r\n    public void hide() { }\r\n \r\n    @Override\r\n    public void pause() { }\r\n \r\n    @Override\r\n    public void resume() { }\r\n\r\n    @Override\r\n    public void show() { }\r\n\r\n    @Override\r\n    public void resize(int width, int height) { }\r\n \r\n    @Override\r\n    public void dispose() {\r\n        ttrSplash.dispose();\r\n        batch.dispose();\r\n    }\r\n}<\/pre>\n<h5>Key Issues:<\/h5>\n<p style=\"text-align: justify;\"><span style=\"text-decoration: underline;\">It&#8217;s very important to stand out that this class must not depend on any other component which has not been loaded yet.<\/span> This is why this class draws directly an image on screen with a <code>SpriteBatch<\/code> object.<\/p>\n<p style=\"text-align: justify;\">Supose you have a class in your project, <code>ImageManager<\/code>, responsible of load and management of the graphics resources of our app.\u00a0Probably, <code>ImageManager<\/code> should be initialized at the aplication startup, so that the resources it manages will be available to the rest of the game. Well, our <code>SplashScreen<\/code> can not use this class. For two reasons:<\/p>\n<ul>\n<li style=\"text-align: justify;\">The splash screen have to be as light as possible. Remember that it will be shown to the user as soon as possible at the aplication startup and it will be visible only for a few seconds.<\/li>\n<li style=\"text-align: justify;\">If we try to use any resource which has not been loaded yet, the splash screen will not can be shown to the user, so our app will still seem \u00abfrozen\u00bb.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h4>\u00a0Main class of the Game, GdxSplashScreenGame<\/h4>\n<p style=\"text-align: justify;\">For the main class of the game, <code>GdxSplashScreenGame<\/code>, I will supose that there is a second class (not included in this tutorial) with the main menu of the game, named <code>MainMenuScreen<\/code> (see <a title=\"How to manage screens in LibGDX\" href=\"http:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-manage-screens-in-libgdx\/\">Scenes management in LibGDX<\/a>). The main menu will be automatically shown after splash screen.<\/p>\n<p style=\"text-align: justify;\">We also add a condition to splash screen, and it is that the screen will be shown at least for two seconds. Why do we do this? Because if we hide the splash screen just when all the resources are loaded, the time while the splash screen is shown is totally dependent of the device where the app is running. Even, if the device is enough fast at resource loading, our splash screen could not get displayed. By defining a minimum display time, we managed to mitigate the differences between the various devices where our game is running.<\/p>\n<p style=\"text-align: justify;\">The code for the main class <code>GdxSplashScreenGame<\/code> would be like this:<\/p>\n<pre lang=\"Java\" line=\"1\">package com.pixnbgames.splashscreen;\r\n\r\nimport com.badlogic.gdx.Game;\r\nimport com.badlogic.gdx.Gdx;\r\nimport com.badlogic.gdx.utils.Timer;\r\n\r\npublic class GdxSplashScreenGame extends Game {\r\n \r\n    private static long SPLASH_MINIMUM_MILLIS = 2000L;\r\n \r\n    public GdxSplashScreenGame() { super(); }\r\n \r\n    @Override\r\n    public void create () {\r\n        setScreen(new SplashScreen());\r\n \r\n        final long splash_start_time = System.currentTimeMillis();\r\n        new Thread(new Runnable() {\r\n               @Override\r\n               public void run() {\r\n \r\n                   Gdx.app.postRunnable(new Runnable() {\r\n                       @Override\r\n                       public void run() {\r\n                           \/\/ ... carga de datos\r\n                           \/\/ ... carga de fuentes tipograficas\r\n                           \/\/ ... carga de sonidos\r\n                           \/\/ ... carga de imagenes\r\n                           \/\/ ... carga de recursos de internacionalizacion\r\n                           \/\/ ... otros\r\n \r\n                           \/\/ Se muestra el menu principal tras la SpashScreen\r\n                           long splash_elapsed_time = System.currentTimeMillis() - splash_start_time;\r\n                           if (splash_elapsed_time &lt; GdxSplashScreenGame.SPLASH_MINIMUM_MILLIS) {\r\n                               Timer.schedule(\r\n                                       new Timer.Task() {\r\n                                           @Override\r\n                                           public void run() {\r\n                                               GdxSplashScreenGame.this.setScreen(new MainMenuScreen());\r\n                                           }\r\n                                       }, (float)(GdxSplashScreenGame.SPLASH_MINIMUM_MILLIS - splash_elapsed_time) \/ 1000f);\r\n                           } else {\r\n                               GdxSplashScreenGame.this.setScreen(new MainMenuScreen());\r\n                           }\r\n                       }\r\n                   });\r\n               }\r\n            }).start();\r\n    }\r\n \r\n    @Override\r\n    public void dispose() {\r\n        \/\/ DISPOSE ALL RESOURCES\r\n        getScreen().dispose();\r\n        Gdx.app.exit();\r\n    }\r\n}\r\n<\/pre>\n<h5>Key Issues:<\/h5>\n<ul>\n<li style=\"text-align: justify;\">The resources loading cannot be done in the main thread, so then the application could not show anything until the loading will be completed. This is why it is done in a new <code>Thread<\/code>.<\/li>\n<li style=\"text-align: justify;\">If after resource loading, it has been spent less time that the time defined in <code>SPLASH_MINIMUM_MILLIS<\/code>, we have to wait the missing time and then show the main menu screen. We get this by passing a <code>Timer.Task<\/code> object to the <code>Timer.schedule()<\/code> method.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3>Source code<\/h3>\n<p>You can download the source code of a simple project with splash screen from my <a title=\"Gdx-SplashScreen-Example en GitHub\" href=\"https:\/\/github.com\/angelnavarro\/Gdx-SplashScreen-Example\" target=\"_blank\">GitHub<\/a> repository.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An important aspect at\u00a0video game development is\u00a0the splash screen. What is the splash screen? It is an screen which is shown to the user just when he opens the application. It is usually used to show some information to user <a class=\"more-link\" href=\"https:\/\/www.pixnbgames.com\/blog\/libgdx\/how-to-make-a-splash-screen-in-libgdx\/\">Seguir leyendo <span class=\"screen-reader-text\">  How to make a splash screen in LibGDX<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":304,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[15,18],"language":[4],"_links":{"self":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/238"}],"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=238"}],"version-history":[{"count":17,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/238\/revisions"}],"predecessor-version":[{"id":300,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/posts\/238\/revisions\/300"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/media\/304"}],"wp:attachment":[{"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/media?parent=238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/categories?post=238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/tags?post=238"},{"taxonomy":"language","embeddable":true,"href":"https:\/\/www.pixnbgames.com\/blog\/wp-json\/wp\/v2\/language?post=238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}