如何修改字幕输出函数,也许这篇文章可以参考。
, v6 ~ Z6 ^8 d* D/ O2 j: Y E' [# Z: O( `0 W4 Q, S. F
, e, U0 p: n& k, A! s8 |6 v( P让OGRE支持中文 (转贴)& }! L2 A" S( k8 A: G, Q
( X; e7 e8 N' Y. s8 \2 H2 H( V% Y* ] j0 ], f8 `
0.前言:% G0 [) ~1 h; Q. D2 f1 e! s8 z7 U& k' p
本人非计算机专业,凭着爱好和一腔热血混入游戏开发大军候补小队,平面尚未钻透。为赶时髦,企图叛变到3D阵营,慌乱之中捡起“OGRE”。学到如今,亦可让正方体飞机等不明物体在三次元空间胡乱打转。但觉得本引擎不支持中文显示而感到不爽,便四处寻求高人指教,但大部分高人指点说:“自己写引擎算了。”衡量了一下自己份量,觉得“自己写”这件事十年内恐尚难做到。再后来找到3DCastle论坛,经过“bug王”以及“浪客☆龙猫” 两位前辈的指点,也通过高手“renwind”遗留下来的教程,误打误撞竟然自己改出了中文支持,兴奋之余便想写点东西留点纪念。
6 A E# \: |" K0 I. q- {1 ]) G. Z4 m1.准备工作
. {7 F5 w4 c, D& N4 ]$ t“bug王”已经通过WINAPI实现了OGRE在Direct7.0下的中文支持,也有高手说这样效率不高,更因为本人基本上是不怎么熟悉WINAPI的,所以就放弃了这种方法。企图直接通过贴图来实现中文显示,毕竟OGRE本身文字输出也是用的这种办法,更好的是OGRE引擎除了普通的“ttf”字体外还支持位图字体(其实“ttf”在引擎中也被Ogre::Font::createTextureFromFont()转换成位图了),基本上就是做一个很大很大的图片,然后上面画满汉字,直接读进去就可以了,问题也就变成了——如何找这个大图片。
) B4 g4 C) ^1 m% S0 ~' t3 v幸好GBA游戏的开发者们已经找到了很好的文字来源和取得方法,通过金山的16*16点阵字库得到接近9000个字模,然后通过程序读出并写到2048*2048的单色位图上,转换成“png”格式图片才221k。9 @8 G# X3 _- `! w
2.基本知识
j7 s- F2 ]8 T6 D$ C修改引擎之前,我们先要知道OGRE是如何显示字体的。OGRE本身面向对象的设计和自带文档都做得非常规范漂亮,很容易就能找到关于显示文字的类以及相关函数。在这里主要看一下关于位图字体是如何显示在画面上。(1)字体的读取。- E0 k: @3 e f
和这项功能相关的有两个类,一个是Ogre::FontManager类,负责分析字体信息(*.fontdef)文件。然后用builder模式构建一个Ogre::Font类。在Font类中最重要的数据莫过于mTexCoords_u1、mTexCoords_u2、mTexCoords_v1、mTexCoords_v2这四个数组,他们分别用来储存不同文字对应在图片上的纹理坐标。 不过数组大小明显不够储存9000个汉字的,一会儿要改的。7 c6 @2 h$ _# V7 P+ [. l
(2)字体的显示。% T7 }6 ]8 ], Z( D, V* Z! J
好像字体显示中用得较多的是Ogre::TextAreaGuiElement类,不过好像还有其他的,我们在这里只看这个吧,估计其他的也大同小异。看了看好像唯一和显示字体有关的函数就是void TextAreaGuiElement::updateGeometry()了,基本上就是根据要写到屏幕上的字串,在Ogre::Font类中得到相应的贴图坐标和贴图,然后画上去,道理也不是很难。; Y. p0 k1 W5 X9 @1 y
3.动手术2 s4 C0 d9 ]! B& _4 T. W' e: Z" Y v
目标锁定到Ogre::Font,Ogre::FontManager,Ogre::TextAreaGuiElement三个类中,把所有文件备份一遍手术开始!. p) D, }: }" Y' }8 B1 l
(1) Ogre::Font类。! [9 C" E# e9 w6 t
首先是储存文字贴图坐标的数组的大小不够,原来定义的是——宽字符集 (1024 - 32)、ASCII(256 - 32)。这点点大小怎么够我近9000字大军进入,索性都改成(9030 - 32)。还有就是set和get文字贴图的id都是char类型数据,256个id也不够分配给汉字,看来要都改成unsigned long形(其实大部分机器上int也是32位,不过long是固定32位的类型,感觉统用点)。1 r) {1 ~" O! f# W- u- |, n
(2) Ogre::FontManager类。* z7 k$ Y( c+ `$ o8 p
里面从脚本文件中解析贴图坐标的方法是根据单字符的方式,为支持汉字,改成同时可以分析int的。一个汉字对应数字是他的区位码+161(前160个留给了半角字)。
. X* H1 r4 P. ], F! T/ Q, p(3) Ogre::TextAreaGuiElement类。
. ^# _ g. w1 ~. k这个是相对比较麻烦的,他要从字串中分辨出到半角字和中文。在这里增加一个std::vector<unsigned long> caption,用来储存分辨的结果。增加以下几行。 D& q# P# H0 v9 I/ y9 K1 ]
std::vector<unsigned long> caption;2 n2 K! }# a! h, ]6 }
unsigned char nTemp;% ]# \' S D& r7 k
String::iterator it=mCaption.begin();
& ~3 H+ p+ i0 n+ F! x+ o7 cfor(;it!=mCaption.end();++it)' d/ F& L/ k2 }
{ j& j% o" h& n
if(unsigned char(*it)<=160)//如果是半角
" \5 g C/ v+ J2 `1 K" [* e* ~{5 `& }. O: p# l2 U( |0 b
caption.push_back((unsigned char)*it);! v0 j8 B h9 J/ u
}
" Y' U, O0 Z0 D% m3 P$ R6 B1 xelse//处理全角字符
8 ~" x: c; a6 Q% C{ 4 c8 Q5 H5 k5 v
nTemp=(unsigned char)(*it);0 m( P! G/ G" K7 q M9 z! W; U
++it;
+ {' k5 g' C6 B5 e; Q' Gif(it==mCaption.end())/ d5 u% M# p; J# r
break;
! P6 ^" ~: W2 i6 {+ m/ z//下面是得到区位码+161的公式。
+ O7 R# X, w+ r3 t+ ycaption.push_back((94*(nTemp-0xa0-1)+((unsigned char)(*it)-0xa0-1))+161);) ~- O* u5 i/ `4 m; Y+ {- O3 ~" @
}7 y* H S2 W9 k6 F+ M0 x' [) f
}
s$ h" ]* m+ v8 d8 d1 m, X4 ~ Q然后后面所有关于mCaption的地方都用caption代替就ok了。
3 z8 x" j* k! b9 |% n( r. x4.结果。
2 @4 Q* \7 t8 ^% O( H3 m. A在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。0 F% z& B! l4 j3 k4 v/ |1 t2 n
因为字体本身原因,文字很扁平的不好看,索性又改了改Ogre::Font,Ogre::FontManager两个类,实现脚本中支持修改文字纵横比例的系数的proportion,当这个值设置为0.8的时候比较好看了。
6 t. v5 x+ v2 ^- Y! a" O7 N* A$ m m( ~; j! Z, S1 d: L6 q
F" Q- P( b- m1 ` n6 ^+ F% I
相关文件
0 H1 _+ r: m9 w7 Ychinese.fontdef//字体信息文件 放在资源文件加中
u& V' ~3 ?( {8 n7 w! G+ k. P$ Ufont.png//字体图片 放在资源文件加中
1 V/ P3 u: {4 ?- W0 b/ z5 s! {7 I P9 K
OgreFont.cpp$ x0 J& g6 W3 z( u6 D, e/ f
OgreFont.h+ U: d9 B' z) [- t6 I0 A A! \! i
OgreFontManager.cpp* ^5 z7 U3 o% R8 Z' O0 ^
OgreTextAreaGuiElement.cpp
) S) o9 j; D p) X& Z* m3 g/ c//上面文件覆盖同名文件 就可以 先备份
8 S' g+ ?* }. Q2 [! U
* f4 h) M8 h& d8 ]) Q) n5 i% I5 l这个是在ogre-win32-v0-13-1基础上改的,请到
0 ~; b2 y9 K5 r+ Y- Uogre-win32-v0-13-1.zip下载
+ U$ f: f% ~' ^; B8 Y4 _. Y: f- @' A% f: A. }
中文字体名字就叫 Chinese,以后能做中文游戏了! |