原文,附上代码。! c0 L. F$ p6 O4 R
http://ubuntu-gamedev.pbworks.com/Using%20Bitmap%20Fonts%20with%20SDL: i; [& f2 B8 G
! j, Z: L$ }* X- h' H+ SUsing Bitmap Fonts with SDL
" Y, y5 d; F! O ( X9 J4 h5 c& D6 Q
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.
+ H3 m9 U3 D- @2 Y6 e- k5 X
' m" P2 {8 z. ?, O+ RCREDIT WHERE CREDIT IS DUE:
! P- N3 T- {9 K! NThe 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.
2 D y+ B( T1 g- G) D+ D- T9 k
0 ]3 D* Y, l5 ]) c5 |
4 u4 T. o1 w7 TIntroduction
. G3 \3 D/ y- z( q3 ], q' p$ p- H0 B# _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.
4 m9 K5 _4 c ?0 R
3 [: T6 t2 @ E. v- r; RHandling the fonts using a class
9 R/ g0 b4 j/ O( V( r1 rAs 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: $ `* t1 N) w% E# c3 S) l
5 B2 M- i8 y5 c4 h
Handle the loading of the font bitmap
' }2 w$ p4 e9 c1 oExclusively deal with any information about the font9 s U. C+ a$ S7 H( D
Deal with drawing/blitting the font to a Surface
( B- c2 g/ a! r# b1 k
5 C9 o1 n/ S- `( VSo lets define our class: ' V- y9 ?: j3 @4 `- @
% ?9 O) q' P2 V4 u
7 g8 F! A6 a( t# W7 nclass Font- C1 T6 d7 C- ?& q. w5 L" h
{
% _- u- t* o3 L SDL_Surface* m_pFontList; // this is our surface to store the bitmap font# K$ }/ @) e% ~% o# y7 k5 [
public:4 E1 p0 c( h, Z0 S
Font(std::string src_file);" Z+ g3 D1 Q: o) U9 @' s
virtual ~Font(void);
& S. a, K' U. w0 G int ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen);
' W0 Y" e* u) E};: ^) }+ F% o! ^" e4 i6 ?
9 w! {7 t3 `& k' l' u J
Font(): constructs the class object and loads the specified file into memory.
& y: @# ^& g6 G( c~Font(): destructs the class but currently contains no code. Its still worth having one for possible future changes
! I G5 ?, h1 v2 _4 r6 V# S" DShowText(): handles translating and drawing a specified string onto our surface
" F% E. S# C5 @$ B! J ' R5 R4 A, L, B. Q3 B$ Z# E7 {
Loading the font surface
# Q# |. o S" T% l" G8 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.
2 i0 Z# p. n2 ]! N( q8 k. N
8 U+ B$ o+ B/ d; e" C' fHeres the code: 0 a- e, k5 L- Z- K
4 S) s J/ ]8 L: r9 Z7 T
1 k, G+ d0 J; S/ u. A) `Font::Font(std::string src_file)
+ B* V# K' l3 I/ j{0 N Z2 \8 U. O
m_pFontList = SDL_DisplayFormatAlpha(IMG_Load(src_file.c_str()));) A& O' b, s& q9 z; b
}
, e6 d- `! h5 u7 z8 m6 M
) [. Z9 q4 \; ^8 Q+ W4 H3 yLets go loopy!
" W6 }( c, o- q1 hNow 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; L' l# \, {' L+ N) N
* X5 f& n0 v8 o0 U5 c' }
& T! c2 ]% \' T5 \int Font::ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen)4 @$ K; V: ^& \7 b. W
{* A' Z( o6 v6 r
/* TODO: We need to calculate the fonts height into the pos_y thing. */6 T/ `3 r W |: |+ Y" \
// Also, id like to see this stuff gathered from an ini file.! D& F' o" e) r' ?$ e `
// That way we can alter fonts without the need for recompilcation, D+ r4 k9 T# }' `. W: g% [/ ~
if(!pScreen) return 1;
! Y6 \' m |0 z7 B // src_rect is the location of the character we need to fetch.
3 h- m% I1 y) x, |6 w7 w" W // rect will be the destenation
- a- P0 ]0 v, T2 r4 T SDL_Rect rect, src_rect; : Y+ w% @! Y' }2 w2 |
rect.x = pos_x;% I" O. k% o0 o3 t
rect.y = pos_y;
( q: M7 u% z1 Q+ u- G5 N SDL_Rect tmp_rect;+ k9 E+ M. E5 l5 `
tmp_rect.y = 0*type;& `3 k7 C1 m6 D1 Z9 T0 f
for(int i=0; i < text.size(); i++) {
9 V c7 g! {, v: w2 ? tmp_rect.y = 0; // set right y axe8 t6 S3 R6 I/ O2 z0 d4 q
switch(text) { n" _" {7 c) k' e2 G6 ?
case 0x20: G6 q/ i1 @6 j" C& p* o6 e3 K
rect.x += 10;
- H3 q6 \. Q% ?1 W break;
* y) x4 u- |( @3 x- x6 J case 0x21: // !* D7 \4 Q _0 q
tmp_rect.x = 4;
0 w m0 L4 i7 {9 { tmp_rect.w = 6;# d; k i9 V% N1 b4 o) `) E
tmp_rect.h = 19;% w$ N* ^* W) N! F% f" ~
tmp_rect.y = 0;. m, e8 T3 X$ z- ?. ^1 V
SDL_BlitSurface( m_pFontList, &tmp_rect, pScreen, &rect);
5 h% H( {0 x5 u! N! e, l5 q- B# Q rect.x += tmp_rect.w;; K- q* z. h9 R: t& D2 a9 l4 m7 y
break;% V0 s7 p. ]; h4 Q) W& \
! f/ z7 j% Z! O& j2 pYou'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!
( r/ w# F5 {* G2 I+ M . z0 w% N4 b% E( {' i
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. $ f) z& u; l5 Y1 P9 B
8 n# d3 s5 H6 o; t* pVDM 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 3 o% p8 C# ]4 K, ? i' W
O: A8 L4 S. w. D( k! L0 D& _; C
Click Here To Download the code sdl-fontfun.tar.gz
: B1 r R# U# C* h
+ `" \6 @0 K4 v/ C+ W6 HTo compile and run the code: 2 _" |7 K+ n, v: X
' R9 R" b8 h' f2 h& K$ x' i8 q8 F: F+ F+ S) l: I% c
g++ -o sdl-funfonts font.cpp sdlfontsfun.cpp `sdl-config --cflags --libs` -lSDL_image" c4 S1 L$ b0 w# C( I
./sdl-funfonts( Q$ I; Z. o6 T) \9 j0 ^5 r7 C" h$ d
( M2 G8 c7 A" }/ d; N% B) t1 P
Final thoughts
" p8 [9 |6 w7 [% Y) p# d1 i- W* _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. |