Loading and Save Highscore XML/IsolatedStorage Tutorial

To display and high scores in XNA, we must first create a format to store the high scores. Then the high scores need a place to be physically stored. Unfortunately, there are two different methods for XBOX and Windows (possibly Windows Phone7 too).

Using the following includes which can be trimmed to your specific needs, I used the following - note that the system.io.serialization, will have to be imported as a reference in your XBOX project file.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Storage;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using System.IO;

Here is an example of the structure to hold high score data, this structure goes inside of "public class Game1 : Microsoft.Xna.Framework.Game" for example.

       //Stuff for HighScoreData
        public struct HighScoreData
        {
            public string[] PlayerName;
            public int[] Score;

            public int Count;

            public HighScoreData(int count)
            {
                PlayerName = new string[count];
                Score = new int[count];

                Count = count;
            }
        }

Also add these variables following the above

       /* More score variables */
        HighScoreData data;
        public string HighScoresFilename = "highscores.dat";
        int PlayerScore = 0;
        string PlayerName;
        string scoreboard;

        // String for get name
        string cmdString = "Enter your player name and press Enter";
        // String we are going to display – initially an empty string
        string messageString = "";

Inside of "public Game1()", add the following:

           #if XBOX
                this.Components.Add(new GamerServicesComponent(this));
            #endif

Inside of "protected override void Initialize()", you need to determine if the XML file exists and act accordingly. Add the following code above base.initialize():

           // Get the path of the save game
            string fullpath = "highscores.dat";

            // Check to see if the save exists
#if WINDOWS
            if (!File.Exists(fullpath))
            {
                //If the file doesn't exist, make a fake one...
                // Create the data to save
                data = new HighScoreData(5);
                data.PlayerName[0] = "neil";
                data.Score[0] = 2000;

                data.PlayerName[1] = "shawn";
                data.Score[1] = 1800;

                data.PlayerName[2] = "mark";
                data.Score[2] = 1500;

                data.PlayerName[3] = "cindy";
                data.Score[3] = 1000;

                data.PlayerName[4] = "sam";
                data.Score[4] = 500;

                SaveHighScores(data, HighScoresFilename, device);
            }
#elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!iso.FileExists(fullpath))
                {
                    //If the file doesn't exist, make a fake one...
                    // Create the data to save
                    data = new HighScoreData(5);
                    data.PlayerName[0] = "neil";
                    data.Score[0] = 2000;

                    data.PlayerName[1] = "shawn";
                    data.Score[1] = 1800;

                    data.PlayerName[2] = "mark";
                    data.Score[2] = 1500;

                    data.PlayerName[3] = "cindy";
                    data.Score[3] = 1000;

                    data.PlayerName[4] = "sam";
                    data.Score[4] = 500;

                    SaveHighScores(data, HighScoresFilename, device);
                }
            }

#endif

Now create the SaveHighScores function, note the device parameter is extraneous now and unneeded. However, it may prove useful to others. This function creates a save file and creates the initial data array.

      /* Save highscores */
        public static void SaveHighScores(HighScoreData data, string filename, StorageDevice device)
        {
            // Get the path of the save game
            string fullpath = "highscores.dat";

            #if WINDOWS
            // Open the file, creating it if necessary
            FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate);
            try
            {
                // Convert the object to XML data and put it in the stream
                XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                serializer.Serialize(stream, data);
            }
            finally
            {
                // Close the file
                stream.Close();
            }
           
            #elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
                {
               
                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fullpath, FileMode.Create, iso))
                    {

                        XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                        serializer.Serialize(stream, data);

                    }

                }
           
            #endif
        }

Now you can use this function to load highscores

       /* Load highscores */
        public static HighScoreData LoadHighScores(string filename)
        {
            HighScoreData data;

            // Get the path of the save game
            string fullpath = "highscores.dat";

            #if WINDOWS
           
            // Open the file
            FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate, FileAccess.Read);
            try
            {
                // Read the data from the file
                XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                data = (HighScoreData)serializer.Deserialize(stream);
            }
            finally
            {
                // Close the file
                stream.Close();
            }
           

            return (data);
           
            #elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fullpath, FileMode.Open,iso))
                {
                    // Read the data from the file
                    XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                    data = (HighScoreData)serializer.Deserialize(stream);
                }
            }

            return (data);

            #endif

        }

Use this function to save the player's score whenever you need to. Note I call a function inside of a Score class. This function can be called anywhere using SaveHighScore().

       /* Save player highscore when game ends */
        private void SaveHighScore()
        {
            // Create the data to saved
            HighScoreData data = LoadHighScores(HighScoresFilename);

            int scoreIndex = -1;
            for (int i = data.Count - 1; i > -1; i--)
            {
                if (score.getScore() >= data.Score[i])
                {
                    scoreIndex = i;
                }
            }

            if (scoreIndex > -1)
            {
                //New high score found ... do swaps
                for (int i = data.Count - 1; i > scoreIndex; i--)
                {
                    data.PlayerName[i] = data.PlayerName[i - 1];
                    data.Score[i] = data.Score[i - 1];
                }

                data.PlayerName[scoreIndex] = PlayerName; //Retrieve User Name Here
                data.Score[scoreIndex] = score.getScore(); // Retrieve score here

                SaveHighScores(data, HighScoresFilename, device);
            }
        }

        /* Iterate through data if highscore is called and make the string to be saved*/
        public string makeHighScoreString()
        {
            // Create the data to save
            HighScoreData data2 = LoadHighScores(HighScoresFilename);

            // Create scoreBoardString
            string scoreBoardString = "Highscores:\n\n";

            for (int i = 0; i<5; i++) // this part was missing (5 means how many in the list/array/Counter)
            {
                        scoreBoardString = scoreBoardString + data2.PlayerName[i] + "-" + data2.Score[i] + "\n";
            }
            return scoreBoardString;
        }

General code ideas were expanded on from here: http://xnaessentials.com/tutorials/highscores.aspx

Blog tags: 

Comments

xml file is empty

After starting my game, it creates the highscores.dat file but it is still empty so i get an error when loading the file. What can be the problem?

XML File Error

Very helpful tutorial but I am encountering an error while testing my game. I've been using your example data: neil, shawn etc. However if I get a score of, say, 2100 as 'Matt', the XML file looks like this: Matt Matt neil shawn mark 2400 2400 2000 1800 1500 5 > It seems to be adding in 'Matt' twice, and also adding an extra > to the end of the file, which causes my program to crash as it tried to load the high scores. Any help would be greatly appreciated.

PC

I'm on PC. It calls savehighscore first, and then I call the load function to print out the results which is where it chucks me the error.

done it

Just to say I have done it! and is working for noobs like me the last past goes: for (int i = 0; i

Hey don't suppose you fancy

Hey don't suppose you fancy sending me the corrected code? I can't get it to even create the file there are no errors but its also not creating the file. doesn't seem to be running theif (!File.Exists(fullpath)) bit. Any help would be greatly appreciated. been trying to get high scores sorted for ages but its almost impossible to find any example for xna 4.0. Thanks in advanced Stephen

Sorted it nearly

have sorted it now however when i get a high score it is replacing all the scores lower than the high score, so if i get a score higher than all the others it every score will be the new score. Any idea how to correct this?

Cheers

Got it working had to change data.PlayerName[i] = data.PlayerName[i - 1]; and data.Score[i] = data.Score[i -1]; to just i. Also changed the FileMode.OpenOrCreate to FileMode.Create in the SaveHighScores so it overwrites it each time as when the data being written was smaller than the previous data the xml file got corrupted.

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <python> <c>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.