XNA-顯示中文

XNA-顯示中文

由上一篇的範例XNA-利用Content Pipeline輸出多國語言學會使用ContentProcessor輸出多國文字,

但是我不想使用資源檔的方式來存內文,我比較想用自己的xml檔,

構想是自己的xml檔輸入想顯示的文字,如下: 

<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
  <!-- TODO: replace this Asset with your own XML asset data. -->
  <Asset Type="MessagePipeline.MessageData">
    <Msg name="title">你好</Msg>
    <Msg name="name">我是天譴寶寶</Msg>
  </Asset>
</XnaContent>

 

然後有一個MessageData的物件,用來載入此xml後在程式裡使用,內容只有一個Dictionary<string,string>物件,

然後還有Importer以及writer如下: 

public class MessageData {
	public Dictionary<string,string> Data = new Dictionary<string,string>();
}

[ContentImporter(DisplayName = "MessagePipeline.MessageImporter")]
public class MessageImporter : ContentImporter<MessageData> {
	public override MessageData Import(string filename, ContentImporterContext context) {
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.Load(filename);

		MessageData messageData = new MessageData();
		
		foreach (XmlNode xmlNode in xmlDocument.SelectNodes("XnaContent/Asset/Msg")) {
			messageData.Data.Add(xmlNode.Attributes["name"].InnerText, xmlNode.InnerText);
		}

		return messageData;
	}
}

[ContentTypeWriter]
public class MessageDataWriter : ContentTypeWriter<MessageData> {

	protected override void Write(ContentWriter output, MessageData value) {
		output.Write(value.Data.Count);
		foreach (string key in value.Data.Keys) {
			output.Write(key);
			output.Write(value.Data[key]);
		}
	}

	public override string GetRuntimeReader(Microsoft.Xna.Framework.TargetPlatform targetPlatform) {
		return "MessagePipeline.MessageDataReader, ContentPipelineExtension1";
	}
}

public class MessageDataReader : ContentTypeReader<MessageData> {

	protected override MessageData Read(ContentReader input, MessageData existingInstance) {
		MessageData data = existingInstance;
		if (data == null) {
			data = new MessageData();
		}
		int count = input.ReadInt32();
		for (int i = 0; i < count; i++) {
			data.Data.Add(input.ReadString(), input.ReadString());
		}


		return data;
	}
}

其中Importer是之前沒有說過的,但是應該很好懂,就是將原始檔案轉成我的MessageData物件。

spritefont檔案會多出指定要輸入那些文字的node: 

    <TextFiles>
      <Text>Message.xml</Text>
    </TextFiles>

這裡我只使用Message.xml,若是以後想要有別種資料,例如用來顯示技能說明、故事對話之類的文字,可以再加。 

再來是自訂processor,主要針對spritefont檔案,有兩個主要的物件: 

public class MessageFontDescription : FontDescription {
	public MessageFontDescription()
		: base("Arial", 14, 0) {

	}

	[ContentSerializer(Optional = true, CollectionItemName = "Text")]
	public List<string> TextFiles {
		get { return textFiles; }
	}

	List<string> textFiles = new List<string>();
}

[ContentProcessor(DisplayName = "MessagePipeline.MessageProcessor")]
public class MessageProcessor : ContentProcessor<MessageFontDescription, SpriteFontContent> {
	public override SpriteFontContent Process(MessageFontDescription input, ContentProcessorContext context) {
		foreach (string path in input.TextFiles) {
			string absolutePath = Path.GetFullPath(path);
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(absolutePath);

			foreach (XmlNode xmlNode in xmlDocument.SelectNodes("XnaContent/Asset/Msg")) {
				string characters = xmlNode.InnerText;

				// Scan each character of the string.
				foreach (char usedCharacter in characters) {
					input.Characters.Add(usedCharacter);
				}
			}
			context.AddDependency(absolutePath);
		}
		return context.Convert<FontDescription, SpriteFontContent>(input, "FontDescriptionProcessor");
	}
}

MessageProcessor要覆寫Process函式,他會取得我們的檔案,然後將裡面的字加到Characters裡,這部份和上一個範例差不多。 

之後要將Message.xml的Importer屬性設定成我們自訂的物件

image

然後spritefont檔也要設定使用我們自訂的processor

image

如此以後想要增加文字敘述,就很方便了!!

程式執行結果:

image

範例下載:XNA-顯示中文.rar