Full LibGDX Game Tutorial – Preferences and Menu

Menu

Sharing is caring!

Full LibGDX Game Tutorial – Menu Controls

This part of the tutorial will go over adding actions to buttons and creating our preferences. If you haven’t seen part 1 of this tutorial you can view it on Full LibGDX Game Tutorial – Project setup where it explains how to create this project as well as setting up the screens and menu.

So now we can run our game and we get our menu. Let’s start by adding the exit action so we can exit our game with the exit button. We will add a ChangeListener to out button so when the button changes our code is executed. Add the following code to your show method.

Anything inside the changed method will be executed when the button is clicked. Here we use “Gdx.app.exit();” to exit the application. Add the listener code again this time for the newGame button and instead of exiting the app we will tell it to change the screen using the reference to our parent class.

And again for our preferences button

Congratulations, you have just created the menu screen. There’s one more thing we need to do to before we move on to our preferences screen and that is, dispose of our stage when we’re finished with it. In libgdx we need to call dispose on any objects that allow you to dispose of them. In our menu screen that is our stage and our skin. Our skin will be disposed of automatically later when we implement our asset manager so we’ll leave that for now and just dispose of our stage. This is done by adding “stage.dispose();” in the dispose method of our MenuScreen.

Your MenuScreen Code should look like this now:

Preferences

Next, we should work on our preferences screen, but in order to do that, we need to set up our AppPreferences class with all the possible preferences. We should control sound volume, music volume, sound on or off and music on or off. This is the bare minimum I use for games and can be expanded later to include options like screen size, texture quality etc. Create a new class called AppPreferences in the top level package shown earlier in our base structure and add the following:

These will store the values of the preferences which will get saved when we close our application. Now we’re going to add a protected method. A protected method is a method that will only be allowed to be run by the current class or any classes that extend it. This means that our Screen classes can’t run the getPrefs method but our AppPreferences class can, and we want it this way so our AppPreferences class is the only one to control how we change our preferences. Now let’s add the method:

Next, let’s add a method to get and set the music volume. We will add a method called getMusicVolume (a getter) and setMusicVolume (a setter). As our getMusicVolume returns the volume we set it up with “public float getMusicVolume()“, our volume will be stored as a float value e.g 0.5 for half volume or 1.0 for full volume. Then we add “return getPrefs().getFloat(PREF_MUSIC_VOLUME, 0.5f);” This code tells the application to pull the PREF_MUSIC_VOLUME value from our saved preferences and if it isn’t set yet use the 0.5f value. As our setter will take a volume value and set it in our preferences we set it up with “public void setMusicVolume(float volume)”. The argument float volume is the value we will pass it when we change the volume. Next, we add “getPrefs().putFloat(PREF_MUSIC_VOLUME, volume);” to save the value of the volume to our preferences and finally “getPrefs().flush();” to make sure they are written to disk and saved. You should end up with this code:

We do that same for the other preferences except when we use yes / no values we use putBoolean and getBoolean instead of putFloat and getFloat. Once all this is complete you will have an AppPreferences class like this:

Preferences Screen

Yay! now we can work on our preferences screen. We will make a screen similar to our menu screen in that we will use a stage and a table to layout all our preference components. This time instead of a single column with 3 cells for the buttons we will make 2 columns one for the label and one for the control and 4 rows for each control. Add the stage, table and skin the same way we added it to our preferences screen and then add the following code to add a new Slider for our volume control:

Add the required imports, as usual, making sure to use the LibGDX versions for the EventListener and Event as the default Java.util ones won’t work and will cause your application to crash or run in unexpected ways. Do this again, this time for the soundSlider.

Next, we add the checkbox versions for music on/off and sound on/off with this code:

Again make sure you import the correct LibGDX versions of these classes. Now we need a way to go back to the main menu once we changed all our preferences. We will do that with a textButton like the ones we used in the main menu.

