我们通过ID3DXFont接口使用任何想用的、安装在系统中的TrueType字体将文本打印到屏幕上。也可以使用基于位图的字体,其字体集以ASCII顺序存储在一个位图文件中,装载了这个位图后,可以借用精灵的特性将字符串中的每个字符渲染出来。DirectX提供了一个字体类,它抽象了整个过程,ID3DXFont接口用于创建字体,我们使用一个名为D3DXCreateFontIndirect的函数来创建字体,最后使用字体对象font的DrawText函数来绘制文字。
还是以前面的例子为基础,首先是DirectX.h文件,添加了新的函数MakeFont来创建并返回一个字体对象,函数FontPrint用于打印文本
1 #pragma once
2
3 #define WIN32_EXTRA_LEAN
4 #define DIRECTINPUT_VERSION 0x0800
5 #include <Windows.h>
6 #include <d3d9.h>
7 #include <d3dx9.h>
8 #include <dinput.h>
9 #include <XInput.h>
10 #include <ctime>
11 #include <iostream>
12 #include <iomanip>
13 using namespace std; 14
15 #pragma comment(lib, "winmm.lib")
16 #pragma comment(lib, "user32.lib")
17 #pragma comment(lib, "gdi32.lib")
18 #pragma comment(lib, "dxguid.lib")
19 #pragma comment(lib, "d3d9.lib")
20 #pragma comment(lib, "d3dx9.lib")
21 #pragma comment(lib, "dinput8.lib")
22 #pragma comment(lib, "xinput.lib")
23
24 extern const string APPTITLE; 25 extern const int SCREENW; 26 extern const int SCREENH; 27 extern bool gameover; 28
29 extern LPDIRECT3D9 d3d; 30 extern LPDIRECT3DDEVICE9 d3ddev; 31 extern LPDIRECT3DSURFACE9 backbuffer; 32
33 //sprite structure
34 struct SPRITE 35 { 36 float x, y; 37 int frame, columns; 38 int width, height; 39 float scaling, rotation; 40 int startframe, endframe; 41 int starttime, delay; 42 int direction; 43 float velx, vely; 44 D3DCOLOR color; 45
46 SPRITE() 47 { 48 frame = 0; 49 columns = 1; 50 width = height = 0; 51 scaling = 1.0f; 52 startframe = endframe = 0; 53 direction = 1; 54 starttime = delay = 0; 55 velx = vely = 0.0f; 56 color = D3DCOLOR_XRGB(255, 255, 255); 57 } 58 }; 59
60 //Direct3D functions
61 bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen); 62 void Direct3D_Shutdown(); 63 bool LoadSurface(string filename, D3DXIMAGE_INFO &info, LPDIRECT3DSURFACE9 &image); 64 void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source); 65 D3DXVECTOR2 GetBitmapSize(string filename); 66 LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor = D3DCOLOR_XRGB(0,0,0)); 67
68 //DirectInput objects, devices, and states
69 extern LPDIRECTINPUT8 dinput; 70 extern LPDIRECTINPUTDEVICE8 dimouse; 71 extern LPDIRECTINPUTDEVICE8 dikeyboard; 72 extern DIMOUSESTATE mouse_state; 73 extern LPD3DXSPRITE spriteobj; 74
75 //DirectInput functions
76 bool DirectInput_Init(HWND); 77 void DirectInput_Update(); 78 void DirectInput_Shutdown(); 79 int Key_Down(int); 80 int Mouse_Button(int); 81 int Mouse_X(); 82 int Mouse_Y(); 83
84 //game functions
85 bool Game_Init(HWND window); 86 void Game_Run(HWND window); 87 void Game_End(); 88
89 //sprite functions
90 void Sprite_Draw_Frame(LPDIRECT3DTEXTURE9 texture, int destx, int desty, 91 int framenum, int framew, int frameh, int columns); 92 void Sprite_Animate(int &frame, int startframe, int endframe, 93 int direction, int &starttime, int delay); 94 void Sprite_Transform_Draw(LPDIRECT3DTEXTURE9 image, int x, int y, int width, int height, 95 int frame, int columns, float rotation, float scaling, D3DCOLOR color); 96
97 //physics functions
98 int Collision(SPRITE sprite1, SPRITE sprite2); 99 bool CollisionD(SPRITE sprite1, SPRITE sprite2); 100
101 //font functions
102 LPD3DXFONT MakeFont(string name, int size); 103 void FontPrint(LPD3DXFONT font, int x, int y, string text, D3DCOLOR color = D3DCOLOR_XRGB(255,255,255));
下面是DirectX.cpp文件
1 #include "DirectX.h"
2 #include <iostream>
3 using namespace std; 4
5 //Direct3D variables
6 LPDIRECT3D9 d3d = NULL; 7 LPDIRECT3DDEVICE9 d3ddev = NULL; 8 LPDIRECT3DSURFACE9 backbuffer = NULL; 9 LPD3DXSPRITE spriteobj; 10
11 //DirectInput variables
12 LPDIRECTINPUT8 dinput = NULL; 13 LPDIRECTINPUTDEVICE8 dimouse = NULL; 14 LPDIRECTINPUTDEVICE8 dikeyboard = NULL; 15 DIMOUSESTATE mouse_state; 16 char keys[256]; 17
18 bool Direct3D_Init(HWND window, int width, int height, bool fullscreen) 19 { 20 //Initialize Direct3D
21 d3d = Direct3DCreate9(D3D_SDK_VERSION); 22 if (!d3d) 23 return false; 24
25 //set Direct3D presentation parameters
26 D3DPRESENT_PARAMETERS d3dpp; 27 ZeroMemory(&d3dpp, sizeof(d3dpp)); 28 d3dpp.hDeviceWindow = window; 29 d3dpp.Windowed = (!fullscreen); 30 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; 31 d3dpp.EnableAutoDepthStencil = 1; 32 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 33 d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; 34 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 35 d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; 36 d3dpp.BackBufferCount = 1; 37 d3dpp.BackBufferWidth = width; 38 d3dpp.BackBufferHeight = height; 39
40 //create Direct3D device
41 d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, 42 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); 43 if (!d3ddev) 44 return false; 45
46 //get a pointer to the back buffer surface
47 d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); 48
49 //create sprite object
50 D3DXCreateSprite(d3ddev, &spriteobj); 51
52 return true; 53 } 54
55 void Direct3D_Shutdown() 56 { 57 if (spriteobj) 58 spriteobj->Release(); 59 if (d3ddev) 60 d3ddev->Release(); 61 if (d3d) 62 d3d->Release(); 63 } 64
65 void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source) 66 { 67 //get width height from source surface
68 D3DSURFACE_DESC desc; 69 source->GetDesc(&desc); 70
71 //create rects for drawing
72 RECT source_rect = {0, 0, (long)desc.Width, (long)desc.Height }; 73 RECT dest_rect = { (long)x, (long)y, (long)x + desc.Width, (long)y + desc.Height}; 74
75 //draw the source surface onto the dest
76 d3ddev->StretchRect(source, &source_rect, dest, &dest_rect, D3DTEXF_NONE); 77 } 78
79 bool LoadSurface(string filename, D3DXIMAGE_INFO &info, LPDIRECT3DSURFACE9 &image) 80 { 81 //get width and height from bitmap file
82 HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info); 83 if (result != D3D_OK) 84 return false; 85
86 //create surface
87 result = d3ddev->CreateOffscreenPlainSurface( 88 info.Width, info.Height, 89 D3DFMT_X8R8G8B8, 90 D3DPOOL_DEFAULT, 91 &image, 92 NULL); 93 if (result != D3D_OK) 94 return false; 95
96 //load surface from file into newly created surface
97 result = D3DXLoadSurfaceFromFile( 98 image, //destination surface
99 NULL, //destination palette
100 NULL, //destination rectangle
101 filename.c_str(), 102 NULL, //source rectangle
103 D3DX_DEFAULT, //controls how image is filtered
104 D3DCOLOR_XRGB(0,0,0), 105 NULL); //source image info
106 if (result != D3D_OK) 107 return false; 108
109 return true; 110 } 111
112 bool DirectInput_Init(HWND hwnd) 113 { 114 //initialize DirectInput object
115 HRESULT result = DirectInput8Create( 116 GetModuleHandle(NULL), 117 DIRECTINPUT_VERSION, 118 IID_IDirectInput8, 119 (void**)&dinput, 120 NULL); 121
122 //initialize the keyboard
123 dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL); 124 dikeyboard->SetDataFormat(&c_dfDIKeyboard); 125 dikeyboard->SetCooperativeLevel(hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND); 126 dikeyboard->Acquire(); 127
128 //initialize the mouse
129 dinput->CreateDevice(GUID_SysMouse, &dimouse, NULL); 130 dimouse->SetDataFormat(&c_dfDIMouse); 131 dimouse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); 132 dimouse->Acquire(); 133
134 ShowCursor(true); 135
136 return true; 137 } 138
139 void DirectInput_Update() 140 { 141 //update mouse
142 dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state); 143
144 //update keyboard
145 dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys); 146 } 147
148 int Mouse_X() 149 { 150 return mouse_state.lX; 151 } 152
153 int Mouse_Y() 154 { 155 return mouse_state.lY; 156 } 157
158 //return mouse button state
159 int Mouse_Button(int button) 160 { 161 return mouse_state.rgbButtons[button] & 0x80; 162 } 163
164 //return key press state
165 int Key_Down(int key) 166 { 167 return (keys[key] & 0x80); 168 } 169
170 void DirectInput_Shutdown() 171 { 172 if (dikeyboard) 173 { 174 dikeyboard->Unacquire(); 175 dikeyboard->Release(); 176 dikeyboard = NULL; 177 } 178
179 if (dimouse) 180 { 181 dimouse->Unacquire(); 182 dimouse->Release(); 183 dimouse = NULL; 184 } 185 } 186
187 //load texture
188 LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor) 189 { 190 LPDIRECT3DTEXTURE9 texture = NULL; 191
192 //get width and height from bitmap file
193 D3DXIMAGE_INFO info; 194 HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info); 195 if (result != D3D_OK) 196 return NULL; 197
198 //create the new texture by loading a bitmap image file
199 result = D3DXCreateTextureFromFileEx( 200 d3ddev, //Direct3D device object
201 filename.c_str(), //filename
202 info.Width, //image width
203 info.Height, //image height
204 1, //mip-map levels (1 for no chain)
205 D3DPOOL_DEFAULT, //the type of surface
206 D3DFMT_UNKNOWN, //surface format
207 D3DPOOL_DEFAULT, //memory class for the texture
208 D3DX_DEFAULT, //image filter
209 D3DX_DEFAULT, //mip filter
210 transcolor, //color key for transparency
211 &info, //bitmap file info
212 NULL, //color palette
213 &texture); //destination texture
214 if (result != D3D_OK) 215 return NULL; 216
217 return texture; 218 } 219
220 D3DXVECTOR2 GetBitmapSize(string filename) 221 { 222 D3DXIMAGE_INFO info; 223 D3DXVECTOR2 size = D3DXVECTOR2(0.0f, 0.0f); 224 HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info); 225 if (result == D3D_OK) 226 size = D3DXVECTOR2((float)info.Width, (float)info.Height); 227
228 return size; 229 } 230
231 //draw sprite frame
232 void Sprite_Draw_Frame(LPDIRECT3DTEXTURE9 texture, int destx, int desty, 233 int framenum, int framew, int frameh, int columns) 234 { 235 D3DXVECTOR3 position((float)destx, (float)desty, 0); 236 D3DCOLOR white = D3DCOLOR_XRGB(255, 255, 255); 237
238 RECT rect; 239 rect.left = (framenum % columns) * framew; 240 rect.top = (framenum / columns) * frameh; 241 rect.right = rect.left + framew; 242 rect.bottom = rect.top + frameh; 243
244 spriteobj->Draw(texture, &rect, NULL, &position, white); 245 } 246
247 void Sprite_Animate(int &frame, int startframe, int endframe, 248 int direction, int &starttime, int delay) 249 { 250 if ((int)GetTickCount() > starttime + delay) 251 { 252 starttime = GetTickCount(); 253
254 frame += direction; 255 if (frame > endframe) 256 frame = startframe; 257 if (frame < startframe) 258 frame = endframe; 259 } 260 } 261
262 void Sprite_Transform_Draw(LPDIRECT3DTEXTURE9 image, int x, int y, int width, int height, 263 int frame, int columns, float rotation, float scaling, D3DCOLOR color) 264 { 265 //create a scale vector
266 D3DXVECTOR2 scale(scaling, scaling); 267
268 //create a translate vector, for moving
269 D3DXVECTOR2 trans(x, y); 270
271 //set rotation center
272 D3DXVECTOR2 center((float)(width*scaling)/2, (float)(height*scaling)/2); 273
274 //create 2D transformation matrix
275 D3DXMATRIX mat; 276 D3DXMatrixTransformation2D(&mat, NULL, 0, &scale, ¢er, rotation, &trans); 277
278 //tell sprite object to use the transform
279 spriteobj->SetTransform(&mat); 280
281 //calculate frame location in source image
282 int fx = (frame % columns) * width; 283 int fy = (frame / columns) * height; 284 RECT srcRect = {fx, fy, fx + width, fy + height}; 285
286 //draw the sprite frame
287 spriteobj->Draw(image, &srcRect, NULL, NULL, color); 288 } 289
290 //bounding box collision detection
291 int Collision(SPRITE sprite1, SPRITE sprite2) 292 { 293 RECT rect1; 294 rect1.left = (long)sprite1.x; 295 rect1.top = (long)sprite1.y; 296 rect1.right = (long)sprite1.x + sprite1.width * sprite1.scaling; 297 rect1.bottom = (long)sprite1.y + sprite1.height * sprite1.scaling; 298
299 RECT rect2; 300 rect2.left = (long)sprite2.x; 301 rect2.top = (long)sprite2.y; 302 rect2.right = (long)sprite2.x + sprite2.width * sprite2.scaling; 303 rect2.bottom = (long)sprite2.y + sprite2.height * sprite2.scaling; 304
305 RECT dest;//ignored, the intersected area between rectangles
306 return IntersectRect(&dest, &rect1, &rect2);//detect if there is collision
307 } 308
309 bool CollisionD(SPRITE sprite1, SPRITE sprite2) 310 { 311 double radius1, radius2; 312
313 //Calculate radius 1
314 if (sprite1.width > sprite1.height) 315 radius1 = (sprite1.width * sprite1.scaling) / 2.0; 316 else
317 radius1 = (sprite1.height * sprite1.scaling) / 2.0; 318
319 //center point 1
320 double x1 = sprite1.x + radius1; 321 double y1 = sprite1.y + radius1; 322 D3DXVECTOR2 vector1(x1, y1); 323
324 //calculate radius2
325 if (sprite2.width > sprite2.height) 326 radius2 = (sprite2.width * sprite2.scaling) / 2.0; 327 else
328 radius2 = (sprite2.height * sprite2.scaling) / 2.0; 329
330 //center point 2
331 double x2 = sprite2.x + radius2; 332 double y2 = sprite2.y + radius2; 333 D3DXVECTOR2 vector2(x2, y2); 334
335 //calculate distance
336 double deltax = vector1.x - vector2.x; 337 double deltay = vector1.y - vector2.y; 338 double dist = sqrt((deltax * deltax) + (deltay * deltay)); 339
340 //return distance comparison
341 return (dist < radius1 + radius2); 342 }
接着是两个新增的函数,在MakeFont函数中,先定义字体描述符desc,然后使用D3DXCreateFontIndirect创建所需的字体对象font。在FontPrint函数中,先定义了一个矩形区域rect(left, top, right, bottom),第一个DrawText函数用于计算正确的rect的right与bottom的值,使用了参数DT_CALCRECT;第二个DrawText函数才开始绘制文本。如果直接给定正确的rect的值,则可以去掉第一个DrawText函数。
1 LPD3DXFONT MakeFont(string name, int size) 2 { 3 LPD3DXFONT font = NULL; 4 D3DXFONT_DESC desc =
5 { 6 size, //height
7 0, //width
8 0, //weight
9 0, //miplevels
10 false, //italic
11 DEFAULT_CHARSET, //charset
12 OUT_TT_PRECIS, //output precision
13 CLIP_DEFAULT_PRECIS, //quality
14 DEFAULT_PITCH, //pitch and family
15 " " //font name
16 }; 17
18 strcpy(desc.FaceName, name.c_str()); 19 D3DXCreateFontIndirect(d3ddev, &desc, &font); 20 return font; 21 } 22
23 void FontPrint(LPD3DXFONT font, int x, int y, string text, D3DCOLOR color) 24 { 25 //figure out the text boundary
26 RECT rect = {x, y, 0, 0}; 27 font->DrawText(NULL, text.c_str(), text.length(), &rect, DT_CALCRECT, color); 28
29 //print the text
30 font->DrawText(spriteobj, text.c_str(), text.length(), &rect, DT_LEFT, color); 31 }
接着是关于窗口创建及消息处理的文件main.cpp,在我前面的例子中讲到过。
1 #include "DirectX.h"
2 using namespace std; 3
4 bool gameover = false; 5
6 //windows event handling function
7 LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 8 { 9 switch (message) 10 { 11 case WM_DESTROY: 12 gameover = true; 13 PostQuitMessage(0); 14 return 0; 15 } 16
17 return DefWindowProc(hwnd, message, wParam, lParam); 18 } 19
20
21 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow) 22 { 23 //set the windows properties
24 WNDCLASSEX wc; 25 wc.cbSize = sizeof(WNDCLASSEX); 26 wc.style = CS_HREDRAW | CS_VREDRAW; 27 wc.lpfnWndProc = (WNDPROC)WinProc; 28 wc.cbClsExtra = 0; 29 wc.cbWndExtra = 0; 30 wc.hInstance = hInstance; 31 wc.hIcon = NULL; 32 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 33 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 34 wc.lpszMenuName = NULL; 35 wc.lpszClassName = APPTITLE.c_str(); 36 wc.hIconSm = NULL; 37 RegisterClassEx(&wc); 38
39 //determine the resolution of the clients desktop screen
40 int screenWidth = GetSystemMetrics(SM_CXSCREEN); 41 int screenHeight = GetSystemMetrics(SM_CYSCREEN); 42
43 //place the window in the middle of screen
44 int posX = (GetSystemMetrics(SM_CXSCREEN) - SCREENW) / 2; 45 int posY = (GetSystemMetrics(SM_CYSCREEN) - SCREENH) / 2; 46
47 //Create a window
48 HWND window; 49 window = CreateWindow(APPTITLE.c_str(), APPTITLE.c_str(), 50 WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, posX, posY, SCREENW, SCREENH, 51 NULL, NULL, hInstance, NULL); 52 if (window == 0) 53 return false; 54
55 //display the window
56 ShowWindow(window, nCmdShow); 57 UpdateWindow(window); 58
59 //initialize the game
60 if (!Game_Init(window)) 61 return 0; 62
63 //main message loop
64 MSG msg; 65 while (!gameover) 66 { 67 //process windows events
68 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 69 { 70 //handle any event messages
71 TranslateMessage(&msg); 72 DispatchMessage(&msg); 73 } 74
75 //process game loop
76 Game_Run(window); 77 } 78
79 //free game resources
80 Game_End(); 81
82 return msg.wParam; 83 }
最后出场的是游戏逻辑处理文件game.cpp,在开头定义了3个字体,然后在初始化函数Game_Init中调用MakeFont函数创建了这3个字体对象。在Game_Run函数中,直接使用了3个FontPrint函数来创建了文本,然后又在下面输出了一段可以自动换行的文本区域,注意参数 DT_WORDBREAK即可。
1 #include "DirectX.h"
2 using namespace std; 3
4 const string APPTITLE = "Font"; 5 const int SCREENW = 1024; 6 const int SCREENH = 576; 7
8 //declare some font objects
9 LPD3DXFONT fontArial = NULL; 10 LPD3DXFONT fontGaramond = NULL; 11 LPD3DXFONT fontTimesNewRoman = NULL; 12
13 //game initialization
14 bool Game_Init(HWND window) 15 { 16 //initialize Direct3D
17 if (!Direct3D_Init(window, SCREENW, SCREENH, false)) 18 { 19 MessageBox(0, "Error initialization Direct3D", "Error", 0); 20 return false; 21 } 22
23 //initialize DirectInput
24 if (!DirectInput_Init(window)) 25 { 26 MessageBox(0, "Error initialization DirectInput", "Error", 0); 27 return false; 28 } 29
30 //create some fonts
31 fontArial = MakeFont("Arial", 24); 32 fontGaramond = MakeFont("Garamond", 36); 33 fontTimesNewRoman = MakeFont("Times New Roman", 40); 34
35 return true; 36 } 37
38 //game update
39 void Game_Run(HWND window) 40 { 41 //make sure the Direct3D device is valid
42 if (!d3ddev) 43 return; 44
45 //update input devices
46 DirectInput_Update(); 47
48 //clear the scene
49 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); 50
51 //start rendering
52 if (d3ddev->BeginScene()) 53 { 54 //start drawing
55 spriteobj->Begin(D3DXSPRITE_ALPHABLEND); 56
57 //demonstrate font output
58 FontPrint(fontArial, 60, 50, "This is the Arial 24 font printed with ID3DXFONT."); 59 FontPrint(fontGaramond, 60, 100, "The text can be printed in any color like this!", 60 D3DCOLOR_XRGB(255, 0, 255)); 61 FontPrint(fontTimesNewRoman, 60, 150, "Or how about bright green instead?", 62 D3DCOLOR_XRGB(0, 255, 0)); 63
64 //demonstrate text wrapping inside a rectangular region
65 RECT rect = {60, 250, 350, 700}; 66 D3DCOLOR white = D3DCOLOR_XRGB(255, 255, 255); 67 string text = "This is a long string that will be "; 68 text += "wrapped inside a rectangle."; 69 fontTimesNewRoman->DrawText(spriteobj, text.c_str(), text.length(), &rect, DT_WORDBREAK, white); 70
71 //stop drawing
72 spriteobj->End(); 73
74 //stop rendering
75 d3ddev->EndScene(); 76 d3ddev->Present(NULL, NULL, NULL, NULL); 77 } 78
79 //escape key exits
80 if (Key_Down(DIK_ESCAPE)) 81 gameover = true; 82 } 83
84 void Game_End() 85 { 86 //free memory
87 if (fontArial) 88 fontArial->Release(); 89 if (fontGaramond) 90 fontGaramond->Release(); 91 if (fontTimesNewRoman) 92 fontTimesNewRoman->Release(); 93 DirectInput_Shutdown(); 94 Direct3D_Shutdown(); 95 }
D3DXFont的使用很简单,但不要创建不常用的字体,以免系统中不存在。本文参考游戏编程入门,源代码,截图如下。