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
Grab your movement component, and cut out all the _sceneObject stuff, including the on Register method, unregister, etc, make it look like this...
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.
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
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.
