Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
AndEngine for Android Game Development Cookbook

You're reading from   AndEngine for Android Game Development Cookbook AndEngine is a simple but powerful 2D game engine that's ideal for developers who want to create mobile games. This cookbook will get you up to speed with the latest features and techniques quickly and practically.

Arrow left icon
Product type Paperback
Published in Jan 2013
Publisher Packt
ISBN-13 9781849518987
Length 380 pages
Edition 1st Edition
Arrow right icon
Authors (3):
Arrow left icon
Brian Boyles Brian Boyles
Author Profile Icon Brian Boyles
Brian Boyles
Nicolas Gramlich Nicolas Gramlich
Author Profile Icon Nicolas Gramlich
Nicolas Gramlich
JAYME SCHROEDER JAYME SCHROEDER
Author Profile Icon JAYME SCHROEDER
JAYME SCHROEDER
Arrow right icon
View More author details
Toc

Table of Contents (18) Chapters Close

AndEngine for Android Game Development Cookbook
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface
1. AndEngine Game Structure FREE CHAPTER 2. Working with Entities 3. Designing Your Menu 4. Working with Cameras 5. Scene and Layer Management 6. Applications of Physics 7. Working with Update Handlers 8. Maximizing Performance 9. AndEngine Extensions Overview 10. Getting More From AndEngine Source Code for MagneTank Index

Saving and loading game data


In the final topic for the game structure chapter, we're going to set up a class that can be used in our project to manage data and settings. The more obvious game data we must save should include character stats, high scores, and other various data we may have included in our game. We should also keep track of certain options a game might have, such as whether the user has sounds muted or not, gore effects, and more. In this recipe, we're going to work with a class called SharedPreferences, which will allow us to easily store data to a device for retrieval at a later time.

Note

The SharedPreferences class is a great way to quickly store and retrieve primitive datatypes. However, as the data size increases, so will the needs of the method we use to store data. If our games do require a large amount of data to be stored, something to consider is to take a look into SQLite databases for data storage.

Getting ready

Please refer to the class named UserData in the code bundle.

How to do it…

In this recipe, we're setting up a UserData class that will store a Boolean variable to determine sound muting and an int variable that will define the highest, unlocked level a user has reached. Depending on the needs of the game, there may be more or less datatypes to include within the class for different reasons, be it high score, currency, or other game-related data. The following steps describe how to set up a class to contain and store user data on a user's device:

  1. The first step involves declaring our constant String variables, which will hold references to our preference file, as well as "key" names, which will hold references to data within the preference file, as well as corresponding "value" variables. Additionally, we declare the SharedPreferences object as well as an editor:

    // Include a 'filename' for our shared preferences
    private static final String PREFS_NAME = "GAME_USERDATA";
      
    /* These keys will tell the shared preferences editor which
      data we're trying to access */
      
    private static final String UNLOCKED_LEVEL_KEY = "unlockedLevels";
    private static final String SOUND_KEY = "soundKey";
    
    /* Create our shared preferences object & editor which will
     be used to save and load data */
    private SharedPreferences mSettings;
    private SharedPreferences.Editor mEditor;
    
    // keep track of our max unlocked level
    private int mUnlockedLevels;
    
    // keep track of whether or not sound is enabled
    private boolean mSoundEnabled;
  2. Create an initialization method for our SharedPreferences file. This method will be called when our game is first launched, either creating a new file for our game if one does not already exist, or load existing values from our preference file if it does exist:

    public synchronized void init(Context pContext) {
      if (mSettings == null) {
        /* Retrieve our shared preference file, or if it's not yet
          * created (first application execution) then create it now
          */
        mSettings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        /* Define the editor, used to store data to our preference file
         */
        mEditor = mSettings.edit();
    
        /* Retrieve our current unlocked levels. if the UNLOCKED_LEVEL_KEY
          * does not currently exist in our shared preferences, we'll create
          * the data to unlock level 1 by default
          */
        mUnlockedLevels = mSettings.getInt(UNLOCKED_LEVEL_KEY, 1);
          
        /* Same idea as above, except we'll set the sound boolean to true
          * if the setting does not currently exist
          */
        mSoundEnabled = mSettings.getBoolean(SOUND_KEY, true);
      }
    }
  3. Next, we will provide getter methods for each of the values that are meant to be stored in our SharedPreferences file, so that we can access the data throughout our game:

    /* retrieve the max unlocked level value */
    public synchronized int getMaxUnlockedLevel() {
      return mUnlockedLevels;
    }
  4. And finally, we must provide setter methods for each of the values that are meant to be stored in our SharedPreferences file. The setter methods will be responsible for saving the data to the device:

    public synchronized void unlockNextLevel() {
      // Increase the max level by 1
      mUnlockedLevels++;
        
      /* Edit our shared preferences unlockedLevels key, setting its
       * value our new mUnlockedLevels value
        */
      mEditor.putInt(UNLOCKED_LEVEL_KEY, mUnlockedLevels);
        
      /* commit() must be called by the editor in order to save
        * changes made to the shared preference data
       */
      mEditor.commit();
    }

