Game-Saving Basics
From a game coding point of view, saving means that your game needs to be able to save its state to a persistent storage device (hard disk or network) and subsequently also be able to reload such a saved state at any point during game play. A simple approach in a game with multiple levels is to save only the level the player was currently on. This has the advantage of being easy to implement: All you have to do is write a number (level=5) or code word (level=forestWorld9) to a file. The code word could also be secret so that players can't cheat by guessing the name of an upcoming level and modifying the save-game file themselves. The disadvantage of this idea is that when players load a game, they must restart the level from the beginning, even if they saved the game seconds from the end of the level. Also, the player's capabilities aren't saved, so the player can't evolve over the course of the game (for example, by getting new items or abilities). Most modern games provide more advanced save-game functionality: Saving "freezes" the game state at any point in the game, and loading returns to that exact point. The entire state of the game is saved-the player returns to the same location, enemies continue to run from where they were, and a bomb about to explode underneath the player still explodes. A from-scratch approach to game saving typically relies on saving the core collection of program variables that make up the game's current player-dependent state to a flat, binary file. The file format normally is a custom proprietary format tailored to the game. This saved-game state includes any information that cannot be recalculated from a freshly installed copy of the game:
- The player(s)'s progress (position in game world, accumulated score, damage, and objects such as weapons, spells, ammunition, and special items)
- The current state of all moveable game objects (location, orientation, animation cycle, velocity, artificial intelligence state, and so on), including the player and his foes or fellow players
- Pending events and any variables defined in game scripts (an event to close a door, an event to activate a staircase after five seconds, and so on)
- All global game-configuration data, as configured by the player (keyboard mappings, game difficulty setting, rendering quality, sound/music settings, and so on)
There's nothing inherently difficult in saving all this data manually, but this approach could be time-consuming to implement and would ignore the siren call of reuse potential offered by Java's Serialization API. This standard API can be leveraged to do much of the hard work for you, so the bulk of this chapter shows you how to safely exploit the Serialization API's features to implement game snapshot saves and reloads. Unfortunately, Java's Serialization API addresses only part of the overall problem of game snapshots. When letting your users save a game, you normally let the user associate a name with this snapshot so that later, when the user wants to revert to a saved game, a list of named snapshots can be browsed and picked from. In the ever-escalating game features stakes, modern games also typically show a thumbnail-size screenshot for each saved game. This way, your player needs to simply visually browse the thumbnails and must refer to the snapshot label only if there's any ambiguity in the list of screenshots. Toward the end of this chapter, we show you how to implement such a feature, necessitating some help from AWT's automation butler, Mr. Robot.