We now have all the control elements we need to add to our preferences screen. We still need to add labels so our users know which slider is for which preference. We will create 5  fields to store our labels in. These fields are defined in the top of our class after the “implements screen {” section like so:

These fields store our labels and will allow us to access them later, which we will need to do. Next, we add the code to create the labels and then add all our newly created controls to our table to be displayed.

You can now test out your application and see what issues you run into….Done!? Let’s see, we were unable to exit the application with the exit button after we viewed the preferences screen. This is because we only set the stage as the input processor when we create the screen. This is not what we want. We want it to be the controller every time we show the screen. So to fix this issue we just move the “Gdx.input.setInputProcessor(stage);” from the constructor to the show method.

Another issue we’re having is when we exit the preferences screen and go back into our preferences screen and change the volume sliders we’re still seeing the old preference sliders behind.

Pref screen error

Again, this is due to when we are creating our objects. We are currently creating the stage when we create the screen and then each time we show the screen we add a table to the stage so looking at our preferences screen 3 times will add 3 tables to our stage. We could move the stage creation into our show method and that would fix our issue as it would be a new stage each time we show our screen. This, however, means creating the stage every time, instead we can just empty the current stage with “stage.clear()” which will allow us to keep our stage.

So now everything works as we want it to. Let’s update the layout a bit so it’s a bit better looking.Our title is centred, but only on the left side of the screen. We want it to be centred across both columns. to do that we add “.colspan(2)” when we add it to our table. We do the same for our button since that should be in the middle too.  Next, we want to make the labels on the left not be centred so that they visually make a line making it more aesthetic to the user. This is done by adding “.leftg()” when addin the labels to our table. Finally, let’s get rid off the debug visuals by commenting out the “table.setDebug(true);

Preferences Layout libGDX

It’s better but not quite there yet. We should add padding to all the rows so they are not all squashed together. We do that by adding .pad(t,l,b,r) to our .row() and replacing the t,l,b,r with the amount of padding for the top, left, bottom, right respectively. I have used 10,0,0,10 for all rows and this is what it looks like now.

Prefs All Done

Later we will add some nice textures to the background for both our main menu screen and our preferences screen but in order to do that properly we will need the asset manager and I think we need to move into creating the game as we’ve done enough setting up to start working on the game logic.

Part 3 of our Full LibGDX Game tutorial will go into game logic and adding Box2D.

← Project Setup Contents Box2D →

Sharing is caring!

31 Replies to “Full LibGDX Game Tutorial – Preferences and Menu”

  1. Where is the source code. For some reason I can’t get “parent.getPreferences” to work inside my PreferencesScreen methods for volume and music.

    1. Unfortunately, there is no source until part 7. I don’t think there were any changes to the preferences between this part and part 7 so you could get the source for part 7 from https://stormyvids.is-sweet.co.uk/download.php?id=$1$d.vzNqFE$wFMn0A8t2qxDym8zktJC91 and check against that.

      1. can you send another link, the link is broken. Thanks!

          1. The code (just in case) is :

            private AppPreferences preferences;

            @Override
            public void create () {

            preferences = new AppPreferences();

            }

            public AppPreferences getPreferences(){
            return this.preferences;
            }

    2. After checking the source code, I found that getPreferences is missing from box2dtutorial class.
      add this in box2dtutorial class

      private AppPreferences preferences;
      add this to create method: preferences = new AppPreferences();
      add the below method
      public AppPreferences getPreferences() {
      return this.preferences;
      }
      then you’ll be able to “parent.getPreferences”
      Thanks for the tutorials 🙂 Really Appreciate it

      1. thanks a lot!

      2. Thank You

    3. Same here.

  2. hello,
    I do not really understand what dispose is for… ?
    would you please explain it for me..?

    1. The dispose method is used to manage memory. If any class you use in libgdx has a dispose method you should use it when you are no longer using that class. In this case it is the stage that is disposed. When the stage is dispose it will remove any files it has from memory and instruct native drivers to free all resources related to this class. In short it helps reduce memory usage and helps prevent memory leaks.

  3. hello, I am just wondering the saving data like preference does not work on my Android phone but, it works on my laptop… do you have any idea ?

    1. Make sure you are using the flush() command each time something is changed as android needs this flush command to write the changes to the save file. Also, check the PREFS_NAME and find the file on disk to see what items if any are changing.

  4. hello, the saving data, preference , does not work on my android phone, but it works on desktop… Do you have any idea? the code is totally same as yours

  5. hello it does not really work on my android phone, but it works on my laptop…

  6. The flush () function does not help, the fact is that you can not pull Libgdx every time you need that or other setting. Libgdx each time creates a new object whose editor field is null, so flush() function does nothing. As an option*: describe the class variable

    private final Preferences prefsObj = Gdx.app.getPreferences(PREFS_NAME);

    and use it instead of getPrefs().
    * This is an idea, so there may be syntax errors 🙂
    A few insides of Libgdx:
    @Override
    public Preferences getPreferences (String name) {
    return new AndroidPreferences(getSharedPreferences(name, Context.MODE_PRIVATE));
    }
    ===========
    @Override
    public void flush () {
    if (editor != null) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
    editor.apply();
    } else {
    editor.commit();
    }
    editor = null;
    }
    }
    ==========
    private void edit () {
    if (editor == null) {
    editor = sharedPrefs.edit();
    }
    }
    ==========
    public AndroidPreferences (SharedPreferences preferences) {
    this.sharedPrefs = preferences;
    }

  7. Hii. thanks for the great tutorial. but there is problem in my project. i cannot figure out the issue. when i open new screen and came back to previous any event is not work. as example if i click on preferences screen and click on back button menu screen will open. but any button is not work.

    1. This is due to the input controller being changed from the main screen controller to the second screen controller. This can be fixed by resetting the controller as the input controller when we go back to the main screen. This issue is pointed out and fixed in a future tutorial part.

  8. […] The Skin class is something like an image wrapper which helps you create the texture for the button while the Table class is something used for organisation. The most useful and simplest resource I found to get me started off was from gamedevelopment.blog:  https://www.gamedevelopment.blog/full-libgdx-game-tutorial-menu-control/  […]

  9. Where is the source code? After checking the source code, I found that getPreferences are missing from box2dtutorial class.

  10. volumeMusicSlider.setValue( parent.getPreferences().getMusicVolume() );
    volumeMucisSlider.addListener( new EventListener() {

    Should be “MusicSlider” not MucisSlider.
    Thanks for the great tutorial 🙂

    1. Thanks for pointing that out, will fix it. Also a Mucis slider sounds disgusting.

  11. That’s alright to this post end, except the size of these display content.All stuff show very tiny on my phone while I publish a test. In other word, this code isn’t effect:
    table.setFillParent( true );
    Is there any trouble in code here? thank you!

    1. Wibrst:
      Did you solve your problem with everything being very small on your phone? I’m running into the same issue!

  12. My preferences table is *tiny*! Like, barely able to see it well enough to do anything! And certainly too small to actually be able to interact with it?

    1. Hello, i added the line
      table.setFillParent(true);
      and it worked for me, size changed to normal.

    2. You need to change the screenViewPort to StretchViewPort then set size like 500,500.
      Try this in preference screen:
      stage=new Stage(new StretchViewport(500,500));
      and see the results.

  13. Hi
    I understand that screen dispose method is not called automatically, so the stage will not be disposed. How do you call the screens dispose method?

    Thanks

  14. No, full source for each page or this tutorial sucks.

    I’m struggling for 3 days to run preferences screen and it fails after first exit. Nothing woks and I have to force close the app.

  15. bad tutorial, not recommended

    1. It’s not bad but it’s incomplete

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.