Saving game-data (how do I do save-games?)

A place for tutorials on how to get the most out of Flash

Saving game-data (how do I do save-games?)

Postby Renara » Fri Jun 03, 2011 11:16 pm

There are several ways to save data in your Flash games such that it can be loaded again later on. Many games use codes, and while this can be work in every case (provided the user remembers a code) there are some much more effective ways that can store any kind of data you like, within reason.

Shared Objects

The Basics
The simplest, and easiest to use method for anyone with a basic understanding of ActionScript is the SharedObject, available in ActionScript 2.0 and above, and all recent Flash players. Using this is dead simple, like so:

Code: Select All Code
savedGame = SharedObject.getLocal("LoKSavedGame");
savedGame.data.items[0] = "PrincessOutfit";
savedGame.data.items[1] = "FlightSuit";
savedGame.data.location = "SharpClawVillage";
savedGame.flush();


This is a simple example that gets a saved object, puts some items in and a note of your current location. It's worth noting that all data is added to "savedGame.data", adding to any other part of the object, for example "savedGame.value = 1234" will set the value as normal, but it will not be saved.

The .flush() method is what actually saves the data, and while it is performed automatically when you close a .swf, it is worth controlling when .flush() is called to avoid half-updated data being saved at unusual times. For this reason, you may wish to save automatically at designated locations or checkpoints, or upon entering a new area. The following example is the simplest and easiest case, which is a button that when pressed will save a player's important information; since this can be made visible on all scenes it is the easiest solution for simple games:

Code: Select All Code
on(release) {
    _root.savedGame.data.items = _root.player.items;
    _root.savedGame.data.location = _root.player.location;
    _root.savedGame.data.flush();
}


Which will immediately save the player at the current location, and save all their currently held items. In this example _root.player contains all current player-data for the game to interact with, and this data is simply copied into the SharedObject for saving, ensuring no unusual partial updates occur.

Validation and success
SharedObjects, just like cookies in a web-browser, are made available based upon the domain-name that the .swf is accessed from, meaning that if you play the game on site A, then play another copy on site B, you will be unable to access your saved game from site A. This isn't usually a big deal for most games, and requires a more complicated solution, which I'll describe at a later time.

In the mean time however, SharedObjects, just like cookies, may be rejected by a user, and it's worth making sure to test for such cases, as you may wish to inform the user of a failed save-game so they can do something about it, you can do this by simply testing the return value of .flush(); a value of true or false indicates success or failure, while a resulting of "pending" indicates that the user has been asked whether to allow the save or not.

If you wish to know what a user chooses for a pending request, then you can do the following:

Code: Select All Code
_root.savedGame.data.message = "Save me!";
success = _root.savedGame.flush();

if (success == "pending") {
    _root.savedGame.onStatus = function(code) {
        if (code == "SharedObject.Flush.Success")
            trace ("Save Successful!");
        else
            trace ("Save Failed!");
    }
} else if (success)
    trace ("Save Successful!");
else
    trace ("Save Failed!");


This might look a little complicated, but it's easy to simplify depending upon which cases you're interested in (if any). Quite simply .flush() is called, if it succeeds then save was successful, or if it fails then it failed. If it is pending then a function is provided and called when the user makes a decision.

One last note, is that you can provide a size (in bytes) to the flush command, allowing you to specify a minimum amount of memory required by your SharedObject, useful for ensuring it has room to grow, it's important to keep the value sensible!

Sharing data between .swf files
If for some reason you have multiple .swf files (for example, updated versions of your game), then you can share data between them by making sure to specify as non-specific a domain as you can when fetching your SharedObject, but you must remember to do this in all of your .swf files, as by default a .swf can only read shared objects created by the .swf that created them, and only if it isn't relocated!

Like so:

Code: Select All Code
savedGame.getLocal("LoKSavedGame", "http://legendofkrystal.com/game");


This will fetch, and later store, a SharedObject accessible to any .swf location in the domain legendofkrystal.com/game, and so long as other games in that domain fetch their SharedObject the same way, then they'll gain access to the shared data! It's worth noting that if you do do this with different versions of your game, that you need to remember that data stored by previous versions may not be in quite the format you expect, for this reason it may be worth storing a version number in your saved-games, and deleting any saved game that is too long out of date. Which brings up the next topic:

Deleting SharedObjects
Default behaviour for a SharedObject is to retain all data entered into them, which means you need to delete all data in the SharedObject before flushing the (empty) result, like so:

