文字——弹幕?

***万物皆虚,万事皆允 ——《刺客信条》***

这里写图片描述

继续Directx3D游戏开发之旅:

字体:

在游戏中,经常要向用户显示一些文本信息。所以就需要我们创建字体和显示字体了,通过几天学习,发现文本上的处理算是所有处理里面最让人头疼的了,尤其是汉字编码,是采用utf-8进行字符编码还是utf-16进行编码,貌似大多数采用utf-16都可以基本解决问题,但不排除其他情况,可能还需要考虑utf-32(即为一个字DWORD),来进行处理。

所以在游戏中开发自己的字体的时候,应多给予此方面的考虑

下面开始学习DirectX为我们提供的字体参考样例,方便学习创建属于自己的字体。

利用ID3DXFont接口

在DirectX中D3DX库提供了接口ID3DXFont,该接口的实质上还是使用GDI(graphics device interfere)接口来绘制文本,所以该接口在速度性能上效果不太好,但可以Directx为其提供了一些API,方便处理一些复杂的字体和格式

创建两步走:
1、创建一个ID3DXFont接口对象
2、利用DrawText绘制文本


创建一个ID3DXFont接口对象:
先利用D3DXCreateFontIndirect函数来创建一个ID3DXFont接口对象。
先看看这个函数的简介:

HRESULT  D3DXCreateFontIndirect(
  __in   LPDIRECT3DDEVICE9 pDevice,        //设备与字体结合
  __in   const D3DXFONT_DESC *pDesc,       //D3DXFONT_DESC的结构对象
  __out  LPD3DXFONT *ppFont                //即返回创建好的字体
);


//接下来看看D3DXFONT_DESC这个结构体,需要填充哪些信息
HRESULT  D3DXCreateFont(
  __in   LPDIRECT3DDEVICE9 pDevice,     //设备与字体结合
  __in   INT Height,                    //字体高度
  __in   UINT Width,                    //字体宽度
  __in   UINT Weight,                   //字体的权重,是否加粗,范围(0~1000)
  __in   UINT MipLevels,                //The number of mipmap levels(纹理映射等级,一般设置为D3DX_DEFAULT)

  __in   BOOL Italic,                   //设置是否为斜体字体,true代表是,反之亦然
  __in   DWORD CharSet,               //字体的字符集,一般设为默认DEFAULT_CHARSET
  __in   DWORD OutputPrecision,       //指定了窗口应该尝试匹配所需的字体大小和字体的特点与实际,一般设置为0
  __in   DWORD Quality,              //指定Windows如何应所需的字体和一个真正的字体匹配。它适用于光栅字体
  __in   DWORD PitchAndFamily,       //Pitch and family index
  __in   LPCTSTR pFacename,          //设置字体的风格
  __out  LPD3DXFONT *ppFont          //其余参数设置完后,返回一个指针指向一个LPD3DXFONT接口,表示所创建的字体对象
);

绘制文本:
通过调用方法DrawText便可轻松完成字体的绘制。

INT DrawText(
  [in]  LPD3DX10SPRITE pSprite,       //指定字符串所属的ID3DXSprite对象接口,可设为默认值0或NULL,表示在当前窗口中绘制字符串
  [in]  LPCTSTR pString,      //指向将要绘制的字符串的指针
  [in]  INT Count,          //统计字符串中的字符个数,若该值为-1,则认为参数pString指向一个以NULL结尾的字符串。
  [in]  LPRECT pRect,   //指定字符串绘制的矩形区域的位置
  [in]  UINT Format,    //指定字符串在pRect指定的矩形区域中的格式化方法。
  [in]  D3DXCOLOR Color  //设置文本颜色
);
ItemDescription
DT_BOTTOM将文本对齐到矩形的底部,但是该值必须与 DT_SINGLELINE进行配合使用
DT_LEFT向左对齐
DT_RIGHT向右对齐
DT_TOP将文本对齐到矩形的顶部

还有其余个别参数,及不一 一列举了

例如:绘制一个简单文本

