原文
, V h) {; |2 p3 b) O! a b5 Qhttp://blog.csdn.net/lqr801225/archive/2009/05/26/4218688.aspx
2 R3 j2 o+ v5 t& Y. n! w: d( _) G6 g5 f
: `+ E8 o' I6 J
在XNA中显示中文字符或其它UNICODE字符(非GDI+)
% C, i5 g) O2 ]# d, J8 v5 FXNA3.0+VS2008SP1下调试通过
5 m( F% d8 ^/ S! N R& |( z由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。% O* T4 Q- b9 J7 w. w Y+ I% k5 @
步骤如下:
( D9 K6 P! v% R, T- i建立字体文件
e5 F* J! y) V+ E[li]在当前项目中的“Content”中点击右键 [/li][li]加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont" [/li][li]打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆” [/li] 字典文件:
/ C* l( }) J0 t1 c[li]把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下: message.txt | 中文输入测试,日本語テストを入力する( V) J* f) h7 j4 z1 ~: |
f2 B6 v5 `- q' o9 T | [/li][li]将这个文件放置在项目的Content目录下。 [/li][li]另存为一下这个文件,以“UTF-8”编码格式。 [/li][li]在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。 [/li] 文字处理类:
& v8 U8 c$ \# ^ h; M[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;
- ?6 |# y4 X: S- T$ I) musing Microsoft.Xna.Framework.Content.Pipeline;- X) E2 ?, X2 j* W9 `: {
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
( W6 e1 E' N L$ V* Susing Microsoft.Xna.Framework.Content.Pipeline.Processors;4 S9 M' I, w! @6 B1 [% }
2 W' @ y0 ~: o# o* z x5 t
r+ i) ?/ t4 enamespace FontProcessors ]* D D; g( O M/ X0 @! ?
{+ f& `- j" I* V, z
[ContentProcessor]
/ a# c# [) B* \& S$ F' z& x2 a9 M public class DefaultFontProcessor : FontDescriptionProcessor+ u$ o; X& G8 ?8 f
{1 L: {1 J ]6 ?1 f
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
5 o% W4 A/ O4 h4 V ~6 n) T {
' _9 Q' |. s! S' g6 R //载入文件 G$ y9 ?* ^6 [1 `: |2 e& b
string fullPath = Path.GetFullPath("message.txt");
- E. T$ A2 e, e/ R1 r" N5 \" B& D context.AddDependency(fullPath);
- {/ A2 {6 ~/ h. F8 k3 C1 I string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);
7 _) n0 \- p( k& X5 b; c! k2 _* ~) S1 F0 ^5 P& k
2 r7 F. @+ m* R, p4 X. m
//导入字符. G _! k7 z, q6 T/ c" I. S3 q# e
foreach (char c in letters)
5 K1 L- A; P3 F5 A {6 Z$ y; P% {. d7 x2 l+ w6 x# g
input.Characters.Add(c);
, _" P! t, ~: c! F) q: }5 a }) P5 l J8 R; P4 v; W) [7 ^
return base.Process(input, context);
6 V8 A: _& Y2 U2 q& M; } }, B8 L( O; ?0 H# W
}% ]. L) J5 m" y5 L5 P% D5 j
}: B1 {2 l5 V# y. F7 j; x/ n9 q* c
' J2 Q' B6 L: `3 Q
|
+ } H; V" A W* w- y" f/ R" i" q% P/ p8 A/ r* W
添加项目引用
V+ E0 p y7 @2 j2 f[li]在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors” [/li][li]在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont" [/li][li]在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor" [/li] 在项目用使用. A+ c( `' p* h f z+ E
Game1.cs | using System;* Q# n. M0 I7 K2 O( P7 _) s
using System.Collections.Generic;
2 E0 K- Q% v! Q9 e. ] \- I/ V" Susing Microsoft.Xna.Framework;" M0 g8 l+ n& \$ \* g
using Microsoft.Xna.Framework.Audio;! ^9 h- o* C$ H8 f7 J8 Q; V
using Microsoft.Xna.Framework.Content;+ i# W- U# r! Q% [% X
using Microsoft.Xna.Framework.GamerServices;! ?2 i! B1 N) Z) `+ Z; P# W0 K; {
using Microsoft.Xna.Framework.Graphics;
( [' J+ e- A2 Z: \5 e, @using Microsoft.Xna.Framework.Input;3 r3 Z% E- ?) S3 n; `) v/ E
using Microsoft.Xna.Framework.Net;/ n5 D) R' r. r+ a
using Microsoft.Xna.Framework.Storage;4 j! A. V+ a; b" Z+ }
$ X+ K+ [5 N. |
4 n9 J+ G) Y4 n, f/ |6 ^1 c: `namespace HelloWorld {' G! o9 ^6 }' Z& v/ d* I6 {. q( s
public class GameMain : Microsoft.Xna.Framework.Game {# C; i) B8 K: N0 A, ?7 @
private GraphicsDeviceManager graphics; ; }0 @) M1 V2 y& s) f$ _7 S
private SpriteBatch spriteBatch;
! ~/ G( L# ]4 o private SpriteFont font; : |5 _9 Z- C8 w; V( q7 }
9 X6 _6 p5 o1 T, r" i* A
) x0 H; e! o1 h- { public GameMain() {2 D- e* g2 ~8 A" B* n5 s$ t
graphics=new GraphicsDeviceManager(this);
, K5 n: {! ^7 U0 L* W2 ~1 \ Content.RootDirectory="Content";% c$ K" a0 k1 A, z7 q) |9 w+ P
}* g* I+ I) ~" P2 O2 o% `
e: q" K$ s6 N' b5 S
' \7 g+ Q3 s0 _5 ]+ q6 V protected override void Initialize() {
) j* w: ^6 P& p" a1 ?4 U4 V base.Initialize();
l; s4 s, t Y }
# p8 i5 d2 e' T( v. j2 k/ B
- ~, i7 \% c& ]5 y- P* K
9 g* H4 |! j& b5 r! n protected override void LoadContent() {
; J/ {" @( Y* v/ \$ \( _/ [ spriteBatch=new SpriteBatch(GraphicsDevice);
[. R1 \/ p2 ?- m: K$ Y1 M: `7 b- ] font=Content.Load<SpriteFont>("DefaultFont");
; h) h7 U2 p; V* B( } }
4 A% n2 W! w' q" Q/ i/ S5 R( `
4 {- Z% f: e E- N) y& ] o& T" _0 l& b
protected override void UnloadContent() {( n- V- X# E( G r0 I3 z) Q' h# | ]
}+ G8 r* \- v" L- S1 |
3 g/ P. W. F3 |. Y0 _) c" r- {$ P
: t" B( n, X- F0 D' l protected override void Update(GameTime gameTime) {
3 E$ F* ?: ?5 `- l5 q5 u8 t if (GamePad.GetState(PlayerIndex.One).Buttons.Back==
5 ^/ B& o$ D) Q% ~, `7 u8 M. M7 T ButtonState.Pressed) {" Y8 `7 w* ^9 H* R+ q! H/ h
Exit();
0 y* W: `1 B1 O2 w; |& Y2 ]% A }0 q% s% Q8 {' }4 \0 G
+ r$ j+ Z+ W5 j: B/ W) i5 F. \3 {+ @5 L8 k4 ]) \
base.Update(gameTime);2 W' |, r( b: T# q8 o
}
4 Y/ w p) c( f$ O! ^) Y. x3 _+ d3 w- | a& Z
6 a8 D. S* W1 I4 G
protected override void Draw(GameTime gameTime) {1 @$ b# b: p) ^& \6 y# k# N
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
" W* z' F2 w+ s: l8 p: B; K2 m5 `* n2 A3 D
+ L9 \) a& T& o4 N6 ] spriteBatch.Begin();3 a1 o/ m# W B9 F- }
DrawString("中文输入测试,日本語テストを入力する",50,50);
5 w8 }3 X6 F4 h spriteBatch.End();
. A& H! O% w" m8 g$ j c
0 p' _4 [+ `5 x7 D' }: q$ V
6 p2 @7 v* r4 B' _5 N2 ~3 @ base.Draw(gameTime);
% Y- w+ z, ]9 M& T7 M9 E }( p9 ~' e. N5 Z$ T# O
# x! g3 Y" U: J) Q% J7 j9 V" Y5 d5 q( Q# d
private void DrawString(String str,int x,int y) {9 q5 ~- Z, v5 ]* t8 o
spriteBatch.DrawString(font,str,new Vector2(x,y),Color.White);2 ~3 U3 i# R* \9 ^. n( ^
}
+ F, V; t2 [ V& P$ O }: K6 e- N$ m- w! @" j9 I
}
/ @: u0 v, }& q3 a! P9 h6 B# I! `& f' U! r
|
|