原文,附上代码。
. b% z3 Q- J2 Lhttp://ubuntu-gamedev.pbworks.com/Using%20Bitmap%20Fonts%20with%20SDL) o; C* {$ O/ [2 } D
7 i* m% C' q1 XUsing Bitmap Fonts with SDL9 b% B! d. O. t- V; m( _
; E; N/ J6 {3 {: p/ ~- ~' Z6 Y# U
In this article were going to demonstrate how to display text on a SDL Surface in much the same way as we would draw a sprite.
5 k" j9 j# [% [ i# Y ^6 X
" H& d( T( ?9 O% J& Y* Y( `CREDIT WHERE CREDIT IS DUE:
1 ?$ ~& K% L% d. B% E1 AThe code for this How-To was kindly donated to us by VDM of www.ubuntuforums.org who is currently acting as an adviser for us on this project. & t) c5 {8 g9 R! R5 A3 K
0 A) h2 D! @( N* i* T0 e
1 m8 {- x5 H+ R* @* ~6 ^Introduction$ D* @4 q. r2 R a* Y6 c @
A lot of the time its much nicer to display text in a font that is themed the same as your game. This means you are faced with using a specially designed True Type Font or you can create one on a bitmap. Its often better to create a bitmap font because it can be more pleasing to the eye and so add to you games look and feel value. , _! Y$ A* s& A7 _* ?# G0 _! z
; k$ `) l s7 t- G' O6 N
Handling the fonts using a class
$ M& h3 J) G5 {& }; Q& CAs we have said before in previous articles, C++ classes handle this kind of job really well, so we're going to stick with the paradigm and create a class that will do the following:
s1 E( `1 Z" C3 B ( D$ I( s% X- i6 C% N
Handle the loading of the font bitmap* j3 Y+ Q; H |: s: N- }6 Z
Exclusively deal with any information about the font
" A- V3 l! ]! I* [ oDeal with drawing/blitting the font to a Surface
; l+ l. [" e6 L% V/ y6 t& I+ i 9 ]: n4 z0 V/ _, O9 D* ?
So lets define our class:
4 L8 _( A/ E6 n9 F7 {8 y 4 J( L. W L+ O6 Y0 S
3 v) j/ L* {2 J* A4 R+ z
class Font
8 O$ X0 F" Y7 v: D+ K{
3 M7 D+ E% n; r3 k9 O SDL_Surface* m_pFontList; // this is our surface to store the bitmap font
0 d9 F" J: ?0 D) E! Upublic:; G4 P1 M- }. P: L: m U' E
Font(std::string src_file);
$ u( b9 N+ }1 R# l) } virtual ~Font(void);
/ ?0 ~0 s4 }% {" H t int ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen);9 J) N9 g/ n, l' i. R
}; S- T6 I0 ~1 A
7 v% q/ B7 A, S5 I6 |- P3 Z. n
Font(): constructs the class object and loads the specified file into memory.8 t a" J9 R0 r& X
~Font(): destructs the class but currently contains no code. Its still worth having one for possible future changes' i, I+ O' Y& w9 y
ShowText(): handles translating and drawing a specified string onto our surface
8 Q7 F Y" C) q& T 2 p4 n1 X; V' T
Loading the font surface
$ `2 ?$ A+ o+ ~9 z _/ o) ZThis is the easy part! we use the IMG_Load() which we have decided to 'nest' inside thae arguments of our SDL_DisplayFormatAlpha() function. SDL_DisplayFormatAlpha() is the same as the SDL_DisplayFormat() we have used previously but also provides an alpha channel which will be handy to have in future How-Tos. $ U+ K! U0 F: V+ @; S
, i5 d' C% m! N5 [
Heres the code:
7 Q/ {/ D' U3 Q2 f 3 p! r. Q6 x! I4 E6 }9 N
- h# _6 v- u' f2 @
Font::Font(std::string src_file)
1 ~: a, |9 @( {3 w( V{1 A- O' N* n" i/ Z
m_pFontList = SDL_DisplayFormatAlpha(IMG_Load(src_file.c_str()));6 A7 \; d0 n% z4 _" N2 Z7 S9 n# G8 ^
}; F% H+ |8 P2 o+ t5 `' Y9 _+ a- b0 k
% e3 f1 s8 [8 `! d3 Z
Lets go loopy!
& J3 T# T4 `+ s2 i( V' f+ KNow comes the complex part of our Font class, we need to loop through every letter of the string and process which bitmapped letter to draw: " t; m7 X: e* D) }" s
% H a- o' U7 Y
7 o1 g& S1 F2 r& K. Lint Font::ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen)
- f4 n& |1 p7 y* P5 E" V! U, W* p{
, f6 ~$ T7 ]! ^+ D, \ o /* TODO: We need to calculate the fonts height into the pos_y thing. */
' }( |2 W+ s& f; H$ @( W" ~ // Also, id like to see this stuff gathered from an ini file., Z2 G4 ~' m% F: b" }5 U
// That way we can alter fonts without the need for recompilcation+ X+ J; E) n* d) U% ]" z8 o
if(!pScreen) return 1;& ^: Z4 ~ }' V% M- i
// src_rect is the location of the character we need to fetch. 9 h8 V: W& c w- q
// rect will be the destenation, K m, s% b, o. M, O5 L1 U
SDL_Rect rect, src_rect; W7 c4 t ^: @
rect.x = pos_x;
; }; [1 D) U4 I& d4 T% U rect.y = pos_y;
; ~0 d" ~$ C, k4 @% A# {$ J SDL_Rect tmp_rect;/ s6 U' v$ o9 K+ t
tmp_rect.y = 0*type;! h3 z: y w4 t4 J, K
for(int i=0; i < text.size(); i++) {! c b) _* A7 ^( ?0 u* Z$ F
tmp_rect.y = 0; // set right y axe
; K9 V: S5 P- R: I- a: N+ m3 b switch(text) {
) Q) V' D; b* V! I$ v3 a case 0x20:
4 O6 p/ X3 R* R R( m2 |* X rect.x += 10;* D* r# N, {' l5 J3 J9 h/ w
break;
2 Z1 B' S# A, y& E case 0x21: // !
" F& p( p$ Y- g' H1 g' x7 u; a tmp_rect.x = 4;( ~) [! f' ]/ h4 M' g) j
tmp_rect.w = 6;
* u W1 [( L. o5 t tmp_rect.h = 19;
* K: s4 ?, W& _: v) O( K tmp_rect.y = 0;
. F2 b, z. V; j4 s1 q7 \& p SDL_BlitSurface( m_pFontList, &tmp_rect, pScreen, &rect);
' f" k5 ^# ~( T) k rect.x += tmp_rect.w;5 P% B2 K! ?1 v! V* J- L7 P2 R- C
break;
5 G' d8 L; }/ ~. B- Q" V 0 ?# |; E( N/ q7 ]
You'll notice that I didn't put the whole thing up for viewing! If would like to see it in its entirety you can download the source code and look at that!
3 e4 O+ R1 n/ ]. X: X9 \ / I- O& x" ?3 b' E4 a7 s3 v0 B
you can see from the code snippet that we use a switch to test the current letter and then act upon what we find. This involves setting the values of a SDL_Rect and passing it to the SDL_BlitSurface() function which, if you have read the earlier How-Tos, is exactly the same method we have used to draw sprites and background images.
t- c$ L( g; R D, Y, J, n# e
7 a/ h! d# _0 S! QVDM and myself both agree that this could be done more elegantly by using some form of initialization file hat could be loaded at the start instead of setting the values in code. Perhaps that an idea for another How-To! ;-D
' ]; O/ }& ?+ a+ P. s % _0 |/ v" a! f% d' K
Click Here To Download the code sdl-fontfun.tar.gz
; H, D: [6 U4 P8 K0 ]2 ^4 D: h8 c
: C* j* ?5 U6 l6 ?, u# I# Q" ?To compile and run the code: $ h6 S- z" Y2 l4 b
" l: i% l7 r6 m Y8 l: J7 K4 J
% h" H" k( n! O- U8 D2 y/ w/ zg++ -o sdl-funfonts font.cpp sdlfontsfun.cpp `sdl-config --cflags --libs` -lSDL_image
: J! l1 z) g# S./sdl-funfonts& W6 D: L5 M4 x6 B
& a3 K" O5 @ `* L xFinal thoughts% G' U* L; \8 ]8 v
Thats the end of this How-To, we both hope this sheds some light on the game development process. If you have any comments or contribution please feel free to contact us on the ubuntu forums. |