为了在一个基本层次上显示文本,要用到两个不同的对象,即LPD3DXFONT和RECT这两个结构。LPD3DXFONT用于创建和显示文本,而RECT用于确定要显示的文本位置。为了创建LPD3DXFONT对象,就要用到一个名为D3DXCreateFont()的函数。该函数原型如程序清单5.1所示。其成员变量如下:
■ Height:字体字符的高度
■ Width:字体字符的宽度
■ Weight:打印字体的权重(即:粗体)
■ MipLevels:文本的Mipmap级别
■ Italic:字体是否为斜体
■ Charset:用到的字符集
■ OutputPrecision:指定Windows与期望字体大小的匹配方法
■ Quality:指定Windows将字体和真实字体的匹配方法
■ PitchAndFamily:斜度和family索引
■ pFaceName:要用的字体类型名称(例如:Times New Roman)
■ ppFont:要填充的LPD3DXFONT对象
HRESULT D3DXCreateFont(
LPDIRECT3DDEVICE9 pDevice,
INT Height, // 字体字符的高度
UINT Width, // 字体字符的宽度
UINT Weight, // 打印字体的权重(即:粗体)
UINT MipLevels, // 文本的Mipmap级别
BOOL Italic, // 字体是否为斜体
DWORD CharSet, // 用到的字符集
DWORD OutputPrecision, // 指定Windows与期望字体大小的匹配方法
DWORD Quality, // 指定Windows将字体和真实字体的匹配方法
DWORD PitchAndFamily, // 斜度和family索引
LPCTSTR pFacename, // 要用的字体类型名称
LPD3DXFONT * ppFont // 要填充的LPD3DXFONT对象
);
在要创建真实的D3D字体对象时,简单地调用D3DXCreateFont()函数即可。最后一个参数在函数返回后保存字体对象。同Direct3D中的大多数对象一样,读者在使用完字体对象后,一定要确保释放该对象以避免内存泄漏。
当使用D3DXCreateFont()函数创建字体时,大多数参数都用不到。Height参数可被认为是字体的大小。Width是字体附加的宽度,通常取值为0。基本上,Weight是一个控制字体是否加粗的参数。Italic则控制字体是否为斜体。MipLevels可以为文本字符创建Mipmap级别,由于文本不像纹理图像那样可以从屏幕更深入地显示出来,所以该值不能设为1。CharSet为文本设置字符集,但它一般保存默认值。OutputPrecision指定Windows将期望字体与实际字体匹配的方法。同样,该值设为默认值,但如果想要确保正在使用的是TrueType字体,就要将该值设为OUT_TT_ONLY_PRECIS。Quality控制文本特性,它会影响到raster(光栅)字体,而不会影响到TrueType字体。PitchAndFamily在DirectX文档中不好解释,它控制文本使用的pitch和family索引,通常该值设为默认值,如DEFAULT_PITCH | FF_DONTCARE。pFacename是字体的真实名称(例如,Arial、Times New Roman)。最后一个但也很重要的参数是ppFont,它是指正在创建的LPD3DXFONT对象。
渲染文本对象就要用到LPD3DXFONT对象的DrawText()函数。
INT DrawText(
LPD3DXSPRITE pSprite, // 指向包含字符串的LPD3DXSPRITE对象的指针
LPCTSTR pString, // 屏幕上要显示的文本
INT Count, // 字符串字符的数目
LPRECT pRect, // 一个RECT对象,定义了要显示在屏幕上的第一个字符的起始位置
DWORD Format, // 指定字符串的显示方式
D3DCOLOR Color // 屏幕上显示的文本颜色
);
pSprite:它是指向包含字符串的LPD3DXSPRITE对象的指针,如果需要Direct3D内部构建每个角色的小图形,该值可以设为NULL。
■ pString:屏幕上要显示的文本。
■ Count:字符串字符的数目。
■ pRect:它是一个RECT对象,定义了要显示在屏幕上的第一个字符的起始位置。
■ Format:指定字符串的显示方式。表5.1给出了对该值完整的介绍,这些值可以通过XOR一起使用。
■ Color:屏幕上显示的文本颜色。
表5.1 显示文本时可以使用的Format(格式)值
值
|
含义
|
DT_BOTTOM | 将文本调整到定义文本的RECT区域的底部 |
DT_CALCRECT | 计算RECT的高度和宽度。使用pRect参数指定的区域根据需要来调整矩形 |
DT_CENTER | 将文本水平地调整到矩形的中间 |
DT_EXPANDTABS | 拓展字符串中的tab字符。默认情况下tab是8个字符 |
DT_LEFT | 将文本调整到矩形的左侧 |
DT_NOCLIP | 无剪切地绘制文本,这样渲染速度更快 |
DT_RIGHT | 将文本调整到矩形的右侧 |
DT_RTLREADING | 按照从右向左的顺序渲染文本。通常在Hebrew或Arabic字体中使用该值 |
DT_SINGLELINE | 只在一行上显示文本。忽律所有的换行字符 |
DT_TOP | 将文本显示在矩形的顶部 |
DT_VCENTER | 将文本垂直地调整到矩形的中间。只使用单独的一行 |
DT_WORDBREAK | 单词通过定义好的矩形时,将被换行 |
演示程序:
bool InitializeObjects()
{
// Create the font.
// 创建字体
if(FAILED(D3DXCreateFont(
g_D3DDevice,
18, 0, // 字体字符的宽高
0, // 是否加粗
1, // Mipmap级别
0, // 是否为斜体
DEFAULT_CHARSET, // 设置默认字符集
OUT_DEFAULT_PRECIS, // 输出精度,使用默认值
DEFAULT_QUALITY, // 文本质量
DEFAULT_PITCH | FF_DONTCARE,
"Arial", // 字体类型名称
&g_Font // 要填充的LPD3DXFONT字体对象
))) return false;
// Here we are setting the position of the font.
// 设置字体对象将会使用的位置信息
g_FontPosition.top = 0;
g_FontPosition.left = 0;
g_FontPosition.right = WINDOW_WIDTH; // 获取窗口的宽度
g_FontPosition.bottom = WINDOW_HEIGHT; // 获取窗口的高度
return true;
}
如同读者见到的D3DXCreateFont()函数一样,可以将大多数参数设为默认值。唯一关心的几个参数是文本名称和字体高度。程序清单5.4中的最后4行代码将字体设置到默认的位置。注意:获取窗口的高度和宽度是为了可以在屏幕上的任何位置显示文本。创建完字体之后,必须要能将它显示出来,或是用完后将其销毁。这可以使用RenderScene()和Shutdown()函数来实现。程序清单5.5提供了这两个函数的代码。
void RenderScene()
{
// Clear the backbuffer.
g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
// Begin the scene. Start rendering.
g_D3DDevice->BeginScene();
// Set next position and draw text.
g_FontPosition.top = 150;
// 在g_FontPosition位置绘制文本
g_Font->DrawText(NULL, "Ultimate Game Programming!",
-1, &g_FontPosition, DT_CENTER,
D3DCOLOR_XRGB(255,255,255));
// Set next position and draw text.
g_FontPosition.top = 180;
// 在g_FontPosition位置绘制文本
g_Font->DrawText(NULL, "Demo on displaying text.",
-1, &g_FontPosition, DT_CENTER,
D3DCOLOR_XRGB(255,255,255));
// Set next position and draw text.
g_FontPosition.top = 210;
// 在g_FontPosition位置绘制文本
g_Font->DrawText(NULL, "Chapter 5 - TEXT.",
-1, &g_FontPosition, DT_CENTER,
D3DCOLOR_XRGB(255,255,255));
// Set next position and draw text.
g_FontPosition.top = 240;
// 在g_FontPosition位置绘制文本
g_Font->DrawText(NULL, "Next up - GUIs.",
-1, &g_FontPosition, DT_CENTER,
D3DCOLOR_XRGB(255,255,255));
// Set next position and draw text.
g_FontPosition.top = 270;
// 在g_FontPosition位置绘制文本
g_Font->DrawText(NULL, "Bye!",
-1, &g_FontPosition, DT_CENTER,
D3DCOLOR_XRGB(255,255,255));
// End the scene. Stop rendering.
g_D3DDevice->EndScene();
// Display the scene.
g_D3DDevice->Present(NULL, NULL, NULL, NULL);
}
void Shutdown()
{
if(g_D3DDevice != NULL) g_D3DDevice->Release();
if(g_D3D != NULL) g_D3D->Release();
if(g_Font) g_Font->Release(); // 释放字体对象
g_D3DDevice = NULL;
g_D3D = NULL;
g_Font = NULL; // 该指针指向为空
}
RenderScene()函数。这里唯一的几行新代码出现在BeginScene()和EndScene()函数之间。设置想要渲染的每行文本Y坐标。为每行文本设置不同值,这样可以避免将每行文本绘制到另一行文本上。因为要将文本设置在定义好的矩形框中间,所以就不要使用同一X坐标值。如果要将文本向左或向右调整,可以简单地将X坐标(g_FontPosition.left)设为想要显示的位置。将InitializeObjects()函数中的默认值设为0,则文本显示在屏幕的最左边。记住:如果是(0,0)的话,就显示在屏幕的左上角。