Saturday, February 27, 2010

Simple Settings Manager for XNA

Being able to load settings into a game is a must. There are a number of ways to accomplish this. My current method works well enough for now, although it needs a bit of work in a few areas. I accomplish this by creating a series of settings classes that can be serialized into XML and back again at run time using my simple serializer.

Settings Manager

public class SettingsManager
{
    const string Extension = ".xml";
    const string Directory = "Content\\Settings\\";

    /// <summary>
    /// Loaded settings - Not currently implemented
    /// </summary>
    //SerializableDictionary<string, SettingsBase> _settings;

    /// <summary>
    /// Constructor
    /// </summary>
    public SettingsManager()
    {
    }

    /// <summary>
    /// Load a settings file
    /// </summary>
    public T Load<T>()
    {
        Type t = typeof(T);
        return Load<T>(t.Name);
    }

    /// <summary>
    /// Attempt to load a settings file.  If not found, it will
    /// load a new, default instance of the settings class.
    /// </summary>
    public T Load<T>(string name)
    {
        try
        {
            return Serializer.Read<T>(
                SettingsManager.Directory + 
                name +
                SettingsManager.Extension);
        }
        catch (Exception e)
        {
            e = null;
            Type t = typeof(T);
            return (T)Activator.CreateInstance(t);
        }
    }

    /// <summary>
    /// Save a settings object
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public void Save<T>(T o)
    {
        Type t = typeof(T);
        Save<T>(o, t.Name);
    }

    /// <summary>
    /// Save a settings object
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="file_name"></param>
    public void Save<T>(T o, string name)
    {
        Serializer.Write<T>(
            o,
            SettingsManager.Directory + name + SettingsManager.Extension);
    }
}

The basic idea is that we can load and save settings files either based on an arbitrary name or, for simplicity, the settings class Type.Name. This is still a rough class - it assumes a lot about the settings files being loaded such as the files being serializable. I currently have a simple class that settings files inherit from:

Settings Base

[Serializable]
public abstract class SettingsBase
{
}

More functionality could be added here such as a Save() function that allowed settings objects to save themselves via the SettingsManager. The only special thing in this class is adding the [Serializable] tag at the top to ensure that all inheriting objects get this.

Simple Settings Example

public class PlayerSettings : SettingsBase
{
    public int Id;
    public string Name;

    public PlayerSettings()
    {
        Id = 1;
        Name = "Spartacus";
    }
}

Now, the settings manager can be used to load/save this.

// Load default settings
PlayerSettings ps = settingsManager.Load<PlayerSettings>();

// Change something
ps.Name = "Hercules";

// Save with default name
settingsManager.Save<PlayerSettings>(ps);

Future Improvements

  • SettingsManager does not ensure that loaded files inherit from SettingsBase at all.
  • SettingsManager does not track previously loaded settings files. Tracking and storing loaded files would prevent costly file IO, deserialization and reflection.
  • Settings classes assume that the constructor will set the default settings.

No comments:

Post a Comment