原文/ K% _; R# o' i8 H
http://blog.csdn.net/lqr801225/archive/2009/05/26/4218688.aspx/ x P! Y5 o0 g* O
# C4 P# L. c% q
! v) O$ V" T5 e" Z在XNA中显示中文字符或其它UNICODE字符(非GDI+)9 H. F" o% a. j' K" k
XNA3.0+VS2008SP1下调试通过& g5 K$ d- M9 I7 q& N
由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。. a, I @+ |0 x* X7 w1 {2 @3 j
步骤如下:
; s- b2 P% L5 K& X建立字体文件1 p3 B0 i1 b# ]& K, C E
[li]在当前项目中的“Content”中点击右键 [/li][li]加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont" [/li][li]打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆” [/li] 字典文件:
4 O2 A- Z; G+ o[li]把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下: message.txt | 中文输入测试,日本語テストを入力する8 b8 h3 K9 x2 n: q5 l l Y$ y
: I* Y( ]0 a; J/ q/ E
| [/li][li]将这个文件放置在项目的Content目录下。 [/li][li]另存为一下这个文件,以“UTF-8”编码格式。 [/li][li]在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。 [/li] 文字处理类:( y- m& y0 V" n4 q! f" d
[li]在解决方案浏览器中右键点击解决方案 [/li][li]添加新的项目,在项目类型对话框中选择"Windows Game Library(3.0)",起名"FontProcess" [/li][li]在项目中增加引用,选择“Microsoft.Xna.Content.Pipeline” [/li][li]将这个项目中的默认类"Class1.cs"改名为"DefaultFontProcessor.cs",修改为如下代码: [/li][li]重新编译这个项目 [/li] DefaultFontProcessor.cs | using System.IO;
; w+ `, {6 C7 L Q9 i( W; c' Cusing Microsoft.Xna.Framework.Content.Pipeline;+ Z% B: C0 }/ f: D
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;4 o O9 _0 ]( y
using Microsoft.Xna.Framework.Content.Pipeline.Processors;4 g6 }# U% ]! b. Q- [* m( B o
( O% B. Q9 g0 L/ x2 l) d
4 u, a9 k, w( x0 f
namespace FontProcessors" t" V8 P$ j& j* e. ^7 {1 T+ A
{! j& u/ b. y/ V! |$ K$ N
[ContentProcessor]. A* R6 G0 G" K$ H
public class DefaultFontProcessor : FontDescriptionProcessor
! t' l3 ]2 a' q+ p j- u {! C5 m0 l% C# ~( h2 X
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
5 P8 u5 T, b% [. Z1 H' B {
8 _# N" ]8 r! E: O0 g9 Z //载入文件
& c' w7 B' E+ E! i8 @: N6 E string fullPath = Path.GetFullPath("message.txt");, N. g, e8 X$ L1 j
context.AddDependency(fullPath);$ ^5 @1 Y; p2 T2 A
string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);
5 p$ w- d1 b7 }( X7 B
. R0 s" H8 q6 C
. S, M: B+ V+ i7 \4 ~ //导入字符
- C# Y5 i* G+ P$ ^' v foreach (char c in letters)/ ^: X) h8 m, l
{+ Q+ M- M9 K1 W4 q
input.Characters.Add(c);3 s( ^1 h" ~4 c4 Z
}
# V) p% S5 f( w E! r, C( n return base.Process(input, context); A% m8 h* M" Z5 b' j* r
} u5 M" |+ D: w: i
}8 ]0 p5 b/ \, R3 N8 |9 }
}
* }8 r8 Q# v) r0 x9 J
* M- w0 C% [* ~7 i) T6 [ | & L, P/ Q$ e) o+ ^# e
0 W1 ]" P4 P7 W
添加项目引用
/ U$ ^: Q2 r" {, e" ^5 Y[li]在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors” [/li][li]在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont" [/li][li]在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor" [/li] 在项目用使用
8 v) G1 M5 A0 c/ g& y X- \' kGame1.cs | using System;
* L1 p& e$ c: a! M# w- Fusing System.Collections.Generic;2 A7 j, h2 Y: R# o' r
using Microsoft.Xna.Framework;
. Z* [4 e \8 `using Microsoft.Xna.Framework.Audio;3 V/ O( o8 S/ V& ]' f/ ^
using Microsoft.Xna.Framework.Content;% N+ X6 Q3 F+ ]4 K8 i
using Microsoft.Xna.Framework.GamerServices;
8 b) L& `" E8 o- d0 E' ?5 [( musing Microsoft.Xna.Framework.Graphics;; J; c3 L, w* l' W$ {1 V
using Microsoft.Xna.Framework.Input;3 ?; ^3 G$ U9 m Q- @2 O6 t% {
using Microsoft.Xna.Framework.Net;+ E* B- F8 M4 }5 z& w# V- d# T
using Microsoft.Xna.Framework.Storage;
$ x* r; P7 t% ^# m. x
& H8 v) w& o! `4 m$ j! O, ?/ b7 n, Q2 p! w$ H" f! s1 q5 f u
namespace HelloWorld {
9 |, F/ e% C5 v public class GameMain : Microsoft.Xna.Framework.Game {" G4 L* v' |3 H. _
private GraphicsDeviceManager graphics; 8 A3 n# R# s. h
private SpriteBatch spriteBatch;/ N* A" y( I) e* a. p! v h
private SpriteFont font; : u/ Y" S1 o" c$ [+ s* u2 Z
# m$ o0 O1 ]' o
+ p: F2 Z8 R% X j. q
public GameMain() {( g4 U! ]" J' ?1 q& x6 l5 H
graphics=new GraphicsDeviceManager(this);" K2 o' i1 }: z! o, d
Content.RootDirectory="Content";
3 T8 _5 u9 [9 V1 N7 d; q% z0 K# { }" l" S1 k% q7 d. i1 Q* E
) t3 o6 e! z( z$ `7 W
' F$ W1 E) T; }6 [9 w$ A% O5 ]' e/ u
protected override void Initialize() {0 b/ A' `6 ~/ F1 U: H
base.Initialize();
6 ]7 p+ c R4 Q3 a, r! x2 O1 D }
% C2 p4 Y2 U, z& v$ s* u- s/ Z, u& r- }: @
# D7 j2 c6 Y9 `- x' H* m# r+ a
/ f( l: u" d e1 b protected override void LoadContent() {; V0 [0 X5 \9 {/ H
spriteBatch=new SpriteBatch(GraphicsDevice);+ r6 w, A" Y, B+ M/ g; v' w* G1 C6 W
font=Content.Load<SpriteFont>("DefaultFont");
2 a9 T/ q( Y' q }
& X% w) ]& O" S' R' ^
* g( c' @$ K1 e8 I+ i, w; P9 P! ?# B+ J3 n3 F/ O% @- [2 R0 `" W
protected override void UnloadContent() {
: B8 r# f% q9 T }" J) ~/ _$ a% z s! z4 u7 C
- u! h, E2 }/ ^
3 N4 X2 _# C* E" w9 \8 u
protected override void Update(GameTime gameTime) {. L0 z3 P, J9 A$ R: M8 G: {
if (GamePad.GetState(PlayerIndex.One).Buttons.Back==
" V6 Z7 v( o# \8 t( l \ ButtonState.Pressed) {2 R. a2 Z) |, r! U8 j
Exit();+ |- H; z% F+ N# W. |
}
) h0 l+ G* v8 c" W
- F* Y i; U$ d/ w( l2 p) i5 f
0 y% U- d' ?/ F. d base.Update(gameTime);" R/ J& F5 a- @' J q
}
6 y! {8 t! n) v3 ~3 Q4 e4 R V( O/ B9 j
3 E" e+ N- a5 e: ~$ {- ~: z9 P5 G
protected override void Draw(GameTime gameTime) {- @! ?% u2 d- L' `) _6 c/ U
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
1 `& D4 W- I0 [+ b! ]+ W
0 F( _6 x4 [4 `- G# A- F
( [: C% ~" K5 b$ ^- S spriteBatch.Begin(); H8 ?! [% A p7 T. v) b6 O
DrawString("中文输入测试,日本語テストを入力する",50,50);
' Z& Q# D+ w! H* }& \. A, l- A spriteBatch.End();
) E; v( A/ i/ a6 ~% C' c, u! v; r* F# ]& E/ C
A9 z* l3 C( U9 P1 v
base.Draw(gameTime);
: W1 v; R* x4 N }
' R# Z. H9 c3 v' i+ w7 W1 b
$ j0 W2 B) q3 l2 }% _4 \. H% i& ~. D5 a2 E+ W' ?$ Q
private void DrawString(String str,int x,int y) {; O. i$ c# E2 V0 S X* U1 B0 N0 G
spriteBatch.DrawString(font,str,new Vector2(x,y),Color.White);
7 i7 s/ X+ R" i# t6 E4 d }5 I' C1 s- z: f$ @- {* d( m
}
7 v3 W$ ~' L' l; E}
8 R0 j. S) Q4 B" s! n
8 R& {0 l2 [6 [7 e: ^ |
|