How it works…

This class demonstrates just how easily we are able to store and retrieve a game's data and options through the use of the SharedPreferences class. The structure of the UserData class is fairly straightforward and can be used in this same fashion in order to adapt to various other options we might want to include in our games.

In the first step, we simply start off by declaring all of the necessary constants and member variables that we'll need to handle different types of data within our game. For constants, we have one String variable named PREFS_NAME that defines the name of our game's preference file, as well as two other String variables that will each act as references to a single primitive datatype within the preference file. For each key constant, we should declare a corresponding variable that preference file data will be stored to when it is first loaded.

In the second step, we provide a means of loading the data from our game's preference file. This method only needs to be called once, during the startup process of a game in order to load the UserData classes member variables with the data stored in the SharedPreferences file. By first calling context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE), we check to see whether or not a SharedPreference file exists for our application under the PREFS_NAME string, and if not, then we create a new one a—MODE_PRIVATE, meaning the file is not visible to other applications.

Once that is done, we can call getter methods from the preference file such as mUnlockedLevels = mSettings.getInt(UNLOCKED_LEVEL_KEY, 1). This will pass the data stored in the UNLOCKED_LEVEL_KEY key of the preference file to mUnlockedLevels. If the game's preference file does not currently hold any value for the defined key, then a default value of 1 is passed to mUnlockedLevels. This would continue to be done for each of the datatypes being handled by the UserData class. In this case, just the levels and sound.

In the third step, we set up the getter methods that will correspond to each of the datatypes being handled by the UserData class. These methods can be used throughout the game; for example, we could call UserData.getInstance().isSoundMuted() during level loading to determine whether or not we should call play() on the Music object.

In the fourth step, we create the methods that save data to the device. These methods are pretty straightforward and should be fairly similar regardless of the data we're working with. We can either take a value from a parameter as seen with setSoundMuted(pEnableSound) or simply increment as seen in unlockNextLevel().

When we want to finally save the data to the device, we use the mEditor object, using putter methods which are suitable for the primitive datatype we wish to store, specifying the key to store the data as well as the value. For example, for level unlocking, we use the method, mEditor.putInt(UNLOCKED_LEVEL_KEY, mUnlockedLevels) as we are storing an int variable. For a boolean variable, we call putBoolean(pKey, pValue), for a String variable, we call putString(pKey, pValue), and so on..

There's more...

Unfortunately, when storing data on a client's device, there's no way of guaranteeing that a user will not have access to the data in order to manipulate it. On the Android platform, most users will not have access to the SharedPreferences file that holds our game data, but users with rooted devices on the other hand will be able to see the file and make changes as they see fit. For the sake of explanation, we used obvious key names, such as soundKey and unlockedLevels. Using some sort of misconstruction can help to make the file look more like gibberish to an average user who had accidentally stumbled upon the game data with their rooted device.

If we feel like going further to protect the game data, then the even more secure approach would be to encrypt the preference file. Java's javax.crypto.* package is a good place to start, but keep in mind that encryption and decryption does take time and will likely increase the duration of loading times within the game.

You have been reading a chapter from
AndEngine for Android Game Development Cookbook
Published in: Jan 2013
Publisher: Packt
ISBN-13: 9781849518987
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime