Hardcoding vs. Data files

In our previous lecture, we showed how to create animations in XML, but we were somehwat sloppy. In addition to creating animation variables in the main class (bad), we also hardcoded the name of the animation file, and size of the animation in our source code (worse!). If our artist wants to change the number of frames of animation, or tweak the width of a character, they will need to go to the code. Both artists and engineers get very grumpy when the artists are forced to hack at the actual source code. The proper way to do this is to have all of the information about which animations you want to use, and the properties of each animation, stored in a data file (or data files), which can be read in a runtime.

There are a number of ways to store data -- you can create your own custom file format (and then create an importer to import that data), or you can use a standard file format, like XML, and use a predefined importer to read in your code. XNA has a reasonable importer for XML, which we will be investigating now

XML Data

XML is a standard, flexible file format that is (more or less) human readable, and easy to work with. It can be edited in almost any text editor (many of which have syntax highlighting, auto-completion of tags, and error checking built in). The XNA content pipeline has facilities for (mostly) automatically filling data structures in from XML files.

XNA and XML

XNA offers a content pipeline that includes loading XML files.

Loading Simple Strings in XNA

First, we will look at the simplist possible way to read in XML files from XNA -- reading in a single string (OK, so storing a single string in a data file is pretty silly, but this is for illustrative purposes).

Loading Collections in XNA

OK, so what if we wanted something more interesting -- like, say, and array of elements? If we use the XML file IntList.xml:
<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
   <Asset Type="int[]">
   4 6 7 11
   </Asset>
</XnaContent>
and then in our LoadContent method we use the line
   int[] data = Content.Load("IntList");
Then we have loaded up our array of integers. Want something even more fun? How about a dictionary that maps strings to recctangles? Create an XML file called DictionaryTest.xml :
<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
   <Asset Type="System.Collections.Generic.Dictionary[System.String, Microsoft.Xna.Framework.Rectangle]">
<Item>
  <Key>firstbox</Key>
  <Value>0 0 10 20</Value>
</Item>
<Item>
  <Key>secondbox</Key>
  <Value>4 5 10 20</Value>
</Item>
   </Asset>
</XnaContent>
Note that you need to use the full names, with all the namespaces (Microsoft.Xna.Framework.Rectangle) to specify types in the .xml file (there is no "using" analog in the XNA xml file format) Now, you can load in your LoadContent method as:
Dictionary<String,Rectangle> dict = Content.Load<Dictionary<String,Rectangle>>("DictionaryTest");

Custom Classes

What if we wanted to load our own custom classes into XNA? That gets a little bit more complicated, since the content importer needs to know the format of our classes in order to load them in. What goes on behind the scenes is that when your code is compiled, the .xml documents in your Content project are also compiled into an intermediate form for quicker loading at runtime. For that whole process to work correctly, you need to tell the Content project about the data format of the classes you need to load. The steps are as follows:

In-Class Project

Time to get your fingers dirty. You are going to create a quick game with an animation, using XML serialization.