WP7 XNA ContentPipelen
ContentPipeline算是比較進階的議題,但是也不會太困難,想要用自己定義的檔案時就需要用到了。
先來看看Pipeline的組件
圖片來源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和主要的專案分離,
其專案型態如下
接著在新增一個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
文字檔的內容如下
然後在此文字當的屬性頁做設定
Build Action要選擇Compile
Content Importer和Content Processor就選剛剛我們自己做的Importer和Processor
最後方案的內容如下
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");
範例的結果如下圖