原文
1 n* O5 {5 f5 ~* D7 jhttp://blog.csdn.net/lqr801225/archive/2009/05/26/4218688.aspx: H$ O. `) R5 I8 q" }/ c
) Q. u9 c3 a; W" B8 |8 ~ ! v7 g: @& o; U$ c
在XNA中显示中文字符或其它UNICODE字符(非GDI+)
- ]- q7 D) a- D5 u! A! Z; b" S! [XNA3.0+VS2008SP1下调试通过
" G6 ~( j3 R S6 }由于XNA内置的DrawString方法并不能输出全角UNICODE字符,只能设定字符的起始和终止的内码,欧洲语系的字元不多,可以一次导入并生成字体,但像亚洲语系这样动辄上千的字元又是全角,好像设计者并没有考虑到这些情况。为了实现字符输出,已经有一些方法,例如利用.net中的GDI+。下面的实现方法是通过生成自定义的文字托管方式来实现的。
: s( q9 Q! b" f2 {- A" r5 u步骤如下:
! ~4 u4 N- I9 n: }1 s9 u建立字体文件
* M' D4 y+ v% \8 `$ g0 E* B, b[li]在当前项目中的“Content”中点击右键 [/li][li]加入新的文件,类型是"Sprite Font",起名为"DefaultFont.spritefont" [/li][li]打开这个XML格式的文件,将"FontName"节中的字体改成含有目标语言字体的字体文件,这里使用“幼圆” [/li] 字典文件:( l, o s/ N7 K# P9 O
[li]把游戏中需要的文字放到一个文本文件“message.txt”中,方便随时修改,以换行符结尾,内容如下: message.txt | 中文输入测试,日本語テストを入力する
- l7 I7 n4 B! t8 M7 k
# W+ I( J7 n P! F9 R | [/li][li]将这个文件放置在项目的Content目录下。 [/li][li]另存为一下这个文件,以“UTF-8”编码格式。 [/li][li]在解决方案浏览器中选择这个文件,在属性窗口的高级中的“生成操作”中选择“无”,“复制到输出目录”里选择“始终复制”。 [/li] 文字处理类:
3 X5 x4 k/ u6 e) v3 b/ A4 ][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;
9 x5 t$ p$ m( p9 X$ r& Busing Microsoft.Xna.Framework.Content.Pipeline;
9 z) |4 V) y& ]1 eusing Microsoft.Xna.Framework.Content.Pipeline.Graphics;3 R* _: Y8 ^9 z
using Microsoft.Xna.Framework.Content.Pipeline.Processors;$ }1 d4 ^. u& `" v5 O
8 |5 N) {2 y# i, F* l
( f5 B0 o" i+ N3 R* z4 p$ Z
namespace FontProcessors
3 M7 f0 ^/ Z( D5 u$ h' x{: R- R! O+ D6 F N5 c$ e
[ContentProcessor]
7 q, M3 v- v* Y3 o1 x public class DefaultFontProcessor : FontDescriptionProcessor
% G& U+ _. |3 ?3 B( `! \' m3 h {0 m9 X* d+ E& g+ G7 d$ N, U
public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
" y& V7 l+ h( I. g. m3 ~5 A {% z$ T! _' _6 N
//载入文件+ G) U/ Q0 v" K: m, y4 ^2 ~6 \ ]
string fullPath = Path.GetFullPath("message.txt");
8 C4 k% u6 q g/ _3 q y8 ?% _ context.AddDependency(fullPath);
& K# S/ h: U( Y0 `8 U, c, j0 m string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);$ @4 S5 ?8 m( T
1 Y5 @: R/ q+ u4 X! t( ?% j0 X& E$ P, W4 v0 k3 Y$ B$ A
//导入字符5 I' ~2 g1 Y7 s4 h- T' P: b; w
foreach (char c in letters)! C6 ?: p: J! x5 ]8 H
{
/ [9 T7 o7 G6 _7 B0 M; J/ D$ C$ I% d input.Characters.Add(c);
* l) E& l$ j* m# [/ P }
, \2 X8 P, K% w" H return base.Process(input, context);- R! L8 l3 d: ^5 [: N. {& J6 U
}7 N$ `: P2 Q- ?" j# V( q, i
}
5 F8 ]1 Z# h2 {1 ?- h8 F}
5 [# K0 w7 K2 \3 S$ [& \& f8 g4 I. U5 k" i7 B/ q
| 1 y9 Q; ^/ _# p1 O/ ^1 G. G
; I4 k! M. e% A添加项目引用3 G0 x; k9 i* v8 w5 {
[li]在本项目的Content下的"引用"上点击右键,添加项目引用,在弹出的对话框中选择刚才建立的项目:“FontProcessors” [/li][li]在解决方案管理器选择本项目中的字体文件"DefaultFont.spritefont" [/li][li]在属性窗口中的Content Processor中选择我们建立的处理类:"DefaultFontProssor" [/li] 在项目用使用
$ J$ i* K% ~) y9 OGame1.cs | using System;
. t; r# B4 s+ eusing System.Collections.Generic;! Y; i9 N/ i0 {8 [) z
using Microsoft.Xna.Framework;* |% q/ c3 r3 H+ i6 N
using Microsoft.Xna.Framework.Audio;
- q; }2 m; k$ U j7 x8 C: Q. zusing Microsoft.Xna.Framework.Content;' b3 `' C$ G& u# }9 p2 B* h
using Microsoft.Xna.Framework.GamerServices;
+ x; x# c2 @3 n) { X5 Susing Microsoft.Xna.Framework.Graphics;
! I- Z6 f" E+ T8 {using Microsoft.Xna.Framework.Input;
7 _; E% a' S; Z9 U: ?: E2 m+ N0 tusing Microsoft.Xna.Framework.Net;
# z5 T* P' N. k7 B! b1 W7 j3 Qusing Microsoft.Xna.Framework.Storage;+ O" M$ e7 Q$ q G0 u) \4 @
2 v+ t) j' l- V2 z
9 _! e) S8 Q. V2 z' Nnamespace HelloWorld {
4 P+ r- Q1 X/ X% n public class GameMain : Microsoft.Xna.Framework.Game {
( k% P# \8 T5 y9 ]" Z private GraphicsDeviceManager graphics;
3 L, H2 N" j! F private SpriteBatch spriteBatch;7 l l' Q2 p/ w5 W! L& H/ }
private SpriteFont font; 0 b; s, V- u+ `+ B
0 }; V4 `3 |- j% F" _ T; c
0 K: J' @4 ~2 o public GameMain() {
& w6 A7 @& t2 L# M graphics=new GraphicsDeviceManager(this);
( R3 ?4 m( t2 P/ l r Content.RootDirectory="Content";
6 J7 v6 a2 W6 [) ]1 N& J }
0 v. }% B0 {% a2 \7 t) S T0 w) r5 c" V
7 r* k0 G% ?. g& p; k
protected override void Initialize() {
% z% Y) `3 T3 K/ N9 c' t6 N base.Initialize();7 [3 n$ [5 D/ ]2 w) Z& h; D/ C0 |' r$ ^
}( K1 S1 D2 t! |( R) z
; \; g! e/ e4 z1 S; [
0 i& M9 T4 x3 e- v+ z6 f( O protected override void LoadContent() {, Y/ `' k+ _# Z: w: j9 \
spriteBatch=new SpriteBatch(GraphicsDevice);
/ v* Q1 D. O3 _ font=Content.Load<SpriteFont>("DefaultFont");" c5 k7 x( G! U9 {- h
}" `1 j3 B3 w/ l3 v' e4 ~
8 B5 m+ X" T! I$ P
5 x; \: z& W! V protected override void UnloadContent() {
# S8 x- T# H& M( J1 W$ `* w }
$ W' `$ w8 ^# }$ ^2 \7 K) V2 W$ n
( Y) T6 I$ R; f4 I4 x* E2 O+ C+ f: e0 W! O) z1 g. _
protected override void Update(GameTime gameTime) {
' x+ X3 L- X* l0 i( g+ S! i if (GamePad.GetState(PlayerIndex.One).Buttons.Back==& N, _. Y3 b1 D7 t5 E0 l' q# }
ButtonState.Pressed) {
4 e4 f' Y5 N% r3 B" t( H# k Exit();
) h* ]3 ^0 \: b" u }
e. K( ]4 \1 z/ r4 b, l ]* D' U+ S+ c+ o% N5 s* r
, \( C5 c$ u% O4 a+ c- ^0 I- C base.Update(gameTime);
( z9 a: `' j* K" ? }
, G. y% Y' Y9 ?3 v" ~8 T2 ?; x' ]7 t4 ?$ `
0 Q/ S5 v S5 p4 G5 o0 E" Z1 N protected override void Draw(GameTime gameTime) { s- h, ?: e: r9 x
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
0 H, j* T, s T Q! B& N6 w7 y" N, a S% `9 Z3 Y9 Z; I+ ^
: u. Y3 t/ Y4 M, m2 z i' D2 W
spriteBatch.Begin();
" e4 g( L# W$ M9 c DrawString("中文输入测试,日本語テストを入力する",50,50);! ^5 Y* T% V. I! V" Z3 x7 n l
spriteBatch.End();
3 S! O4 M6 O$ ]+ \) E y$ R# U( c
8 V0 O* l+ s e1 z: r- T" g! t' f6 { base.Draw(gameTime);! H, l, e$ J7 H3 E, |8 r, l; M
}
9 T- j7 c' U) w' D- G: C$ z, {* W3 v4 |8 E' Y1 T
4 U+ ]0 c% p: R' A* {8 n% p6 X9 G3 c private void DrawString(String str,int x,int y) {
: l0 a; s# @% P5 w( i* y spriteBatch.DrawString(font,str,new Vector2(x,y),Color.White); l3 z7 p- k' H8 |' ]5 |( B0 i6 @; t: I
}
) g! e- C0 t* |1 h, _ }" ?- T( F, Z3 l
}, {0 U7 Z @$ Q! J g: K& \" ^
! l V @% g% Z( `3 k
|
|