tags:

views:

772

answers:

2

I'm writing a small 2D shooter game in XNA, and I've decided that, so that one could implement custom made content in the game, it loads definitions of the game objects from XML files. When I found out that XNA has an easy to use XML serializer, it made it extra easy. The problem is, my objects that I want to serialize are DrawableGameComponents. XNA's XML serializer, the ContentTypeWriter class which you extend to create custom content writers, requires that the object have a constructor with no arguments to default to. DrawableGameComponent, however, requires a Game object in its constructor and will not let you set the game after the object is initialized. I cannot modify the behavior of the ContentTypeWriter enough, however, to accept a non-blank constructor, because the content is loaded by an entirely different method that I cannot overwrite. So essentially I have this:

class Star : DrawableGameComponent{
    public Star(Game game)
        : base(game)
    {
    }
}

With the ContentTypeWriter requiring a constructor with no arguments. I can't create one though, because then I have no way to get a Game object into the Star class. I could just not make it a DrawableGameComponent, but I am trying to decouple these objects from the primary game class such that I can reuse them, etc. and without a Game object this is absurdly difficult. My question therefore is, does anyone know how to modify ContentTypeWriter enough to allow a constructor with arguments, or any ways around this?

I also thought about writing my own XML parsing code using XPath or the Linq XML classes but XNA throws a fit if I have any XML files in the project that do not follow the XNA schema and won't build. Would it be reasonable to Write a base class with only the primary fields of the class and a DrawableGameComponent version that uses the decorator pattern, and serialize only the base? I'm pulling out my hair trying to get around this, and wondering what exactly I should be doing in this situation.

A: 

Going with the "Write your own" option: How strictly does XNA monitor XML files? If it is based off of file extensions, could you just use a custom file extension?

Jamie Penney
Looks like I can get around that restriction by changing the filename, which I apparently never thought of.
Annath
+2  A: 

I am also building levels via parsing level files, and i use System.Xml to load data. I changed the properties on the Xml file i added to the following: Build Action: None Copy To Output Directory: Copy If Newer

then i wrote some code like this:

public static LevelInfo LoadLevel(
    string xmlFile, 
    GraphicsDevice device, 
    PhysicsSimulator sim, 
    ContentManager content)
{
    FileInfo xmlFileInfo = new FileInfo(xmlFile);

    XDocument fileDoc = XDocument.Load(xmlFile);
    //this part is game specific
    LevelInfo levelData = new LevelInfo();
    levelData.DynamicObjects = LevelLoader.LoadDynamicObjects(device, sim, content, xmlFileInfo, fileDoc);
    levelData.StaticObjects = LevelLoader.LoadStaticObjects(device, sim, content, xmlFileInfo, fileDoc);
    levelData.LevelAreas = LevelLoader.LoadAreas(device, xmlFileInfo, fileDoc);
    return levelData;
}

This is just a sample but it lets you build objects however you want with whatever XML data you want.

For those curious, here's the xml file:

<Level>
  <Object Type="Custom" 
          PositionX="400" 
          PositionY="400" 
          IsStatic="true"
          Rotation="0"
          Texture="sampleObj1_geometrymap"
          Mass="5"
          ColorR="0"
          ColorG="255"
          ColorB="0">
  </Object>
  <Object Type="Custom"
          PositionX="400"
          PositionY="600"
          IsStatic="false"
          Rotation="0"
          Texture="sampleObj2_geometrymap"
          Mass="5"
          ColorR="230"
          ColorG="230"
          ColorB="255">
  </Object>
  <Object Type="Area"
          MinPositionX="0"
          MinPositionY="0"
          MaxPositionX="300"
          MaxPositionY="300"
          AreaType="Goal">
  </Object>
</Level>
RCIX