ゲームプログラムのメモ書き

DirectX

デバッグ文字列の表示 〜画面に映して分かりやすくしよう〜

ゲーム内のデータ(数値)は刻々と変化する物。デバッグ中にそれらを画面に映し確認できると
作業がしやすくなります。

LPD3DXFONT pFont;	//フォント
HRESULT InitFont(LPD3DXDEVICE9 pDevice)
{
    //文字列フォントの設定
    if(FAILED(D3DXCreateFont(pDevice,
        14,                     //文字高さ
        7,                      //文字幅
        FW_BOLD,                //フォントスタイル
        NULL,                   //ミップマップモデルの数
        FALSE,                  //斜体にするかどうか
        SHIFTJIS_CHARSET,       //文字セット
        OUT_DEFAULT_PRECIS,
        PROOF_QUALITY,
        FIXED_PITCH | FF_MODERN,
        "tahoma",               //フォントの種類
        &pFont)))
    {
        return E_FAIL;
    }
    return TRUE;
}

D3DXCreateFont関数でフォントを生成します。 フォントの種類はワードで使用されているものは使える様です。 また、参考書にはtahomaフォントが例にあげられているものが多いです。 なので、ここでもtahomaにしておきます。




//文字列レンダリング関数
VOID RenderString(LPD3DXFONT pFont,
            LPSTR szStr,    //表示する文字列
            INT iX,         //表示X座標
            INT iY)         //表示Y座標
{
    RECT rect = {iX, iY, 0, 0}; //表示領域

    //文字列サイズを計算
    pFont->DrawText(
        NULL,
        szStr,
        -1,             //表示サイズ(-1で全部)
        &rect,          //表示範囲
        DT_CALCRECT,    //表示範囲に調整
        NULL);

    //そのサイズでレンダリング
    pFont->DrawText(
        NULL,
        szStr,
        -1,                     //表示サイズ(-1で全部)
        &rect,                  //表示範囲
        DT_LEFT | DT_BOTTOM,    //左詰めで両端揃え
        0xff00ff00);            //色
}

■使い方

RenderString(pFont, "文字列", 10, 10);

これで文字列の表示が出来ました。 たかがデバッグ文字列、されどデバッグ文字列です。これが有ると無いとで バグの発見しやすさが大分変わります。






■扱いやすくしてみる
上記の方法では、文字列をRenderString関数に渡すため、例えば数値を表示する際に

char str[64];
sprintf(str, "%d", 何かの値);
RenderString(pFont, str, 10, 10);

という感じに、毎回値を文字列に変換するという作業を入れなければなりません。 そこでオーバーロードを利用し扱いやすくしてみます。





#pragma once

#include <d3dx9.h>
#include <stdio.h>
#include <string>

#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p) = NULL; } }


using namespace std;

class CDebugFont
{
    private:
        LPD3DXFONT m_pFont;
        TCHAR c[20];
        string str;

    public:
        CDebugFont(LPDIRECT3DDEVICE9 pDevice)
        {
            m_pFont = NULL;
            //文字列レンダリングの初期化
            if(FAILED(D3DXCreateFont(pDevice,
                18,                 //高さ
                9,                  //幅
                FW_REGULAR,         //普通(BOLD:太字)
                NULL,               //下線
                FALSE,              //斜体
                SHIFTJIS_CHARSET,   //文字セット
                OUT_DEFAULT_PRECIS, //固定
                PROOF_QUALITY,      //固定
                FIXED_PITCH | FF_MODERN,
                "tahoma",           //フォント
                &m_pFont)))
            {
                MessageBox(NULL, "フォントを作成できません","Error",  MB_OK);
            }
        };

        ~CDebugFont()
        {
            SAFE_RELEASE(m_pFont);
        };

    private:
        VOID Conversion(short value)
        {
            sprintf(c, "%d", value);
            str += c;
        }

        VOID Conversion(unsigned short value)
        {
            sprintf(c, "%d", value);
            str += c;
        }


        VOID Conversion(int value)
        {
            sprintf(c, "%d", value);
            str += c;
        }

        VOID Conversion(unsigned int value)
        {
            sprintf(c, "%d", value);
            str += c;
        }


        VOID Conversion(float value)
        {
            sprintf(c, "%.3lf", value);
            str += c;
        }

        VOID Conversion(double value)
        {
            sprintf(c, "%.3lf", value);
            str += c;
        }

        VOID Conversion(bool value)
        {
            if(value)
            {
                str += "true";
            }
            else
            {
                str += "false";
            }
        }
            

    public:
        template <typename TYPE>
        VOID Render(LPSTR szStr, TYPE type, int x, int y)
        {
            str += szStr;

            Conversion(type);   //文字列に置き換える

            RECT rect = {x, y, 0, 0};   //表示領域
            m_pFont->DrawText(NULL, str.c_str(), -1, &rect, DT_CALCRECT, NULL);
            m_pFont->DrawText(NULL, str.c_str(), -1, &rect, DT_LEFT | DT_BOTTOM, 0xffffffff);
            
            str = (""); //空文字でクリア
        }
};

Conversion関数は名前の通り値の変換を行い、その後文字列をつなげています。 使い方は

CDebugFont DebugFont = new CDebugFont(pDevice);
DebugFont->Render("文字列1", value1, 10, 10);
DebugFont->Render("文字列2", value2, 10, 30);
DebugFont->Render("文字列3", value3, 10, 50);
DebugFont->Render("文字列4", value4, 10, 70);

こんな感じになります。型を気にせず放り込めるので、楽に表示が出来るようになりました。
今回は数値だけですが、型を増やすなどするともっと良くなりますね。