Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

Issues in Application Architecture - Xna Tombstoning and Settings

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
3/13/2011 10:50:19 PM
XNA applications aren’t normally built around pages like Silverlight applications. If you wanted, however, you could certainly implement your own page-like structure within an XNA program. You’ll recall that the state of the phone’s Back button is checked during every call to the standard Update override. You can use this logic for navigational purposes as well as for terminating the program. But that’s something I’ll let you work out on your own.

An XNA program can also make use of the same PhoneApplicationService class used by Silverlight programs for saving transient state information during tombstoning. An XNA program can also use this class to install handlers for the four PhoneApplicationService events: Launching, Activated, Deactivated, and Closing. You’ll need references both to the Microsoft.Phone library (for PhoneApplicationService itself) and System.Windows (for the IApplicationService interface that PhoneApplicationService implements). Within the Game1.cs file you’ll want a using directive for Microsoft.Phone.Shell.

In the constructor of the Game1 class you can obtain the PhoneApplicationService instance associated with the application through the static PhoneApplicationService.Current property.

The Game class also defines a couple handy virtual methods named OnActivated and OnDeactivated that are also useful for handling tombstoning. The OnActivated method is called during launching and re-activation, and OnDeactivated is called during deactivation and program closing, much like the OnNavigatedTo and OnNavigatedFrom virtual methods of a Silverlight page.

The program uses the PhoneApplicationService events for saving and restoring application settings (a Color), and overrides of the OnDeactivated and OnActivated events for retaining transient data (the number of taps).

But I went a little further in providing a more generalized solution for application settings. I gave the XnaTombstoning project a dedicated Settings class that uses the more generalized features of isolated storage that involve real files rather than just simple settings. You’ll need a reference to System.Xml.Serialization library for this class as well using directives for the System.IO, System.IO.IsolatedStorage, and System.Xml.Serialization namespaces.

Example 1. Silverlight Project: XnaTombstoning File: Settings.cs (excerpt)
public class Settings
{
const string filename = "settings.xml";

// Application settings
public Color BackgroundColor { set; get; }

public Settings()
{
BackgroundColor = Color.Navy;
}

public void Save()
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = storage.CreateFile(filename);
XmlSerializer xml = new XmlSerializer(GetType());
xml.Serialize(stream, this);
stream.Close();
stream.Dispose();
}

public static Settings Load()
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
Settings settings;

if (storage.FileExists(filename))
{
IsolatedStorageFileStream stream =
storage.OpenFile("settings.xml", FileMode.Open);
XmlSerializer xml = new XmlSerializer(typeof(Settings));
settings = xml.Deserialize(stream) as Settings;
stream.Close();
stream.Dispose();
}
else
{
settings = new Settings();
}

return settings;
}
}

The idea here is that an instance of this Settings class itself is serialized and saved in isolated storage in the Save method, and then retrieved from isolated storage and deserialized in the Load method. Notice that the Load method is static and returns an instance of the Settings class.

When an instance of this Settings class is serialized, all its public properties are serialized. This class has exactly one public property of type Color named BackgroundColor but it would be very easy to add more properties to this class as the application develops and gets more sophisticated.

In the Save method, the area of isolated storage reserved for this application is obtained from the static IsolatedStorageFile.GetUserStoreForApplication method. This method returns an object of type IsolatedStorageFile but the name is a little misleading. This IsolatedStorageFile object is closer in functionality to a file system than a file. You use the object to maintain directories, and to create and open files. A call to CreateFile returns an IsolatedStorageFileStream which here is used with an XmlSerializer object to serialize and save the file.

The Load method is a bit more complex because it’s possible that the program is being run for the very first time and the settings.xml file does not exist. In that case, the Load method creates a new instance of Settings.

Notice the constructor that initializes the properties to their default values, which in this case only involves the single public property named BackgroundColor. If you add a second public property for another application setting at some point, you’ll want to also specify a default value of that property in the constructor. The first time you run the new version of the program, that new property will be initialized in the constructor, but the Load method will retrieve a file that doesn’t have that property, so the new version smoothly integrates with the previous version.

Here’s another consideration: This scheme only works if the properties representing application settings are serializable. For a more complex program, that might not be the case. For objects that are not serializable but still must be saved to isolated storage, you can still include a property for that object in this file but you’ll want to flag that property definition with the [XmlIgnore] attribute. The property will be ignored for serialization purposes. Instead you’ll need to handle that property with special code in the Save and Load methods.

The remainder of the XnaTombstoning project lets you tap the screen and responds by displaying a new random background color and a count of the number of taps. The background color is treated as an application setting (as is evident by its inclusion in the Settings class) and the number of taps is a transient setting.

Here’s an excerpt of the Game1 class showing the fields, constructor, and PhoneApplicationService events:

Example 2. Silverlight Project: XnaTombstoning File: Game1.cs (excerpt)
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

