XNA - 再談Xml

  • 4271
  • 0
  • XNA
  • 2010-08-28

XNA - 再談Xml

xml又來了!~這次講深入一點
前兩篇關於XML的文章都只做比較簡單的部份
但是真的遊戲要用XML設定的話,內容應該是很有變化的
接下來就講講我做過的一些用法
首先定義兩個Data物件

   1: public class ImageData {
   2:     public string Name;
   3:     public string TexturePath;
   4:     public int DestWidth;
   5:     public int DestHeight;
   6:  
   7:     [ContentSerializerIgnore]
   8:     public Texture2D Texture2DImage;
   9: }
  10:  
  11: public class AnimationData : ImageData {
  12:     public bool IsLoop;
  13:     public List<Frame> Frames = new List<Frame>();
  14:  
  15: }
  16:  
  17: public class Frame {
  18:     public Rectangle FrameRect;
  19:     public int Time;
  20:  
  21:  
  22:     public class FrameReader : ContentTypeReader<Frame> {
  23:  
  24:         protected override Frame Read(ContentReader input, Frame existingInstance) {
  25:             Frame frame = existingInstance;
  26:             if (frame == null) {
  27:                 frame = new Frame();
  28:             }
  29:  
  30:             frame.FrameRect = input.ReadObject<Rectangle>();
  31:             frame.Time = input.ReadInt32();
  32:  
  33:             return frame;
  34:         }
  35:     }
  36: }

 

ImageData是用來放圖片資訊的,
AnimationData是放動畫資訊,
Frame是存放每一格畫面的顯示位置和時間,而我特別把Frame的Reader寫成巢狀類別,
這會影響到Writer的GetRuntimeReader內容,後面會說!
另外關於動畫,請參考這篇
很明顯的,動畫一定也是一張圖,只是他多了畫出的位置和每格的時間,所以這裡用繼承!
而xml就會編輯成下面的樣子

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <XnaContent>
   3:   <Asset Type="XMLLibrary.AnimationData">
   4:     <Name>小紅圈</Name>
   5:     <TexturePath>Texture\小紅圈</TexturePath>
   6:     <DestWidth>32</DestWidth>
   7:     <DestHeight>32</DestHeight>
   8:     <IsLoop>true</IsLoop>
   9:     <Frames>
  10:       <Item>
  11:         <FrameRect>0 0 32 32</FrameRect>
  12:         <Time>80</Time>
  13:       </Item>
  14:       <Item>
  15:         <FrameRect>33 0 32 32</FrameRect>
  16:         <Time>80</Time>
  17:       </Item>
  18:       <Item>
  19:         <FrameRect>66 0 32 32</FrameRect>
  20:         <Time>80</Time>
  21:       </Item>
  22:       <Item>
  23:         <FrameRect>99 0 32 32</FrameRect>
  24:         <Time>80</Time>
  25:       </Item>
  26:       <Item>
  27:         <FrameRect>132 0 32 32</FrameRect>
  28:         <Time>80</Time>
  29:       </Item>
  30:       <Item>
  31:         <FrameRect>165 0 32 32</FrameRect>
  32:         <Time>80</Time>
  33:       </Item>
  34:       <Item>
  35:         <FrameRect>198 0 32 32</FrameRect>
  36:         <Time>80</Time>
  37:       </Item>
  38:       <Item>
  39:         <FrameRect>231 0 32 32</FrameRect>
  40:         <Time>80</Time>
  41:       </Item>
  42:       <Item>
  43:         <FrameRect>262 0 32 32</FrameRect>
  44:         <Time>80</Time>
  45:       </Item>
  46:     </Frames>
  47:   </Asset>
  48: </XnaContent>

 

