在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);
}
}
}
|