Now that we have our first trappings of a proper game, we should make it save the game between gaming sessions.
Android provides us with four ways to save our data from being lost forever, but first I will go on a tangent to explain the two types of data we should be concerned with: persistent and transient. Let’s say we’re writing a race timer application that keeps track of fastest times and includes a stopwatch function. In this case, the fastest times are persistent data because we want to be able to go into the application and see them after we close it. The stopwatch timer is transient because we don’t care to keep it if we close the application after a session of races. In most cases it’d be a nice feature to keep the stopwatch timer, but for the sake of the example, we don’t care about it.
Android offers us three ways to store persistent data: simple-settings based based, flat-file based, and database based data files. It also comes with a fourth way for transient-only data, but we’ll get to that later.
The first way is the simple-settings file, which will store simple primitives – a boolean true/false, a number, some text – and offers a very clean way to load the data later. This is good for simple settings, as the name would imply, but it’s not great for more complex things like custom objects or dynamic lists of simple objects, or dynamic lists of complex objects, god forbid. For that we’ll need something more flexible.
Databases offer a wonderfully powerful way to easily organize data and link the relevant pieces together, and provide a great interface for pulling only little bits of data at a time as it’s needed. For instance, if you have a notepad application that you want to pull out the titles of each note to display in a list, then you click on one and it loads that specific note’s body text at that time – the benefit is you don’t need to pull every note’s body text to display the initial note list, you can save it until you choose which note you want to view. The drawback of using this method is there’s a lot of overhead to creating and using the database. If we’re not selectively loading our data – as is the case with the game – the benefit is lost and the overhead is not worth it.
Finally, we have the flat-file. For this, we can only read and write text to a file. It doesn’t sound very complex or helpful at first glance, but it’s lack of complexity is made up for with it’s immense flexibility. If you can create a way to translate your complex objects and lists to and from a text string, you can simply write it to a file and read from it. The hard part is formatting your complex objects into a string that can be parsed later. Fortunately there’s a few libraries out there that can help us with this (json, xml, etc).
Now, the Android has a strange quirk where if you change the orientation of the device – landscape or portrait – it’ll destroy all data, even in the middle of running an application. You can stop this from happening by locking the device into a specific orientation, but offering support for multiple orientations is more user-friendly. This is where, in addition to the persistent data being captured using one of the methods above, we’ll capture transient data – so we don’t see the timer clock (using the run timer example) reset when we tilt the screen. This transient data is stored in a special fast-access section of memory so it’s quickly stored and retrieved, but it’s not intended for the often-more-hefty persistent data, which is stored on the file system.
- Added the hooks necessary to let us know when we need to save and load.
- Created a load method to match the save method from last update.
- Players and Monsters can now cast projectile spells.
Current demo: Monster AI changed to throw one fireball when the player is in range. Red can launch a fireball too, but he only gets one per monster he’s already killed. The number of enemies per level is increased, as is Red’s initial health to make games last a little longer.
Here’s a video of the enemies and fireballs in action.