16:フォントクラスを作る

 黎明期のパソコンではグラフィック処理をするだけでも大変な処理能力が必要とされていたため、個人で作るゲームといえば、キャラクター(文字)ベースのゲームがあたりまえでした。このキャラクターベースのゲームで有名なものとして「ローグ」があげられます。

不思議なダンジョンシリーズのモチーフとなったゲームでもある

 Direct3Dにおいても2Dグラフィックよりも文字列を扱うプログラムの方が簡単なので、まずは文字列の描画を行うクラスを作成しましょう。Direct3Dによるフォントの描画はID3DXFontインターフェースによって行われます。このインターフェースを基盤とするクラスを作成することで、数行のコーディングでフォント描画を実現できるようにします。
 まずは宣言部。ここではコンストラクタ、デコンストラクタ、フォント作成関数、すべてのパラメータを指定する描画関数、座標と文字列を指定するだけで表示できるものぐさ描画関数(←楽をしたいのならこれは重要)、ID3DXFontインターフェース取得関数を用意してみました。必要に応じて描画関数を拡張するとよいでしょう。
#pragma once
#include "GameObject.h"

class CDxFont : public CGameObject
{
private:
    LPD3DXFONT font;

public:
    CDxFont();
    CDxFont(int fontsize);
    ~CDxFont();

    BOOL Create(int fontsize);

    void Draw(LPCTSTR text, int x, int y);
    void Draw(LPCTSTR text, int count, 
        LPRECT pRect, DWORD Format, D3DXCOLOR Color);

    const LPD3DXFONT GetD3DXFont();
};
#include "DxFont.h"

CDxFont::CDxFont()
{
    font = NULL;
    Create(16);
}

CDxFont::CDxFont(int fontsize)
{
     font = NULL;
    Create(fontsize);
}

CDxFont::~CDxFont()
{
    RELEASE(font);
}

BOOL CDxFont::Create(int fontsize)
{
    RELEASE(font);

    int result = D3DXCreateFont(
        pD3Ddevice,                        // 取得元となるデバイス
        fontsize,                        // 幅
        NULL,                            // 高さ(規定の高さ)
        FW_DONTCARE,                    // 太さ(規定の太さ)
        NULL,                            // ミップマップレベル(なし)
        FALSE,                            // 斜体(なし)
        ANSI_CHARSET,                    // 文字セット(ANSI)
        OUT_DEFAULT_PRECIS,                // 出力精度(標準)
        DEFAULT_QUALITY,                // 出力品質(標準)
        DEFAULT_PITCH | FF_DONTCARE,    // フォントピッチ&フォントファミリ(システムに任せる)
        _T("MS UI Gothic"),                // フォント名
        &font                            // 格納先
    );

    return (result == 0) ? FALSE : TRUE;
}

const LPD3DXFONT CDxFont::GetD3DXFont()
{
    return font;
}

void CDxFont::Draw
    (LPCTSTR text, int count, LPRECT pRect,
    DWORD Format, D3DXCOLOR Color)
{
    if(font){
        pSprite->Begin(NULL);    // 2Dの描画開始を宣言

        font->DrawText(
            pSprite,    // 描画に用いるスプライトオブジェクト
            text,        // 表示する文字列
            count,        // 表示する文字数。-1で文字列すべて
            pRect,        // 文字列を描画する範囲
            Format,        // 文字列描画設定
            Color        // 文字列描画色
        );
        
        pSprite->End();            // 描画終了の宣言
    }
}

void CDxFont::Draw(LPCTSTR text, int x, int y)
{
    // 最低限の指定だけですむものぐさ版
    // [x, y]の位置を左上にして文字列が描画される
    RECT rect = {x, y, x, y};
    Draw(text, -1, &rect,
        DT_NOCLIP | DT_SINGLELINE,
        0xFFFFFFFF);
}
 ID3DXFont::DrawTextのFormat欄に指定できるパラメータの一部をご紹介。
DT_BOTTOM指定枠の底に描画 DT_CENTER指定枠の左右中央に描画
DT_LEFT指定枠の左に描画 DT_NOCLIP枠からはみ出た文字も描画
DT_RIGHT指定枠の右に描画 DT_SINGLELINE改行を無視する
DT_TOP指定枠の上に描画 DT_VCENTER指定枠の上下中央に描画
DT_WORDBREAK単語単位で改行
 Colorパラメータは16進数で指定することができます。左2桁からアルファ値、赤値、緑値、青値となります。たとえば、0xFF00FFFFなら完全不透明のシアン色になります。
class CDxFontTest : public CGameObject
{
private:
    CDxFont font;
protected:
    void Exec();
};

void CDxFontTest::Exec()
{
    font.Draw(_T("文字列描画のテストです"), 100, 100);
}
 試しに上のクラスをタスクリストに追加してみてください。(追加例:AppendObject(new CDxFontTest(), 1000, true);)ウィンドウの特定の位置に指定した文字列が描画されるはずです。
 単独の文字列のみを表示するだけならこれで十分なのですが、複数の文字列を扱うとなると、文字列の分だけID3DXFontが作成されることになり、少しばかり非効率です。そこで次回は、CDxFontオブジェクト自体をタスクリストに追加することによって、より少ないメモリで大量のテキスト描画を行う方法をご紹介します。