再來就是重點的Writer和Reader了
首先從ImageData寫起

   1:  
   2: [ContentTypeWriter]
   3: public class ImageDataWriter : ContentTypeWriter<ImageData> {
   4:  
   5:     protected override void Write(ContentWriter output, ImageData value) {
   6:         output.Write(value.Name);
   7:         output.Write(value.TexturePath);
   8:         output.Write(value.DestWidth);
   9:         output.Write(value.DestHeight);
  10:     }
  11:  
  12:     public override string GetRuntimeReader(TargetPlatform targetPlatform) {
  13:         return "XMLLibrary.ImageDataReader, XMLLibrary";
  14:     }
  15: }
  16:  
  17: public class ImageDataReader : ContentTypeReader<ImageData> {
  18:  
  19:     protected override ImageData Read(ContentReader input, ImageData existingInstance) {
  20:         ImageData data = existingInstance;
  21:         if (data == null) {
  22:             data = new ImageData();
  23:         }
  24:  
  25:         data.Name = input.ReadString();
  26:         data.TexturePath = input.ReadString();
  27:         data.DestWidth = input.ReadInt32();
  28:         data.DestHeight = input.ReadInt32();
  29:  
  30:         data.Texture2DImage = input.ContentManager.Load<Texture2D>(data.TexturePath);
  31:  
  32:         return data;
  33:     }
  34: }

Writer沒有什麼特別的,就不多說了
倒是Reader有在載入的時候順便把圖也載近來
所以用到30行的ContentManager
接著看看Reader

   1:  
   2: [ContentTypeWriter]
   3: public class ImageDataWriter : ContentTypeWriter<ImageData> {
   4:  
   5:     protected override void Write(ContentWriter output, ImageData value) {
   6:         output.Write(value.Name);
   7:         output.Write(value.TexturePath);
   8:         output.Write(value.DestWidth);
   9:         output.Write(value.DestHeight);
  10:     }
  11:  
  12:     public override string GetRuntimeReader(TargetPlatform targetPlatform) {
  13:         return "XMLLibrary.ImageDataReader, XMLLibrary";
  14:     }
  15: }
  16: [ContentTypeWriter]
  17: public class AnimationDataWriter : ContentTypeWriter<AnimationData> {
  18:     ImageDataWriter imageDataWriter = null;
  19:  
  20:     protected override void Initialize(ContentCompiler compiler) {
  21:         imageDataWriter = compiler.GetTypeWriter(typeof(ImageData))
  22:             as ImageDataWriter;
  23:  
  24:         base.Initialize(compiler);
  25:     }
  26:  
  27:     protected override void Write(ContentWriter output, AnimationData value) {
  28:         output.WriteRawObject<ImageData>(value as ImageData, imageDataWriter);
  29:         output.Write(value.IsLoop);
  30:         output.WriteObject(value.Frames);
  31:     }
  32:  
  33:     public override string GetRuntimeReader(TargetPlatform targetPlatform) {
  34:         return "XMLLibrary.AnimationDataReader, XMLLibrary";
  35:     }
  36: }
  37:  
  38: [ContentTypeWriter]
  39: public class FrameWriter : ContentTypeWriter<Frame> {
  40:  
  41:     protected override void Write(ContentWriter output, Frame value) {
  42:         output.WriteObject<Rectangle>(value.FrameRect);
  43:         output.Write(value.Time);
  44:     }
  45:     
  46:     public override string GetRuntimeReader(TargetPlatform targetPlatform) {
  47:         return "XMLLibrary.Frame+FrameReader, XMLLibrary";
  48:     }
  49: }

來看看AnimationDataWriter,他裡面有一個ImageDataWriter,在初始函式取得ImageDataWriter物件,
在28行呼叫的WriteRawObject就需要用到他,因為我們的AnimationData是繼承ImageData,
在XML裡面就一定要把父類別的資料寫在前面,
WriteRawObject 會把接下來的內容當做ImageData來讀取。
再來是30和35行,讀進一個物件,不是基本型態的話就需要這樣讀,
最後要講的就是40行,GetRuntimeReader這個函式是要告訴電腦要執行哪一個reader
所以40行回傳的就是"命名空間.物件名稱+巢狀物件名稱, 組件名稱",
必須回傳類別的組件限定名稱,可參考這裡
最後範例程式並沒有什麼畫面可以看,請設定中斷點查看載入的物件內容吧!

再談Xml.rar