本篇是
创建游戏内核(11)的续篇,其中涉及到的字体知识请参阅D3D中的字体绘制示例。
使用FONT处理文本和字体
虽然ID3DXFont对象处理起来比较容易,但是设置字体却让人痛苦不堪。不要紧,使用FONT类就能快速并容易地得到字体。
来看看FONT类的定义:
class FONT
{
private:
ID3DXFont* _font;
public:
FONT();
~FONT();
ID3DXFont* Get_Font_COM();
BOOL Create(GRAPHICS* graphics, char* face_name, long size = 16, BOOL is_bold = FALSE, BOOL is_italic = FALSE);
void Free();
BOOL Print(char* text, long x_pos, long y_pos, long width = 0, long height = 0,
D3DCOLOR color = 0xFFFFFFFF, DWORD format = 0);
};
接着是FONT类的实现:
//-------------------------------------------------------------------
// Constructor, initialize data member.
//-------------------------------------------------------------------
FONT::FONT()
{
_font = NULL;
}
//-------------------------------------------------------------------
// Destructor, release font resource.
//-------------------------------------------------------------------
FONT::~FONT()
{
Free();
}
//-------------------------------------------------------------------
// Get pointer to font object.
//-------------------------------------------------------------------
ID3DXFont* FONT::Get_Font_COM()
{
return _font;
}
//-------------------------------------------------------------------
// Create font object.
//-------------------------------------------------------------------
BOOL FONT::Create(GRAPHICS *graphics, char* face_name, long size, BOOL is_bold, BOOL is_italic)
{
D3DXFONT_DESC font_desc;
// check condition first
if(graphics == NULL || face_name == NULL)
return FALSE;
if(graphics->Get_Device_COM() == NULL)
return FALSE;
// clear out the font structure
ZeroMemory(&font_desc, sizeof(D3DXFONT_DESC));
// set the font property
strcpy(font_desc.FaceName, face_name);
font_desc.Height = -size;
font_desc.Weight = is_bold ? 700 : 0;
font_desc.Italic = is_italic;
// create the font object
if(FAILED(D3DXCreateFontIndirect(graphics->Get_Device_COM(), &font_desc, &_font)))
return FALSE;
return TRUE;
}
//-------------------------------------------------------------------
// Release font resource.
//-------------------------------------------------------------------
void FONT::Free()
{
Release_COM(_font);
}
//-------------------------------------------------------------------
// Draw text.
//-------------------------------------------------------------------
BOOL FONT::Print(char* text, long x_pos, long y_pos, long width, long height, D3DCOLOR color, DWORD format)
{
RECT rect;
if(_font == NULL)
return FALSE;
// set draw region's width and height
if(width == 0) width = 65536;
if(height == 0) height = 65536;
// set draw region
rect.left = x_pos;
rect.top = y_pos;
rect.right = rect.left + width;
rect.bottom = rect.top + height;
// draw text now
if(FAILED(_font->DrawText(NULL, text, -1, &rect, format, color)))
return FALSE;
return TRUE;
}
要使用某个字体,使用FONT::Create函数来创建,必须给Create函数传递一个预初始化的GRAPHICS对象,提供一个字体名称,并指定字体的大小(使用像素高度的近似值)。
打印一行文本时,需要给FONT::Print函数提供一个指向要打印文本的指针、开始打印处的坐标、用于裁剪文本的边界框(bounding
box,即文本区域框)的大小(width和height的缺省值为0,表示全屏)、文本的颜色(缺省为白色,而且要使用D3DCOLOR_RGBA宏定义颜色)以及文本格式。
下表列出了打印文本时可以使用的格式:
标志 |
说明 |
DT_BOTTOM |
将文本对齐到边界矩形的底部。 |
DT_CENTER |
在边界矩形中将文本水平居中。 |
DT_LEFT |
将文本左对齐到边界矩形的左边缘。 |
DT_NOCLIP |
绘制文本,不将文本裁剪到边界矩形中,用于快速绘制。 |
DT_RIGHT |
将文本右对齐到边界矩形的右边缘。 |
DT_TOP |
将文本对齐到边界矩形的顶部。 |
DT_WORDBREAK |
当到达边界矩形的右边缘时,文本将自动切换到下一行输出。 |
下面来看看一个完整的示例:
点击下载源码和工程
/*****************************************************************************
PURPOSE:
Test for class FONT.
*****************************************************************************/
#include "Core_Global.h"
#pragma warning(disable : 4996)
//===========================================================================
// Defines class APP which public inherits from class APPLICATION.
//===========================================================================
class APP : public APPLICATION
{
private:
GRAPHICS _graphics;
FONT _font;
public:
BOOL Init();
BOOL Shutdown();
BOOL Frame();
};
//-----------------------------------------------------------------------------
// Initialize graphics, set display mode, create font object.
//-----------------------------------------------------------------------------
BOOL APP::Init()
{
// initialize graphics
if (! _graphics.Init())
return FALSE;
// set display mode for graphics
if(! _graphics.Set_Mode(Get_Hwnd(), TRUE, TRUE, 400, 400, 32))
return FALSE;
// create font object
if(! _font.Create(&_graphics, "Segoe Script", 32))
return FALSE;
return TRUE;
}
//-----------------------------------------------------------------------------
// Release all d3d resource.
//-----------------------------------------------------------------------------
BOOL APP::Shutdown()
{
return TRUE;
}
//-----------------------------------------------------------------------------
// Render a frame.
//-----------------------------------------------------------------------------
BOOL APP::Frame()
{
// clear display with specified color
_graphics.Clear(D3DCOLOR_RGBA(0, 0, 0, 255), 1.0);
// begin scene
if(_graphics.Begin_Scene())
{
// draw text
_font.Print("How are you, cloud?", 0, 0, _graphics.Get_Width(), _graphics.Get_Height(),
0xFFFFFFFF, DT_CENTER | DT_VCENTER);
// end the scene
_graphics.End_Scene();
}
// display video buffer
_graphics.Display();
return TRUE;
}
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
return app.Run();
}
运行截图: