Saving and Loading in Actionscript 3 (Mini-Lesson)

One thing you want to do as a game developer is make your players want to come back to your game more than once. And one of the best ways to accomplish this is to enable them to save their data for persistent gameplay. You might expect saving and loading to be tough to implement, but actionscript 3 is helpful enough to include the powerful SharedObject, which makes saving and loading data a piece of cake.

In this tutorial, we will create the following demo. Click the “+1″ button a few times to add to your score. If you refresh this webpage without clicking the “save” button, your score will revert to 0 when the page loads. But if you do click the “save” button, your score will load automatically the next time you load the page. Try it out!

SharedObject: The force behind saving and loading

A game’s ability to save and load data (such as the player’s highscore) requires a few different lines of code, all of which have to do with the SharedObject data type. All you need to do is create a SharedObject variable. Then you can give it simple “messages”, and it will do the dirty work of reading and writing to the player’s local disk for you.

The following steps will implement everything you need to save and load data. After we go through these basic steps, we can test it out with the demo.

1. Create a SharedObject variable.

Before we can start using the shared object, we need to create it. Declare the variable the same way you would any other — but don’t give it a value yet.

var saveDataObject:SharedObject;

2. Tell the SharedObject where to save and load

Right after you create the variable, set it using the SharedObject.getLocal function. This function will look for a specific file on the player’s computer, which will contain your data. If the file doesn’t exist yet, it will create one. The exact string you pass into this function doesn’t really matter — it will be used as part of the file name, but most player’s will never see it. I usually just set mine to “test” while I’m working on the game, and then change it to the title of my game when I publish it.

saveDataObject = SharedObject.getLocal("test");

(Note: You can combine this with the previous step and just write var saveDataObject:SharedObject = SharedObject.getLocal("test"). The only reason I divided into two sections is for clarity.)

3. Add any variable to the data property of your SharedObject

Here is the “meat” of the actionscript which handles saving. The past two steps set up the shared object. Now we are actually writing data to that object. The SharedObject data type has a built-in object variable called data“. Now, if you’ve been following my tutorials you may not have run into the official “object” data type so far. It’s a very flexible data type, which you can think of almost as a container for a bunch of other “sub-variables”, or “properties”. For example, if I wanted to create a new object variable I might write: var myDataObject:Object = {highscore:100, myName:"Player 1", time:10.4} and then I can access or modify the value of one of these properties, for example, the highscore, by using myDataObject.highscore

The cool thing is that the “data” Object is built into a SharedObject, so all you need to type to save something is:

saveDataObject.data.savedScore = currentScore;

Notice, you don’t even need to define the “savedScore” property of the data Object before you can set it to a value.

4. Tell the SharedObject to write the data to the local file

Setting a value to the data in the shared object won’t actually save anything immediately. It saves everything when the player quits the application, but never only rely on that — it won’t work if the player navigates away from a web page, the application crashes, etc, etc.

When you want the SharedObject to actually, immediately write its save data to its file on the player’s local hard drive you flush it:

saveDataObject.flush();

This is a very processor intensive action to call, so use it sparingly (never include it an a loop function). The game will probably lag for a half-second or so whenever you flush the save data, so be careful when to do it (but don’t leave it out entirely, or your players will be unhappy when they discover their data to be missing).

5. Load anything you have saved in the SharedObject’s data

Loading is literally the opposite of saving. Instead of saving a variable’s value to the saveDataObject.data, we just set the value of our variable to its respective property of the saveDataObject.

To load “currentScore” from the “savedScore”, we would write:

currentScore = saveDataObject.data.savedScore;

Testing it out:

Time to go from theory to a practical test. Our test project will include a variable that keeps track of the player’s score. Clicking a button will add one point and update the text field to display the current score. Clicking the save button will save the current score to a shared object, and flush the data to the player’s local drive.

Setting Up

Create a new Flash Professional project. We are going to set up the stage so that it looks like the following screenshot:

First use the rectangle tool to create two buttons. It doesn’t matter too much what they look like, as long as you label them so you can tell them apart.

Next, I converted them one at a time into Symbols of the Button type (Modify –> Convert to Symbol). Name one of them btnAdd and the other btnSave.

Then, for simplicity’s sake, give each button an instance name identical to its symbol name (btnAdd and btnSave).

Because this is just a test, it doesn’t really matter how the buttons look. However, I did spend a little time adding some effects to the buttons so that they change color when the player hovers their mouse cursor over the buttons, or clicks on them. It doesn’t require any code at all, so if you’re curious to see exactly what I did, just check out my source file (all you need to do is add more frames to the Button Symbol, like in the image below).

After your buttons are set up and code-ready, create a text field  above them (using the Text Tool) and type “Score: 0″ inside it. Make sure to make it a Dynamic Text Field (by using the drop-down list in the Properties panel). This will allow you to give it an instance name, and therefore modify it with code. Give it the instance name txtCode.

Note: In the interest of staying organized, it is considered good practice to add a prefix to your instance names according to what kind of object they are. For example, I give my Buttons the “btn” prefix, and my Text Fields the “txt” prefix. Some people even give their Movie Clips the “mc” prefix… but I usually ignore that one ;-)

Time to Code

OK, open up your Actions panel for frame 1 of your main project timeline.

Start by declaring two variables: the currentScore, which will keep track of how much score to display in the txtScore field, and the saveDataObject, which is our Shared Object, and the focus of the tutorial.

var saveDataObject:SharedObject;
var currentScore:int;

Next, we need to create the init() function, and call it once to initialize the project. I’ve included everything in this function that it will include in the final version, so don’t be startled if you see something in there that we haven’t even discussed yet. I’ve commented everything, explaining as you read along. I’ll also explain afterwards.

init(); // this line goes directly beneath the variables

function init():void{ // call once to set everything up

     saveDataObject = SharedObject.getLocal("test"); // give the save data a location
     currentScore = 0; //start with 0 score

     btnAdd.addEventListener(MouseEvent.CLICK, addScore); // clicking on +1
     btnSave.addEventListener(MouseEvent.CLICK, saveData); // clicking on Save

     if(saveDataObject.data.savedScore == null){ // checks if there is save data
          trace("No saved data yet."); // if there isn't any data on the computer...
          saveDataObject.data.savedScore = currentScore; // ...set the savedScore to 0
     } else {
          trace("Save data found."); // if we did find data...
          loadData(); // ...load the data
     }

     updateScoreText(); // finally, update the text field
}

The first thing we do in this function is use the SharedObject.getLocal function to tell the saveDataObject where to look for and save the data file. Next, we set the currentScore to 0, for the obvious reason that we are initializing the game with default values. The next two lines add Event Listeners to the two buttons. The btnAdd button will call the addScore function when it is clicked, and the btnSave button will call the saveData function.

The next little section of code might look a little more complicated, but all it does is check whether or not there is previous save data on the computer. How can we figure out whether there is save data or not? Well, one way is to check if our savedScore property in the shared object’s data is null. If we have saved data previously, that data will have a value other than null, so the conditional will be false, and we’ll call the loadData function. But if we never set the savedData to be anything, it will be null, so we won’t load the data. Instead, we’ll just start by setting the score to 0.

Finally, we call a function to update the txtScore field.

Here are the 4 other functions which we reference in the initialization. This is the entire remainder of the code in our demo program. You can add these functions anywhere — I just put them beneath the init function.


function addScore(e:MouseEvent):void{
     currentScore += 1; // add 1 to the score
     updateScoreText(); // update the textfield
}

function saveData(e:MouseEvent):void{
     saveDataObject.data.savedScore = currentScore; // set the saved score to the current score
     trace("Data Saved!");
     saveDataObject.flush(); // immediately save to the local drive
     trace(saveDataObject.size); // this will show the size of the save file, in bytes
}

function loadData():void{
     currentScore = saveDataObject.data.savedScore; // set the current score to the saved score
     trace("Data Loaded!");
}

function updateScoreText():void
{
     txtScore.text = ("Score: " + currentScore); // set the text property of the txtScore
     trace("Score text updated");
}

These functions should be fairly self-explanatory, based off of the theory we discussed earlier. If you have any questions about it, feel free to leave a comment!

If you want check out the source file, you can find it here.

Hopefully this has given you a solid understanding of how saving and loading works in AS3. If you’re looking for another source to learn about the SharedObject, you might want to check out this post by Michael James Williams; or, if you’re feeling ambitious you can try reading Adobe’s official reference doc on it, here, for much more technical information. Try expanding this topic to apply to your other games, maybe even to save your score in the Pong tutorial ;-)

Cheers,

Ben Reynolds

About these ads

