Game Development Community

dev|Pro Game Development Curriculum

Saving Games in TorqueX, on your 360 or PC

by Will O-Reagan · 06/23/2007 (1:22 pm) · 0 comments

This quick and dirty sample of how to get save game features working on your XBox and PC.

First Open a StarterGame, find your game.cs, and make your begin run look like this
protected override void BeginRun()
        {
            base.BeginRun();
            
            
#if XBOX360
            //Create an XboxStorage Device Object, that will keep track of our Device, and make sure it does what we want.
XboxStorageDevice myXboxStorage = new XboxStorageDevice();
            //Name it, so we can find it in code using the TorqueObjectDatabase
            myXboxStorage.Name = "MyXboxStorage";
            //Give it a tick, so it can fire off saves and loads, after the device has been found.
            ProcessList.Instance.AddTickCallback(myXboxStorage);

#endif


            //Load our Scene, just a single ggPlayerObject, offscreen, with no velocity or anything. 
            //(just apply to it a world Limit and "Rigid Physics" for world Limit Collision Resolution)
            SceneLoader.Load(@"data\levels\levelData.txscene");
            //Create Our Save LoadObject
            SaveLoad _saveLoad = new SaveLoad();
            //name the object, so we can find it using the TorqueObjectDatabase
            _saveLoad.Name = "SaveLoad";
            //Activate an input map, so it can load and unload our game as well as move our "player buddy" around
            _saveLoad._SetupInputMap(_saveLoad, 0, "gamepad" + 0, "keyboard");
            //Load Initial Data, so we can have the option of loading a "New Game"
            _saveLoad._loadInitialData();
            //Give it a tick callback, so it can move our "player buddy" around
            ProcessList.Instance.AddTickCallback(_saveLoad);
        }


Grab your movement component, and cut out all the _sceneObject stuff, including the on Register method, unregister, etc, make it look like this...

using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

using GarageGames.Torque.Core;
using GarageGames.Torque.T2D;
using GarageGames.Torque.Sim;
using GarageGames.Torque.Platform;

namespace StarterGame
{
    //Note, we have changed "TorqueComponent" to "TorqueObject"
    public class SaveLoad : TorqueObject, ITickObject
    {
        //======================================================
        #region Constructors
        #endregion

        //======================================================
        #region Public properties, operators, constants, and enums

        #endregion

        //======================================================
        #region Public Methods
        public void InterpolateTick(float k)
        {
        }

        public void ProcessTick(Move move, float elapsed)
        {
            if (_player != null)
            {

                if (move != null)
                {
                    if (move.Sticks[0].X > 0)
                        _player.Physics.VelocityX += 1;
                    if (move.Sticks[0].X < 0)
                        _player.Physics.VelocityX -= 1;
                    if (move.Sticks[0].Y > 0)
                        _player.Physics.VelocityY += 1;
                    if (move.Sticks[0].Y < 0)
                        _player.Physics.VelocityY -= 1;
                }
            }

        }
        public void _saveGame()
        {

            StorageSystem storageSystem = new StorageSystem();
            StorageSystem.PlayerData playerData = new StorageSystem.PlayerData();
            _player = (T2DSceneObject)TorqueObjectDatabase.Instance.FindObject("ggPlayer");
            if (_player != null)
            {
                playerData.AngularVelocity = _player.Physics.AngularVelocity;
                playerData.Rotation = _player.Rotation;
                playerData.Velocity = _player.Physics.Velocity;
                playerData.position = _player.Position;
                storageSystem.SavePlayerData(playerData, "ExpertSaveSample", "SavedGame.vrd");
            }


        }
        public void _loadSavedGame()
        {
            StorageSystem storageSystem = new StorageSystem();
            StorageSystem.PlayerData loadPlayerData = new StorageSystem.PlayerData();
            loadPlayerData = storageSystem.LoadPlayerData("ExpertSaveSample", "SavedGame.vrd");
            if (loadPlayerData.Velocity != null)
            {
                T2DSceneObject _oldPlayer = (T2DSceneObject)TorqueObjectDatabase.Instance.FindObject("ggPlayer");
                _oldPlayer.MarkForDelete = true;
                _player = (T2DSceneObject)(TorqueObjectDatabase.Instance.FindObject("ggPlayerObject") as T2DSceneObject).Clone();
                TorqueObjectDatabase.Instance.Register(_player);
                _player.Name = "ggPlayer";
                _player.Position = loadPlayerData.position;
                _player.Rotation = loadPlayerData.Rotation;
                _player.Physics.AngularVelocity = loadPlayerData.AngularVelocity;
                _player.Physics.Velocity = loadPlayerData.Velocity;
            }

        }
        public void _loadNewGame()
        {
            StorageSystem storageSystem = new StorageSystem();
            StorageSystem.PlayerData loadPlayerData = new StorageSystem.PlayerData();
            loadPlayerData = storageSystem.LoadPlayerData("ExpertSaveSample", "NewGame.vrd");
            T2DSceneObject _oldPlayer = (T2DSceneObject)TorqueObjectDatabase.Instance.FindObject("ggPlayer");
            if (_oldPlayer != null)
            {
                _oldPlayer.MarkForDelete = true;
            }
            _player = (T2DSceneObject)(TorqueObjectDatabase.Instance.FindObject("ggPlayerObject") as T2DSceneObject).Clone();
            TorqueObjectDatabase.Instance.Register(_player);
            _player.Name = "ggPlayer";
            _player.Position = loadPlayerData.position;
            _player.Rotation = loadPlayerData.Rotation;
            _player.Physics.AngularVelocity = loadPlayerData.AngularVelocity;
            _player.Physics.Velocity = loadPlayerData.Velocity;

        }
        public void _loadInitialData()
        {
            StorageSystem storageSystem = new StorageSystem();
            StorageSystem.PlayerData playerData = new StorageSystem.PlayerData();
            playerData.Velocity = new Vector2(0, 0);
            playerData.position = new Vector2(0, 0);
            playerData.AngularVelocity = 0;
            playerData.Rotation = 0;
            storageSystem.SavePlayerData(playerData, "ExpertSaveSample", "NewGame.vrd");
        }
        #endregion