ID3DXFont* Font = 0;
DWORD FrameCnt = 0;
//创建字体
	D3DXFONT_DESC lf;
	ZeroMemory(&lf, sizeof(D3DXFONT_DESC));

	lf.Height = 25;    // in logical units
	lf.Width = 12;    // in logical units
	lf.Weight = 500;
	lf.MipLevels = D3DX_DEFAULT;
	lf.Italic = FALSE;
	lf.CharSet = DEFAULT_CHARSET;
	lf.OutputPrecision = 0;
	lf.Quality = 0;
	lf.PitchAndFamily = 0;
	strcpy_s((char *)lf.FaceName,sizeof("Times New Roman"), "Times New Roman");	// font style
				
	 // 基于“IF”创建字体格式.					
	if (FAILED(D3DXCreateFontIndirect(Device, &lf, &Font)))
	{
		::MessageBox(0, L"D3DXCreateFontIndirect() - FAILED", 0, 0);
		::PostQuitMessage(0);
	}

开始绘制字体:

bool Display(float timeDelta)
{
	if (Device)
	{
		
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		RECT rect = { 0, 0, Width, Height };
		//绘画出字体
		Font->DrawText(
			NULL,
			L"Hello World ", 
			-1,          
			&rect,
			DT_TOP | DT_LEFT, 
			0xff000000);     
		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

这里写图片描述


利用CD3DFont

在DirectX SDK中提供了一个类——CD3DFont类,该类可以借助Direct3D和映射有纹理的三角形来绘制文本,由于该类使用的是Direct3D而并非GDI,所以其绘制速度会比前面的ID3DFont要快得多,但该类也有极大的缺陷,就是不支持ID3DFont所支持的那些复杂的字体和格式,而且尤其是对汉字字符非常抵触,如果要想让其既支持各种复杂的字体和格式,又要让其能支持汉字字符的编码,这就得需要自己重写或者自己封装一个属于自己的字体类。

下面来看看使用的实例:

方法还是和前面一样,首先创建对象

先来看看,该类构造函数的原型

CD3DFont(const TCHAR * strFontName,DWORD dwHeight,DWORD dwFlags=0L);
//strFontName:表示一个以NULL结尾的字符串,它指定了字体的名称
//dwHeight:所创建字体的高度
//dwFlags:创建标记,参数可以是D3DFONT_BOLD、D3DFONT_ITALIC、D3DFONT_ZENABLE的组合,自己表示没怎么用过这些组合。

实例化对象,进行初始化

CD3DFont* Font = 0;
Font = new CD3DFont(_T("Times New Roman"), 16, 0);
Font->InitDeviceObjects(Device);
Font->RestoreDeviceObjects();

接下来,咱们绘制文本,在CD3DFont类中有个绘制函数提供使用

HRESULT CD3DFont::DrawText(FLOAT x,FLOAT y,DWORD dwColor,const TCHAR * strText,DWORD dwFlags=0);
//x,y表示文本绘制起点的x坐标和y坐标
//dwColor表示文本的颜色
//strText:表示指向所要绘制文本的指针
//dwFlags:绘制的标记

调用绘制函数

Font->DrawText(10,10,0xff000000,"Hello World");

差点忘了,该文件需要包含D3DFont.h头文件

#ifndef D3DFONT_H
#define D3DFONT_H
#include <tchar.h>
#include <D3D9.h>


// Font creation flags
#define D3DFONT_BOLD        0x0001
#define D3DFONT_ITALIC      0x0002
#define D3DFONT_ZENABLE     0x0004

// Font rendering flags
#define D3DFONT_CENTERED    0x0001
#define D3DFONT_TWOSIDED    0x0002
#define D3DFONT_FILTERED    0x0004




//-----------------------------------------------------------------------------
// Name: class CD3DFont
// Desc: Texture-based font class for doing text in a 3D scene.
//-----------------------------------------------------------------------------
class CD3DFont
{
	TCHAR   m_strFontName[80];            // Font properties
	DWORD   m_dwFontHeight;
	DWORD   m_dwFontFlags;

	LPDIRECT3DDEVICE9       m_pd3dDevice; // A D3DDevice used for rendering
	LPDIRECT3DTEXTURE9      m_pTexture;   // The d3d texture for this font
	LPDIRECT3DVERTEXBUFFER9 m_pVB;        // VertexBuffer for rendering text
	DWORD   m_dwTexWidth;                 // Texture dimensions
	DWORD   m_dwTexHeight;
	FLOAT   m_fTextScale;
	FLOAT   m_fTexCoords[128 - 32][4];

	// Stateblocks for setting and restoring render states
	LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved;
	LPDIRECT3DSTATEBLOCK9 m_pStateBlockDrawText;

public:
	// 2D and 3D text drawing functions
	HRESULT DrawText(FLOAT x, FLOAT y, DWORD dwColor,
		const TCHAR* strText, DWORD dwFlags = 0L);
	HRESULT DrawTextScaled(FLOAT x, FLOAT y, FLOAT z,
		FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
		const TCHAR* strText, DWORD dwFlags = 0L);
	HRESULT Render3DText(const TCHAR* strText, DWORD dwFlags = 0L);

	// Function to get extent of text
	HRESULT GetTextExtent(const TCHAR* strText, SIZE* pSize);

	// Initializing and destroying device-dependent objects
	HRESULT InitDeviceObjects(LPDIRECT3DDEVICE9 pd3dDevice);
	HRESULT RestoreDeviceObjects();
	HRESULT InvalidateDeviceObjects();
	HRESULT DeleteDeviceObjects();

	// Constructor / destructor
	CD3DFont(const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags = 0L);
	~CD3DFont();
};
#endif

源文件过长就放码云,或者源程序中

运行效果图:
这里写图片描述


利用D3DXCreateText函数

这个函数和前面两种略有区别,前面两种都只涉及到x和y坐标,而没涉及到z坐标,而此函数就涉及到了,采用3D网格来进行创建文本。

首先来看看此函数的原型,看看咱们怎么使用

HRESULT D3DXCreateText(
	LPDIRECT3DDEVICE9 pDevice,     //指向与网格相关的设备
	HDC hdc,                      //设备环境句柄,包含了用来创建网格字体的相关信息
	LPCTSTR pText,     //确定所要生成文本的字符串的指针
	FLOAT Deviation,    //字体轮廓的最大弦偏差,该值必须>=0
	FLOAT Extrusion,    //z轴负方向度量的字体深度
	LPD3DXMESH* ppMesh,  //返回创建的网格
	LPD3DXBUFFER *ppAdjacency,     //返回创建网格的邻接信息
	LPGLYPHMETRICSFLOAT pGlyphMetrics   //包含字体的度量数据
	);

关于填充LOGFONT结构

typedef struct tagLOGFONT { 
  LONG lfHeight;          //高度
  LONG lfWidth;           //宽度
  LONG lfEscapement;      //角度
  LONG lfOrientation;     //方向
  LONG lfWeight;          //权重 0~1000
  BYTE lfItalic;          //是否为斜体
  BYTE lfUnderline;       //是否有下划线
  BYTE lfStrikeOut;       //指定删除线字体
  BYTE lfCharSet;         //字符集,ANSI还是unicode等
  BYTE lfOutPrecision;    //输出精度
  BYTE lfClipPrecision;   //裁剪精度
  BYTE lfQuality;          //指定Windows如何应所需的字体和一个真正的字体匹配。它适用于光栅字体
  BYTE lfPitchAndFamily;     //Pitch and family index
  TCHAR lfFaceName[LF_FACESIZE]; //指定字体的风格,且长度不能超过32个字符
} LOGFONT, *PLOGFONT; 

如何使用?
创建

HDC hdc = CreateCompatibleDC(0);
HFONT hFont;
HFONT hFontOld;

LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));
 
lf.lfHeight = 25;    // in logical units
lf.lfWidth = 12;    // in logical units
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = 500;   // boldness, range 0(light) - 1000(bold)
lf.lfItalic = false;
lf.lfUnderline = false;
lf.lfStrikeOut = false;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = 0;
lf.lfClipPrecision = 0;
lf.lfQuality = 0;
lf.lfPitchAndFamily = 0;
strcpy_s((CHAR *)lf.lfFaceName,sizeof("Times New Roman"), "Times New Roman"); // font style

hFont = CreateFontIndirect(&lf);
hFontOld = (HFONT)SelectObject(hdc, hFont);

D3DXCreateText(Device, hdc, L"Direct3D",
		0.001f, 0.4f, &Text, 0, 0);


SelectObject(hdc, hFontOld);
DeleteObject(hFont);
DeleteDC(hdc);

绘制

Text->DrawSubset(0);

效果:
这里写图片描述


试试自己的弹幕效果:
这里写图片描述

资源下载:

http://download.csdn.net/download/qq_33248019/10138562

码云下载:
https://gitee.com/lengya/codes/gfcmp0wk3j7vy4haer1bo37

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值