WP7 XNA - ContentPipeline

  • 4529
  • 0
  • WP
  • 2011-07-07

WP7 XNA ContentPipelen

ContentPipeline算是比較進階的議題,但是也不會太困難,想要用自己定義的檔案時就需要用到了。

先來看看Pipeline的組件

Bb447745.ContentPipeline_Diagram(en-us,XNAGameStudio.40).jpg

圖片來源http://msdn.microsoft.com/en-us/library/bb447745.aspx

 

Soure Asset就是自定義的檔案,經過Importer讀入成Content DOM Type,然後再經過Processor轉換成Output Type,然後編譯成XNB檔案,最後在遊戲執行時讀入XNB檔。

白話一點的說就是就是一個檔案藉由Importer讀入成一個物件,在經過Processor轉換成另一個物件,

以上這些動作都是在Design Time,也就是在電腦上執行到編譯成XNB檔為止,然後才是遊戲的編譯。

基本的概念說過後就來看看例子!

 

這個例子示範讀入一個文字檔,然後文字檔的資料就是簡單的玩家資訊,就來個名稱、年紀、X座標、Y座標,每筆資料佔一行,這幾個資料分別是第一到四行

 

決定好文字檔格式後,就開始寫程式囉。

先創建一個XNA的方案,XNA的Content在3.0和4.0有比較大的不一樣,4.0的Content和主要的專案分離,

其專案型態如下

image

接著在新增一個Windows Phone Game Library的專案,取名為DataType用來決定物件的結構,

4.0之前可以不用為了資料結構特地開一個專案,那是因為Content和主專案在一起,彼此可以互通,

現在content和主專案分開,所以要將自己定義的資料結構寫在另一個Library專案內,才可以讓主專案以及Content專案都用的到。

在此專案加入一個class,名稱叫做PlayerData,程式碼如下

	   1:  public class PlayerData {
	   2:      public string Name;
	   3:      public int Age;
	   4:      public Vector2 Position;
	   5:  }

只是用來定義玩家的資料。

 

然後再新增一個Content Pipeline Extension Library的專案,我們取名為ContentPipline,這個專案就是用來寫Importer和Processor的地方,

收先要將DataType的Library加入參考才可以用的到PlayerData物件

Importer的程式碼如下

	   1:  [ContentImporter(".txt", DisplayName = "PlayerData Importer", DefaultProcessor = "PlayerDataContentProcessor")]
	   2:  public class PlayerDataContentImporter : ContentImporter<string> {
	   3:      public override string Import(string filename, ContentImporterContext context) {
	   4:          StreamReader sr = new StreamReader(File.OpenRead(filename));
	   5:          StringBuilder sb = new StringBuilder();
	   6:          while (!sr.EndOfStream) {
	   7:              sb.Append(sr.ReadLine()).Append(",");
	   8:          }
	   9:          return sb.ToString();
	  10:      }
	  11:  }

記得在此class加上ContentImporter的屬性。

程式碼的3到10行就是把文字檔讀出來,把每一行都組合起來,並以逗號做連結

Import函式回傳的string就是所謂的Content DOM Type,你可以將讀出來的檔案直接轉成自己定義的物件,這個例子就直接用string了。

接著是Processor

	   1:  [ContentProcessor(DisplayName = "PlayerDataContentProcessor")]
	   2:  public class PlayerDataContentProcessor : ContentProcessor<string, PlayerData> {
	   3:      public override PlayerData Process(string input, ContentProcessorContext context) {
	   4:          PlayerData data = new PlayerData();
	   5:  
	   6:          string[] strs = input.Split(new char[] { ',' });
	   7:          if (strs.Length > 3) {
	   8:              data.Name = strs[0];
	   9:              data.Age = int.Parse(strs[1]);
	  10:              data.Position = new Vector2(float.Parse(strs[2]), float.Parse(strs[3]));
	  11:          }
	  12:          
	  13:          return data;
	  14:      }
	  15:  }

 

他就是將Import進來的Content DOM Type做處理,將字串用逗號拆解,並且一一放入正確的變數內

然後回傳PlayerData,也就是所謂的Processor Output Type。

 

完成Importer和Processor之後,要先將此專案做編譯,然後於Content專案要加入此參考,如此一來Content才有選項可以選。

接著在Content裡面增加文字檔,取名叫做PlayerData_Help

文字檔的內容如下

image

然後在此文字當的屬性頁做設定

image

Build Action要選擇Compile

Content Importer和Content Processor就選剛剛我們自己做的Importer和Processor

 

最後方案的內容如下

image

TestProcessorImport是主要的遊戲專案,TestProcessorImporterContent是遊戲的資源專案,DataType釋放資料結構用的專案,ContentPipeline是寫Importer和Processor的專案。

專案的類型從他前面的小圖示就可以看出端倪,TestProcessorImport和DataType這兩個專案是真的會變成dll檔,然後是會出現在xap內的,

TestProcessorImporterContent裡面的資源會編譯成xnb檔,也會放進xap裡的Content目錄內,

而ContentPipline專案卻不會在最後執行的xap內看到,原因就如同之前講的,

Importer和Porcessor是在Design Time的時候執行,或著說在遊戲編譯的時候才會需要他,真正執行遊戲是用不到他的。

 

如此一來,我們就可以讀取文字檔,轉換成PlayerData物件在遊戲裡面使用了!

在遊戲內就只要像一般的資源一樣載入就可以使用了


PlayerData data = Content.Load<PlayerData>("PlayerData_Help");

 

範例的結果如下圖

image

範例程式下載TestProcessorImporter.rar