Code: Select All Code
savedGame = SharedObject.getLocal("LoKSavedGame");
for (i in savedGame.data) delete savedGame.data[i];
savedGame.flush();


This can be useful for deleting old saved-game data that is no longer compatible, or for creating a new saved-game that overwrites the first, as other old values may still be left in the SharedObject that can result in a corrupted game!

For works in progress
For those of you wanting to add save-games to something you're still actively developing, then it's best to provide some resistance to data corruption or odd save-game glitches by designing core statistics for your game as early as possible. So let's take a look at combining some of the ideas covered.

Let's say you have a game with levels, and experience for upgrading characters. These two stats should allow you to preserve old player-games, without needing to worry about current level, checkpoints, or character upgrades, in such a way that you can trash old data without inconveniencing players too much.

So, let's take a look at saving the game:
Code: Select All Code
savedGame.data.version = _root.saveGameVersion; // Save game version, increase this as you change the save-game data.
savedGame.data.level = 4; // Save the highest game-level that the player reached, so they can return to it, even if they can't pick up exactly where they left off.
savedGame.data.experience = 123; // Save experience points total, this should also cover the value of all upgrades purchased, so if you have to nuke a user's upgrades, they can re-purchase them again.


And here, some compatibility checks for older saved-games:
Code: Select All Code
// Grab the crucial progress stats
playerLevel = savedGame.data.level;
playerExperience = savedGame.data.experience;

// Check save-game version
if (savedGame.data.version < _root.saveGameVersion) { // We should delete old game data
    for (i in savedGame.data) delete savedGame.data[i];
} else if (savedGame.data.version > _root.saveGameVersion) {
    // Save game was created by newer version of game! Best to warn the user they need a newer copy of the game, to avoid losing data.
    // Alternatively, remove this section and test above for "savedGame.data.version != _root.saveGameVersion"
} else { // Otherwise, it should be safe to load remaining game data
    currentLevel = savedGame.data.currentLevel;
    currentCheckpoint = savedGame.data.currentCheckpoint;
}

This is a good format even for release games, as you never know if you're going to add stuff later that may be vulnerable to unexpected values from old saved games.
Renara (team twitter | newgrounds)
Team Lead Programmer
Lok Team Member
Site Administrator
User avatar
Renara
Foxy Admin
 
Joined: Fri Jan 08, 2010 4:16 pm

Re: Saving game-data (how do I do save-games?)

Postby Mr. Bingo » Sun Jun 05, 2011 2:09 am

Wait since there will be a saved feature does that mean the game will only be playable if you download it?
The Most Hated Among the Stupid
Mr. Bingo
 
Joined: Sun Mar 20, 2011 4:13 am
Location: ur mom's house lol

Re: Saving game-data (how do I do save-games?)

Postby Renara » Sun Jun 05, 2011 5:05 pm

Mr. Bingo Wrote:Wait since there will be a saved feature does that mean the game will only be playable if you download it?

This is just a tutorial, so bear in mind it isn't describing how LoK v0.3 will actually work, I'm just trying to give people an idea of how they can most easily add saved-games to their own flashes.

That said; SharedObjects in flash are like cookies, the data they contain is stored locally on your machine, but the .swf files (the game) can be anywhere, there are just some caveats with regards to what information they're able to access. One of the problems with SharedObjects though is that they're domain specific (like cookies) so if you play the game from a different location (such as if you downloaded a copy for offline use) then it won't be able to access the same game-data. But in effect, you can play a game hosted on legendofkrystal.com, with your progress being stored automatically on your computer with SharedObjects, there'd be no need to download the game.
However, if you were to download the game or play a copy hosted elsewhere, then you'd be unable to continue your SharedObject-based saved game, likewise if you played the game from a different computer. So SharedObjects are great for simpler games where it isn't a big deal if you have to start again, but for longer, more involved games it becomes an issue.

However, LoK v0.3 will have a few different options for saved-games, that should hopefully ensure that players are able to keep their progress as conveniently as possible, and even pass it around between online and offline copies of the game. I likely won't do a tutorial on these more complex methods until LoK v0.3's code is available. But my hope is to be able to allow users running Flash 10 or higher to save and load their game from anywhere they like (just like you would a document in Word for example), and also possibly support remotely saving games here on the website, provided you have a user account of course.
Renara (team twitter | newgrounds)
Team Lead Programmer
Lok Team Member
Site Administrator
User avatar
Renara
Foxy Admin
 
Joined: Fri Jan 08, 2010 4:16 pm


Return to Tutorials



Who is online

Users browsing this forum: No registered users