Settings settings;
SpriteFont segoe14;
Viewport viewport;
Random rand = new Random();
StringBuilder text = new StringBuilder();
Vector2 position;
int numTaps = 0;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";

// Frame rate is 30 fps by default for Windows Phone.
TargetElapsedTime = TimeSpan.FromTicks(333333);

TouchPanel.EnabledGestures = GestureType.Tap;

PhoneApplicationService appService = PhoneApplicationService.Current;
appService.Launching += OnAppServiceLaunching;
appService.Activated += OnAppServiceActivated;
appService.Deactivated += OnAppServiceDeactivated;
appService.Closing += OnAppServiceClosing;
}

. . .

void OnAppServiceLaunching(object sender, LaunchingEventArgs args)
{
settings = Settings.Load();
}

void OnAppServiceActivated(object sender, ActivatedEventArgs args)
{
settings = Settings.Load();
}

void OnAppServiceDeactivated(object sender, DeactivatedEventArgs args)
{
settings.Save();
}

void OnAppServiceClosing(object sender, ClosingEventArgs args)
{
settings.Save();
}
}

A Settings object named settings is saved as a field. The constructor attaches handlers for the four events of PhoneApplicationService and it is in the handlers for these events that the application settings are saved and loaded.

The LoadContent override contains nothing surprising:

Example 3. Silverlight Project: XnaTombstoning File: Game1.cs (excerpt)
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
segoe14 = this.Content.Load<SpriteFont>("Segoe14");
viewport = this.GraphicsDevice.Viewport;
}

The Update method reads taps, updates the numTaps field, determines a new random color, and also prepares a StringBuilder object for displaying the number of taps:

Example 4. Silverlight Project: XnaTombstoning File: Game1.cs (excerpt)
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

while (TouchPanel.IsGestureAvailable)
if (TouchPanel.ReadGesture().GestureType == GestureType.Tap)
{
numTaps++;
settings.BackgroundColor = new Color((byte)rand.Next(255),
(byte)rand.Next(255),
(byte)rand.Next(255));
}

text.Remove(0, text.Length);
text.AppendFormat("{0} taps total", numTaps);
Vector2 textSize = segoe14.MeasureString(text.ToString());
position = new Vector2((viewport.Width - textSize.X) / 2,
(viewport.Height - textSize.Y) / 2);

base.Update(gameTime);
}

Notice that the new color is saved not as a field, but as the BackgroundColor property of the Settings instance. That property is then referenced in the Draw override:

Example 5. Silverlight Project: XnaTombstoning File: Game1.cs (excerpt)
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(settings.BackgroundColor);

spriteBatch.Begin();
spriteBatch.DrawString(segoe14, text, position, Color.White);
spriteBatch.End();

base.Draw(gameTime);
}

The transient value of the numTaps field is saved to and restored from the State dictionary of the PhoneApplicationService in overrides of OnActivated and OnDeactivated:

Example 6. Silverlight Project: XnaTombstoning File: Game1.cs (excerpt)
protected override void OnActivated(object sender, EventArgs args)
{
if (PhoneApplicationService.Current.State.ContainsKey("numTaps"))
numTaps = (int)PhoneApplicationService.Current.State["numTaps"];

base.OnActivated(sender, args);
}

protected override void OnDeactivated(object sender, EventArgs args)
{
PhoneApplicationService.Current.State["numTaps"] = numTaps;
base.OnDeactivated(sender, args);
}

It might seem a little arbitrary to save and restore application settings in one set of event handlers, and save and restore transient settings in another set of overrides to virtual methods, and in a practical sense it is arbitrary. The program will get a call to OnActivated about the same time the Launching and Activated events are fired, and a call to OnDeactivated about the same time the Deactivated and Closing events are fired. The differentiation is more conceptual in that OnActivated and OnDeactivated are associated with the Game instance, so they should be used for properties associated with the game rather than overall application settings.

It’s possible that you’ll need to save an unserializable object as a transient setting, but because it’s not serializable, you can’t use the State dictionary of the PhoneApplicationService class. You’ll need to use isolated storage for such an object, but you don’t want to accidently retrieve that object and reuse it when the program is run again. In this case, you’ll use a flag in the State dictionary indicating whether you need to load the transient object from isolated storage.

Other -----------------
- Issues in Application Architecture - Isolated Storage
- Issues in Application Architecture - Page State
- Issues in Application Architecture - Task Switching on the Phone
- Issues in Application Architecture - Retaining Data across Instances
- Issues in Application Architecture - Sharing Data Among Pages
- Issues in Application Architecture - Passing Data to Pages
- Issues in Application Architecture - Basic Navigation
- Sensors and Services - Using a Map Service
- Sensors and Services - Geographic Location
- Sensors and Services : A Simple Bubble Level
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server