2009-06-16 2 views
0

J'écris un petit jeu de tir 2D dans XNA, et j'ai décidé que, pour que l'on puisse implémenter du contenu personnalisé dans le jeu, il charge les définitions des objets du jeu à partir de fichiers XML. Quand j'ai découvert que XNA avait un sérialiseur XML facile à utiliser, cela rendait la tâche très facile. Le problème est, mes objets que je veux sérialiser sont DrawableGameComponent s. Le sérialiseur XML de XNA, la classe ContentTypeWriter que vous étendez pour créer des rédacteurs de contenu personnalisés, nécessite que l'objet ait un constructeur sans arguments par défaut. DrawableGameComponent, cependant, nécessite un objet Game dans son constructeur et ne vous laissera pas définir le jeu après l'initialisation de l'objet. Cependant, je ne peux pas modifier le comportement du ContentTypeWriter suffisamment pour accepter un constructeur non vide, car le contenu est chargé par une méthode entièrement différente que je ne peux pas écraser. Donc, essentiellement, j'ai ceci:Sérialiser un DrawableGameComponent en XML en utilisant la classe ContentTypeWriter de XNA

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

Avec le ContentTypeWriter nécessitant un constructeur sans argument. Je ne peux pas en créer un, parce que je n'ai aucun moyen d'obtenir un objet Game dans la classe Star. Je ne pouvais pas en faire un DrawableGameComponent, mais j'essaie de découpler ces objets de la classe de jeu primaire de sorte que je puisse les réutiliser, etc. et sans un objet Game, c'est incroyablement difficile. Ma question est donc, est-ce que quelqu'un sait comment modifier ContentTypeWriter assez pour autoriser un constructeur avec des arguments, ou des moyens de contourner cela? J'ai aussi pensé à écrire mon propre code d'analyse XML en utilisant XPath ou les classes XML Linq mais XNA jette un ajustement si j'ai des fichiers XML dans le projet qui ne suivent pas le schéma XNA et ne construiront pas. Serait-il raisonnable d'écrire une classe de base avec seulement les champs principaux de la classe et une version DrawableGameComponent qui utilise le modèle décorateur, et ne sérialiser que la base? Je tire mes cheveux en essayant de contourner cela, et je me demande ce que je devrais faire exactement dans cette situation.

Répondre

2

Je construis également des niveaux via des fichiers de niveau d'analyse, et j'utilise System.Xml pour charger des données. J'ai changé les propriétés du fichier Xml i ajouté à ce qui suit: Build Action: Aucune Copie vers le répertoire de sortie: Copier si plus récent

alors je l'ai écrit un code comme ceci:

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

Ceci est juste un exemple mais il vous permet de construire des objets comme vous le souhaitez avec les données XML que vous voulez.

Pour les curieux, voici le fichier 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>