        //======================================================
        #region Private, protected, internal methods


        void _OnBackButton(float val)
        {
            if (val > 0.0f)
                Game.Instance.Exit();
        }


        public void _SetupInputMap(TorqueObject player, int playerIndex, String gamePad, String keyboard)
        {
            // Set player as the controllable object
            PlayerManager.Instance.GetPlayer(playerIndex).ControlObject = player;

            // Get input map for this player and configure it
            InputMap inputMap = PlayerManager.Instance.GetPlayer(playerIndex).InputMap;

            int gamepadId = InputManager.Instance.FindDevice(gamePad);
            if (gamepadId >= 0)
            {
                inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.LeftThumbX, MoveMapTypes.StickAnalogHorizontal, 0);
                inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.LeftThumbY, MoveMapTypes.StickAnalogVertical, 0);
                inputMap.BindAction(gamepadId, (int)XGamePadDevice.GamePadObjects.Back, _OnBackButton);
                inputMap.BindCommand(gamepadId, (int)XGamePadDevice.GamePadObjects.A, null, _saveGame);
                inputMap.BindCommand(gamepadId, (int)XGamePadDevice.GamePadObjects.X, null, _loadNewGame);
                inputMap.BindCommand(gamepadId, (int)XGamePadDevice.GamePadObjects.Y, null, _loadSavedGame);
            }

            // keyboard controls
            int keyboardId = InputManager.Instance.FindDevice(keyboard);
            if (keyboardId >= 0)
            {
               //sorry, no keyboard commands yet
            }
        }
        #endregion

        //======================================================
        #region Private, protected, internal fields
        T2DSceneObject _player;
        #endregion
    }
}

Next, open up your "levelData" in your TXB editor. Remove the movement component if its not gone already. Drag the gg logo outside the viewable area. Mark it as a template. Give it a WorldLimit, and apply rigid physics so we can get some angular velocity on our bounces. (Remeber to size the world limit to the size of your screen/camera), (so we can see whats going on!) Name it "ggPlayerObject".

Finally, Create two new classes, with the following code in each.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;


using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using GarageGames.Torque.Core;
using GarageGames.Torque.T2D;
using GarageGames.Torque.Sim;
using GarageGames.Torque.Platform;

namespace StarterGame
{
    class XboxStorageDevice : TorqueObject, ITickObject
    {
        #region Constructors
        #endregion
        #region Public properties, operators, constants, and enums
        public bool DeviceFound
        {
            get { return _deviceFound; }
            set { _deviceFound = value; }
        }
        public StorageDevice Device
        {
            get { return device; }
            set { device = value; }
        }
        #endregion
        #region Public Methods
        public void InterpolateTick(float k)
        {
        }
        public void ProcessTick(Move move, float elapsed)
        {
            if (_savePending && _deviceFound != true)
            {
                if (result != null)
                {
                    if (result.IsCompleted)
                    {
                        device = StorageDevice.EndShowStorageDeviceGuide(result);
                        if (device.IsConnected)
                        {
                            _deviceFound = true;
                            _savePending = false;
                            StorageSystem storageSystem = new StorageSystem();
                            storageSystem.SavePlayerData(_playerData, _containerName, _filename);
                        }
                    }
                }
            }
            if (_loadPending && _deviceFound != true)
            {
                if (result != null)
                {
                    if (result.IsCompleted)
                    {
                        device = StorageDevice.EndShowStorageDeviceGuide(result);
                        if (device.IsConnected)
                        {
                            _deviceFound = true;
                            _loadPending = false;
                            SaveLoad _saveLoad = (SaveLoad)TorqueObjectDatabase.Instance.FindObject("SaveLoad");
                            if (_filename == "NewGame.vrd")
                                _saveLoad._loadNewGame();
                            else if (_filename == "SavedGame.vrd") 
                            _saveLoad._loadSavedGame();
                        }
                    }
                }
            }
        }
        public void FindDeviceAndAttemptSave(StarterGame.StorageSystem.PlayerData playerData, string containerName, string filename)
        {
            _savePending = true;
            _playerData = playerData;
            _containerName = containerName;
            _filename = filename;
            result = StorageDevice.BeginShowStorageDeviceGuide(PlayerIndex.One, null, null);

        }
        public void FindDeviceAndAttemptLoad(string containerName, string filename)
        {
            _loadPending = true;
            _containerName = containerName;
            _filename = filename;
            result = StorageDevice.BeginShowStorageDeviceGuide(PlayerIndex.One, null, null);

        }
        #endregion
        #region Private, protected, internal methods
#endregion
        #region Private, protected, internal fields
        bool _deviceFound = false;
        StorageDevice device;
        IAsyncResult result;
        string _containerName = "";
        StarterGame.StorageSystem.PlayerData  _playerData;
        string _filename = "";
        bool _savePending = false;
        bool _loadPending = false;
        #endregion
    }
}

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