45 comments on “Saving and Loading in Actionscript 3 (Mini-Lesson)

  1. Jaime says:

    Oh oh! You made the save game post :)! Sweetness.

  2. Josh Woosley says:

    Hello, nice mini tutorial! I need a lot of help concerning the development of my game and I would very appreciate your help. Link: http://www.kongregate.com/games/freakymrq/a-game-alpha I need a better system for following the character and I cannot for the life of me figure out the coding for enemy ai that attack. I plan on adding your parallax effect to my game but I need help with the menu system as well. Sorry for all the help requests but I have a hard time finding any help online. Any help is appreciated, Josh

    • I think you made the player as well as the background move up while jumping and you moved the player going down due to gravitation and not the gravitation (its very annoying) , you should just move the background and keep the player at one place, like Ben Renolds did in his Platformer so that the player does not go of of sight.

      • Josh Woosley says:

        So you think I should remove all my coding making the character move and just have the background move instead? Will this affect my enemy ai? Thanks for the reply, Josh

        • Ben Reynolds says:

          Hi Josh. Although I’m not quite sure how you programmed your player movement, I agree with Palash that your easiest, most fail-proof method would probably be rewriting it according to my tutorials. I’m sure there are other ways to do it, but if you follow along with my tuts you are sure to get a similar, working product as in my demos. I’ve tried a few different methods for scrolling backgrounds, and I think the method I came up with is the easiest to implement. The impact on the rest of your code (such as AI) would be that the player never moves, so anywhere in your code that uses that value would probably need to take the scrollX and scrollY values of the background instead.

          Hope that helps,
          Ben

  3. Renz says:

    Wow this tutorial is nice! Cant wait for new one!

  4. Renz says:

    I need help please have a comment in my game and tell me what you can say thank you I will appreciate any comment you post I know it will help us thank you.

    Here’s the link : http://www.kongregate.com/games/mojmon11/stoichen-elements

    • Ben Reynolds says:

      Are you looking for advice on the technical side (bugs, code, etc), or just general game suggestions/advice? I’ll definitely leave you some feedback — just making sure I know what you are looking for. Good luck on your game!

      • Renz says:

        Thank You Ben, yes I am looking for advice on the technical side cause as you can see it has a lot of bugs. Thank you ben I have learn a lot from you but still I have to learn more.

  5. HitlaH says:

    Ben??? Are you still making the next tutorial?? Hope I think it will be really Good! :D

    • Ben Reynolds says:

      Hi there. Yes, I am making the next tutorial :)

      I just got a new computer (a MacBook Pro), and I am trying to transfer all of my files over.

      Sorry for the delay, I hope to post the next tutorial this weekend.

  6. danman113 says:

    Wow, amazing tutorial. Something that seems really complex turned out to be simple, thanks for revealing this!

  7. Jesse Herwig says:

    Your Tutorials are awesome.
    Could you make one about animating a character for a platformer (walking, rolling etc.)

  8. Steven says:

    May I suggest a preloader for the next mini tutorial? =P I’d like to see one that goes into things like showing the percent loaded, start both automatically or with a play button, or one that is a bit more complicated then a simple bar? :D

  9. Steven says:

    or maybe working with sound? =)

  10. Steven says:

    Thanks for the link! :D

  11. Jaime says:

    Ben, I had a question. If I want the game to save automatically – say like on every 5 minutes, would I set the saveDataObject.flush() inside of a timer?

    • Ben Reynolds says:

      Yes… almost. I’ve never actually used this in a game myself, but it sounds like a good idea. I’m assuming you know how to set up a timer that repeats every 5 minutes, forever (if not, there’s a nice tutorial here: http://www.republicofcode.com/tutorials/flash/as3timer/). Each time the timer triggers, you would want to flush the saveDataObject, but make sure that you also update the data on the saveDataObject to be equal to the current data, otherwise you will be just saving the same old data every 5 minutes. In this example, I would call the entire saveData() function every time the timer triggers.

      • Jaime says:

        Yes, I know how to set up timers, but thanks for the link. I can always use it if I mess the timer up somehow. Made a note about updating the data. I would have probably forgot to do that ;)

        Thanks!

  12. Gary says:

    Great tutorial, been looking for something to explain this properly for ages.

    Cheers

  13. Gary says:

    …Also, a reset/restart game tutorial would be handy! Ive been trying to figure out the best way to remove all objects and listeners from stage after clicking a restart button (after game over etc). Im using multiple classes and theres always something left over causing errors. Cheers

  14. Daikuro says:

    Thank you much for this information, I am an intermediate amateur graphic/web designer and I want to get into the codey-side of game design.

    I’d like to ask your opinion on storing Save data in XML files. As “my first flash game” project I wanted to make a simple turn-based RPG battle (only one battle for now) that loads it’s data from an XML file. Obviously the XML file would include things like HP, MP, Stats, Equipment, Inventory, and the party composition.

    I know it’s possible to also write to an XML file from AS3 and I wanted your opinion on it.

    Thank you,
    -Daikuro

  15. Ciara says:

    Hi, I really hope somebody is still reading these posts. I’ve just about finished my platform game but want the ability to save levels, how can i apply the sharedObject for saving played game levels?

    • Ben Reynolds says:

      Do you mean you want the player’s progress to be saved (which levels they have completed and which one they are currently up to)?

      You could just create a new “variable” in the sharedObject, and set it to the currentLevel:
      saveDataObject.data.currentLevel = currentLevel;

      Then when you start the game, instead of setting the level to 1, when you start the game set currentLevel = saveDataObject.data.currentLevel, and then run through a series of if/else conditionals to go to the appropriate level.
      if(currentLevel == 1){
      gotoLevel1();
      } else if(currentLevel == 2){
      gotoLevel2();

      } else if… etc

      • Ciara says:

        Thanks for replying and for the brilliant platformer turtorials, seriously saved my college project :) yeah thats what i wanted to save but right now I have an intro screen with a play btn that goes straight to level one what i would like is for it to go to a levels screen with an image icon for each level (1-20) with all the unplayed levels icons to be lower alpha and the played levels to be 100% and then the player could click only on a level that they have completed and the others would be locked until completed. I hope that makes sense, I’ve barely slept in days trying to finish this game in time for handup date!
        if you could help me out one last time its hugely appreciated
        thx :)

        • Ben Reynolds says:

          Yeah, that makes sense. I haven’t tested this myself but I’m pretty sure you could do the following: create an array for the levels that are unlocked.

          var unlockedLevels:Array = [1]; //right now only level 1 is unlocked

          When you complete a level:
          unlockedLevels.push(currentLevel+1); //unlocks the next level

          When you are in the menu screen, check if a level is unlocked by checking if its number is the array:
          if(unlockedLevels.indexOf(thisLevelNumber) < 0){ //thisLevelNumber isn't in the array
          //lower the alpha of this level select button
          } else {
          //the level is unlocked, so show this button completely
          }

          Then for saving and loading, just proceed like you would for any variable.

          Saving:
          saveDataObject.data.unlockedLevels = unlockedLevels;

          Loading:
          unlockedLevels = saveDataObject.data.unlockedLevels;

          Hopefully this works. Good luck with your project! Let me know how it goes :-)

  16. som says:

    Nice tutorial; however, when I increment the score, save and refresh, the score returns to 0 in Firefox and Chrome. I’ve written similar code for my own stuff that works when it runs locally, but not from a website. Just trying to figure out why. Using a recent Mac Pro running OS 10.7.4. Works with Safari.

  17. André Alves de Oliveira says:

    Hi, I`m creating a point and click game and I`m trying to add a save and a load button, based on your code i`ve did this code but it didin`t work, could you help me?

    var mySharedObject:SharedObject = SharedObject.getLocal(“save”);

    saveGame.addEventListener(MouseEvent.CLICK, saveCurrentFrame);

    function saveCurrentFrame(event:MouseEvent):void

    {
    mySharedObject.data.lastframe= this.currentFrame;
    mySharedObject.flush();
    }

    loadGame.addEventListener(MouseEvent.CLICK, getLastFrame);

    function getLastFrame():int

    {
    return mySharedObject.data.lastframe;
    }

    Best.

    André

  18. aosteklov says:

    thank you so much! this was very helpfull!

  19. hellohellohello says:

    is it possible to have multiple save slot for user to save? so user can load different saved file.

  20. Lay Kuan says:

    hi, the game i need to create has multiple scenes. I would like to ask how i need to write in the AS3 to save the game when the user want to stop and back to front scene, and then load the game where the user stops. Thanks.

  21. Daphne says:

    I know this is over a year old, but I just wanted to comment and say thanks! I’m glad you made a tutorial like this, because I was trying to save data from a text box where the user types in the information, and thanks to you, I was able to take the concepts of this tutorial and make them work for me. Thanks again!

  22. Daphne says:

    I know this is over a year old, but I just wanted to comment and say thanks! I’m glad you made a tutorial like this, because I was trying to save data from a text box where the user types in the information, and thanks to you, I was able to take the concepts of this tutorial and make them work for me. Thanks again!

  23. Knut Harald says:

    Had been delaying this forever since I thought it would be tough work… but 30 min and now my game can save! nice.

  24. anonymous100 says:

    this may not sound very nice but im trying to “cheat” at a game that I like quite a lot because its slightly difficult and I want to be able to do certain things only when I want to. I don’t really know much a bout actionscript, so im a complete beginner to this kind of stuff. however, ive found a bunch of stuff that seems to be linked to the save files, but im not quite sure what to make of it. it starts out with data, but then down the rank of equal signs it comes don to arrays. I really have no idea what to do so any general advice you could give on the subject of what exactly “data” and “arrays” are would be appreciated.

  25. nabeelfarooqui says:

    I dont think that you read these anymore but if you do then could you tell me the difference between your style of coding (using Actions panel) and someone elses (using .as class files, what are classes? I don’t understand these things!!!!!!)

  26. CMS says:

    Bravo!! Bravo!!

  27. Nathan says:

    Please Help I’ve been trying to implement this inside my game for awhile now. But the problem is i dont know how to access textfields in a separate class that show the bestScore and finalScore. I posted full details on what I need help on here: http://stackoverflow.com/questions/21808680/how-to-use-sharedobject-with-two-document-classes-in-as3/21810589?noredirect=1#21810589

    Please any help will be appreciated thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s