原文,附上代码。' C0 m( q; q1 l; H( @
http://ubuntu-gamedev.pbworks.com/Using%20Bitmap%20Fonts%20with%20SDL0 T8 y6 W2 X- E7 I
8 K2 X& l# @- f
Using Bitmap Fonts with SDL( k: R' L, W8 d+ b! ]) P
) ?$ O4 _& N0 Z: Y' {' EIn 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.
; t- K. ~5 _8 w/ K/ c
$ L9 q- X5 Q/ U( _+ L4 dCREDIT WHERE CREDIT IS DUE:
$ g; r! T c: W+ IThe 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.
, f$ K& n* b5 |% p % t+ o' X" B/ `6 n6 `
; D! {. W; I( F6 f; L& _$ M
Introduction
' t2 A) ^* n2 l D! bA 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. $ p7 {/ j ?: Q' p8 \& y, Y
3 ^6 E# W4 t3 }6 x
Handling the fonts using a class
, U5 v4 S, \9 AAs 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: ( T3 H% q% i% w) l/ m' g
, M! [) P* X+ J) O5 [
Handle the loading of the font bitmap8 r# \3 X+ i5 C3 Y% D! J1 ^; @( w( N6 x
Exclusively deal with any information about the font4 B0 L7 z' ]$ R4 |; R6 L* [
Deal with drawing/blitting the font to a Surface/ _9 p1 U1 c$ |2 l" ~0 F) a
4 e" d: U% N1 M! E' N/ gSo lets define our class:
l6 `: M$ L& V6 W$ c8 T
+ o: K" H' O0 d1 A+ e2 e" s% N: C0 D& i) q3 W' ^" B: f
class Font8 M+ y( w2 G* e* m; u9 g; w6 Y' h( r
{
$ b; X; a7 V0 T: |2 P SDL_Surface* m_pFontList; // this is our surface to store the bitmap font
8 t8 n& D4 K5 A& f1 \public:
! i) H6 p' Z- d7 \( X9 \* |0 M3 D Font(std::string src_file);
3 Q) z, d% V% H* R" [ virtual ~Font(void); q% W/ }5 _4 W; l. q, J9 d
int ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen);; }' p/ K V1 |9 S; `
};7 e. l) L8 R$ j, d
+ ^* {/ ]1 p1 G* j2 N
Font(): constructs the class object and loads the specified file into memory.; ~: Y" z; Q c3 j
~Font(): destructs the class but currently contains no code. Its still worth having one for possible future changes
0 e( f5 D0 k7 ~4 uShowText(): handles translating and drawing a specified string onto our surface
6 {/ h* d6 J8 q* Q0 M
% w+ B9 j) x. C2 b, f9 rLoading the font surface
* A7 A' O. R& B& s! ]+ fThis 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. * i( F5 m7 d! \
. Y) T; f- u# a# P) pHeres the code: ( Y) ^5 M* F$ D0 s
' N9 Z0 U5 p' a' O- H1 }) Z& c/ ~& e; ]- [5 J% v: O
Font::Font(std::string src_file)' D0 v3 J9 U5 @: k! t x
{
2 A3 s/ Q+ i9 |* Y m_pFontList = SDL_DisplayFormatAlpha(IMG_Load(src_file.c_str()));$ s' z5 A, ~& B
}
2 t B- W7 L& B' ?# Y 3 ?3 \$ e, K4 n- T
Lets go loopy!
: Y) k3 w9 v& a) p2 b2 UNow 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: 5 X } g6 [4 U7 C3 u/ L4 d
& J0 w+ H; k0 E0 s% t3 V2 Z4 P
! u: W9 R R& u, C& e
int Font::ShowText(std::string text, int type, int pos_x, int pos_y, SDL_Surface* pScreen)
5 j0 r! p8 m O! ^, a. G{, J; C" t1 p- N) e' c3 g$ T
/* TODO: We need to calculate the fonts height into the pos_y thing. */0 p& x+ T0 h% Y$ r* R
// Also, id like to see this stuff gathered from an ini file.3 e3 x3 y5 _% `) {! ?
// That way we can alter fonts without the need for recompilcation* z3 N1 E* B! N: J4 n; p
if(!pScreen) return 1;& [: a8 @2 c6 P! _+ M" ]. m1 L
// src_rect is the location of the character we need to fetch. ( L+ G* I1 z$ D s7 I' ?1 k. o( x
// rect will be the destenation) \; |4 ?3 E0 X4 Z" u0 a$ ?
SDL_Rect rect, src_rect; $ I0 J8 V# e0 L- l+ W5 {
rect.x = pos_x;4 `# j) e; D; @% M2 w
rect.y = pos_y;
8 h3 J! H M8 y4 I SDL_Rect tmp_rect;
; M. Q/ T' i9 H: J2 x- F, _5 I tmp_rect.y = 0*type;
- T' e* G4 @: ?) f2 f7 q/ a for(int i=0; i < text.size(); i++) { N2 E" J" Q c9 h1 S
tmp_rect.y = 0; // set right y axe
! M# F7 n+ [6 Q switch(text) {
$ S) Y M0 k: x6 _/ F1 \" M+ ` case 0x20:
3 S& `2 G- y+ w" @8 m; M% [ rect.x += 10;
) {; _3 p# @4 s4 k, q1 }: X# M break;. y# C3 w7 ]- n* f5 T' b
case 0x21: // !
# R- k, P `5 T1 ` tmp_rect.x = 4;
( R1 Q* K" R0 { n7 E' G3 a: i6 | tmp_rect.w = 6;$ M! q0 ?% J6 c v) f
tmp_rect.h = 19;
5 {* c2 Y" Z# a5 h( U tmp_rect.y = 0;
5 ^; V D& ]) | Q SDL_BlitSurface( m_pFontList, &tmp_rect, pScreen, &rect);
2 [1 w0 W; n4 P% I5 W' h2 _, M rect.x += tmp_rect.w;
v0 L K6 M/ G& d break;
7 Y% U3 B& l0 h+ c; A( `
8 `- g, a1 O1 M5 j8 \' h/ LYou'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!
! f/ F1 ` ^/ f" k. g
$ W: c& k( D+ _" G* v' m, ]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. : H$ I$ F9 C c+ L i1 \; u# ]) J
/ K6 M4 d* M; h" N4 L$ r# T
VDM 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
* ^1 Q. G/ Z- H1 M2 Z! B9 E& j4 u
& r A% G* v6 j( b* zClick Here To Download the code sdl-fontfun.tar.gz " H; A. V \3 m/ o$ G1 D! [
# W" N$ q4 S) X% ~2 p. E
To compile and run the code: 0 j( z4 Y5 q" @# P0 q
7 z$ h- Z; e2 |3 Z6 y: `
# L: X) J& d4 ug++ -o sdl-funfonts font.cpp sdlfontsfun.cpp `sdl-config --cflags --libs` -lSDL_image
% J% @2 m4 d& g: P" z/ k0 v& X./sdl-funfonts1 n) ]4 N. }5 w8 L
( f9 {7 H: {: g
Final thoughts
& q) |% o% c) \+ B/ {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. |