using GarageGames.Torque.Core;
using GarageGames.Torque.T2D;
using GarageGames.Torque.Sim;
using GarageGames.Torque.Platform;


using System.IO;
using System.Xml.Serialization;

namespace StarterGame
{
    public class StorageSystem
    {
        [Serializable]
        public struct PlayerData
        {
            //Assign all relevent data, so we can update our game accurately 
            public float AngularVelocity;
            public float Rotation;
            public Vector2 position;
            public Vector2 Velocity;
        } 
        public void SavePlayerData(PlayerData playerData, string containerName, string fileName)
        {
           
          #if XBOX360
             XboxStorageDevice _xboxStorage = (XboxStorageDevice)TorqueObjectDatabase.Instance.FindObject("MyXboxStorage");
             if (_xboxStorage.DeviceFound != true)
             {
                 _xboxStorage.FindDeviceAndAttemptSave(playerData, containerName, fileName);
             }
             else
             {
                 StorageDevice device = _xboxStorage.Device;
                 // Open a storage container 
                 StorageContainer container = device.OpenContainer(containerName);
                 // Get the path of the save game 
                 string tempFileName = Path.Combine(container.Path, fileName);
                 // Open the file, creating it if necessary 
                 FileStream stream = File.Open(tempFileName, FileMode.OpenOrCreate);
                 // Convert the object to XML data and put it in the stream 
                 XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
                 serializer.Serialize(stream, playerData);
                 // Close the file 
                 stream.Close();
                 // Dispose the container, to commit changes 
                 container.Dispose();
             }
#endif
#if !XBOX360
            StorageDevice device = StorageDevice.ShowStorageDeviceGuide();
            // Open a storage container 
            StorageContainer container = device.OpenContainer(containerName);
            // Get the path of the save game 
            string tempFileName = Path.Combine(container.Path, fileName);
            // Open the file, creating it if necessary 
            FileStream stream = File.Open(tempFileName, FileMode.OpenOrCreate);
            // Convert the object to XML data and put it in the stream 
            XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
            serializer.Serialize(stream, playerData);
            // Close the file 
            stream.Close();
            // Dispose the container, to commit changes 
            container.Dispose();
#endif

        }
        public PlayerData LoadPlayerData(string containerName, string fileName)
        {
            PlayerData playerData = new PlayerData();
              #if XBOX360
            XboxStorageDevice _xboxStorage = (XboxStorageDevice)TorqueObjectDatabase.Instance.FindObject("MyXboxStorage");  
                StorageDevice device = _xboxStorage.Device;      
#endif
#if !XBOX360          
            StorageDevice device = StorageDevice.ShowStorageDeviceGuide();
#endif
            // Open a storage container 
            StorageContainer container = device.OpenContainer(containerName);
            // Get the path of the save game 
            string tempFileName = Path.Combine(container.Path, fileName);
            // Check to see if the save exists 
            if (!File.Exists(tempFileName))
                // Notify the user there is no save 
                return playerData;
            // Open the file 
            FileStream stream = File.Open(tempFileName, FileMode.OpenOrCreate, FileAccess.Read);
            // Read the data from the file 
            XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));
            playerData = (PlayerData)serializer.Deserialize(stream);
            // Close the file 
            stream.Close();
            // Dispose the container 
            container.Dispose();
            return playerData;
        }
  
    }
    
}

That should pretty much do it. Dont forget to add a reference to System.XML in your game.

My references, were mostly taken from the GSE Help, Contents. Check under Programming Guide, Storage.

Also...(http://www.virtualrealm.com.au/blogs/mykre/archive/2007/05/06/xna-storage-the-beginning.aspx)

And of course, the GG TX forums

You can save and load all 4 properties of the GG Logo, accross multiple games and loads on your XBox or PC. Now I'm going to go put this in MY game..

enjoy,

Heres a Sample Picture of what it might look like..


edit: removed dead links

About the author

I have a degree in dramatic art, and literature, from UC Santa Barbara. I've worked for a few studios, also at Animax Ent in 2008, and some smaller studios. Currently studying Computer Science at CSU Channel Islands.