在XNA中显示中文字符

时间:2022-06-03 06:39:30

 

在XNA中显示中文字符或其它UNICODE字符(非GDI+)

XNA3.0+VS2008SP1下调试通过

由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。

步骤如下:

建立字体文件

  1. 在当前项目中的“Content”中点击右键
  2. 加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont"
  3. 打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆”

字典文件:

  1. 把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下:
    message.txt
    中文输入测试,日本語テストを入力する

  2. 将这个文件放置在项目的Content目录下。
  3. 另存为一下这个文件,以“UTF-8”编码格式。
  4. 在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。

文字处理类:

  1. 在解决方案浏览器中右键点击解决方案
  2. 添加新的项目,在项目类型对话框中选择"Windows Game Library(3.0)",起名"FontProcess"
  3. 在项目中增加引用,选择“Microsoft.Xna.Content.Pipeline”
  4. 将这个项目中的默认类"Class1.cs"改名为"DefaultFontProcessor.cs",修改为如下代码:
  5. 重新编译这个项目
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);        }    }}

添加项目引用

  1. 在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors”
  2. 在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont"
  3. 在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor"

在项目用使用

  1. 在我们的项目中使用如下代码:
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);        }    }}