在XNA中显示中文字符或其它UNICODE字符(非GDI+)
XNA3.0+VS2008SP1下调试通过
由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。
步骤如下:
建立字体文件
- 在当前项目中的“Content”中点击右键
- 加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont"
- 打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆”
字典文件:
- 把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下:
message.txt 中文输入测试,日本語テストを入力する
- 将这个文件放置在项目的Content目录下。
- 另存为一下这个文件,以“UTF-8”编码格式。
- 在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。
文字处理类:
- 在解决方案浏览器中右键点击解决方案
- 添加新的项目,在项目类型对话框中选择"Windows Game Library(3.0)",起名"FontProcess"
- 在项目中增加引用,选择“Microsoft.Xna.Content.Pipeline”
- 将这个项目中的默认类"Class1.cs"改名为"DefaultFontProcessor.cs",修改为如下代码:
- 重新编译这个项目
DefaultFontProcessor.cs |
using System.IO;using Microsoft.Xna.Framework.Content.Pipeline;using Microsoft.Xna.Framework.Content.Pipeline.Graphics;using Microsoft.Xna.Framework.Content.Pipeline.Processors; namespace FontProcessors{ [ContentProcessor] public class DefaultFontProcessor : FontDescriptionProcessor { public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context) { //载入文件 string fullPath = Path.GetFullPath("message.txt"); context.AddDependency(fullPath); string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8); //导入字符 foreach (char c in letters) { input.Characters.Add(c); } return base.Process(input, context); } }} |
添加项目引用
- 在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors”
- 在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont"
- 在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor"
在项目用使用
- 在我们的项目中使用如下代码:
Game1.cs |
using System;using System.Collections.Generic;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Audio;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.GamerServices;using Microsoft.Xna.Framework.Graphics;using Microsoft.Xna.Framework.Input;using Microsoft.Xna.Framework.Net;using Microsoft.Xna.Framework.Storage; namespace HelloWorld { public class GameMain : Microsoft.Xna.Framework.Game { private GraphicsDeviceManager graphics; private SpriteBatch spriteBatch; private SpriteFont font; public GameMain() { graphics=new GraphicsDeviceManager(this); Content.RootDirectory="Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch=new SpriteBatch(GraphicsDevice); font=Content.Load<SpriteFont>("DefaultFont"); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back== ButtonState.Pressed) { Exit(); } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); DrawString("中文输入测试,日本語テストを入力する",50,50); spriteBatch.End(); base.Draw(gameTime); } private void DrawString(String str,int x,int y) { spriteBatch.DrawString(font,str,new Vector2(x,y),Color.White); } }} |