使用XNA的ContentTypeWriter类将DrawableGameComponent序列化为XML

时间:2021-10-30 11:31:44

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:

我正在XNA中编写一个小型2D射击游戏,我已经决定,为了能够在游戏中实现自定义内容,它会从XML文件中加载游戏对象的定义。当我发现XNA有一个易于使用的XML序列化程序时,它使它更容易。问题是,我要序列化的对象是DrawableGameComponents。 XNA的XML序列化程序,您扩展为创建自定义内容编写器的ContentTypeWriter类,要求对象具有默认情况下没有参数的构造函数。但是,DrawableGameComponent在其构造函数中需要一个Game对象,并且在初始化对象后不允许您设置游戏。但是,我不能足够地修改ContentTypeWriter的行为来接受非空构造函数,因为内容是由一个我无法覆盖的完全不同的方法加载的。基本上我有这个:

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?

ContentTypeWriter需要不带参数的构造函数。我不能创建一个,因为那时我无法将一个Game对象放入Star类中。我可以不把它变成DrawableGameComponent,但是我试图将这些对象从主游戏类中解耦,这样我就可以重用它们等等。如果没有Game对象,这是非常困难的。因此,我的问题是,有没有人知道如何修改ContentTypeWriter足以允许带有参数的构造函数,或者任何方法?

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.

我还考虑过使用XPath或Linq XML类编写自己的XML解析代码,但是如果我在项目中有任何不遵循XNA架构但不会构建的XML文件,那么XNA会引发一个问题。编写只包含类的主要字段和使用装饰器模式的DrawableGameComponent版本的基类是否合理,并仅序列化基类?我正在拔出我的头发试图解决这个问题,并想知道在这种情况下我应该做些什么。

1 个解决方案

#1


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

我也通过解析级别文件来构建级别,我使用System.Xml来加载数据。我更改了添加到以下内容的Xml文件的属性:构建操作:无复制到输出目录:复制如果更新

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.

这只是一个示例,但它允许您根据需要使用所需的任何XML数据构建对象。

For those curious, here's the xml file:

对于那些好奇的人,这是xml文件:

<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>

#1


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

我也通过解析级别文件来构建级别,我使用System.Xml来加载数据。我更改了添加到以下内容的Xml文件的属性:构建操作:无复制到输出目录:复制如果更新

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.

这只是一个示例,但它允许您根据需要使用所需的任何XML数据构建对象。

For those curious, here's the xml file:

对于那些好奇的人,这是xml文件:

<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>