ホーム < ゲームつくろー! < ツール編

その5 ビルボード文字列クラス


 DirectX技術編その5「高速フォント文字」に関して多くの方から実装方法についてご質問を頂いておりました。日本語を扱う上でやはりフォントテクスチャは需要が高いようです。そこでここではその章の理屈を利用したビルボード文字列クラスをどどんと提供致します!

 このクラスはDirectX上で動作するツールで、指定のフォントでスクリーン座標上に文字列を描画します。機能はID3DXFontインターフェイスと似ておりますが、もう少し簡略に扱えるようにして、さらに登録された文字列からフォントテクスチャを作成して描画するので効率が高くなっています。

ツール名 ビルボード文字列クラス
名前空間 Dix
クラス名 BillboardString
公開メソッド BillboardString( IDirect3DDevice9 *dev )
dev : 描画デバイス
コンストラクタ
Draw() フォント文字列を描画する。必ずIDirect3DDevice9::BeginSceneメソッドの呼出し後に実行する必要がある。フォントテクスチャの変更が必要な場合は描画前に再構築される。変更が無い場合は再構築されず板ポリゴンの描画のみとなるため高速描画となる。
RegistString( const TCHAR *str )
str   : 文字列
表示させる文字列を登録する。既に登録されている文字列は破棄され新しいフォントテクスチャが作成される。同じ文字列を登録した場合は変更されないため作成にかかるパフォーマンスの低下は生じない。
SetAlpha( int alpha )
alpha : 透過度(0〜255)
フォント文字列の透過度を指定。0以下及び0以上を指定した場合は飽和される。
この値を変更してもフォントテクスチャは再構築されないのでパフォーマンスに影響しない。
SetColor( DWORD color)
color : フォントカラー
フォントの色を32bit(XRGB)で指定する。
この値を変更してもフォントテクスチャは再構築されないのでパフォーマンスに影響しない。
SetFont( const TCHAR FaceName )
FaceName : フォント名
フォント名を指定する。フォント名はWordからコピペすると便利。
フォント名が変更されるとフォントテクスチャが再構築される。同じフォント名が指定された場合は再構築されないのでパフォーマンスに影響しない。
SetMaxPixelSize( unsigned int size)
size : フォントの大きさ
フォントの大きさを指定する。これはフォントを囲むボックスの最大幅であるため、フォントの実際の大きさはこれより小さくなることに注意。
設定値が既にある値と異なる場合はフォントテクスチャが再構築される。同じ値の場合は再構築されないのでパフォーマンスに影響しない。
SetPosition( float x, float y )
x : スクリーンX座標
y : スクリーンY座標
スクリーン上での表示位置を指定する。制御点は文字列の左上となる。
この変更はパフォーマンスに影響しない。
SetScale( float xs, float ys )
xs : X方向のスケール
ys : Y方向のスケール
フォントを貼り付ける板ポリゴンのスケールを変更する。これは貼り付けられているフォントテクスチャを引き伸ばす。
この変更はフォントテクスチャを再構築しないのでパフォーマンスに影響しない。
バージョン v1.01 (2008. 11. 16)
ファイル BillboardString.h, BillboardString.cpp
BillboardChar.h, BillboardChar.cpp



@ BillboardStringクラスの使い方

 このクラスを使用するためにはコンストラクタでIDirect3DDevice9インターフェイスを渡す必要があります。表示したい文字はRegistStringメソッドで登録します:

BillboardString BS( pDev );
BS.RegistString( _T("○×つくろ〜ドットコム。") );

 文字列は_Tマクロをご使用下さい。このクラスはUnicode文字セットにも対応しています。

 デフォルトでは32ピクセルサイズ、白色、透過度255、MSゴシックが設定されています。このまま描画すると(0, 0)の位置にフォント文字列が描画されます。この時必ずIDirect3DDevice9::BeginSceneメソッドの後にメソッドを呼び出さなければなりません

pDev->BeginScene();
BS.Draw();
pDev->EndScene();

 デバッグバージョンの場合、このクラスは背景がちょっと白いフォントテクスチャを描画します。これは位置関係を把握しやすくするためです。リリースバージョンでは消えます。

 ゲームループでDrawメソッドを呼び続けても、内部の変更がなければ作成した板ポリゴンを表示し続けるだけなので高速に描画されます。



A 内部変更が起こる状態

 「内部変更」とはここでは内部でフォントテクスチャが再構築される事を指します。フォントテクスチャ作成作業は実行時に行われるため負荷がかかります(大抵一瞬で終わりますが)。よって、毎フレーム内部変更が起こるような使い方は避けるべきです。

 内部変更はテクスチャの再構築が必要となる次のパラメータを変更すると起こります:

 ・ RegistStringメソッド
 ・ SetFontメソッド
 ・ SetMaxPixcelSizeメソッド

ただし、内部で保存されている値と同じ値を設定した場合は内部変更が起こりません。また透過度(アルファ値)、位置及びスケールの変更は内部でテクスチャを変更しないためその値を変えても内部変更は起こりません。

 以下のように同じ文字列を描画し続けてもパフォーマンスに問題はありません:

BillboardString BS( pDev );
while(1)
{
   // ゲームループ
   BS.RegistString( _T("本日のハイスコア") );
   pDev->BeginScene();
   BS.Draw();
   pDev->EndScene();
}

また、文字列を後ろに追加していった場合も追加分だけが新規作成され、蓄積分はキャッシュされてそのまま使われます:

BS.RegistString( _T("本") );
BS.RegistString( _T("本日") );
BS.RegistString( _T("本日の") );
BS.RegistString( _T("本日のハ") );
BS.RegistString( _T("本日のハイ") );
BS.RegistString( _T("本日のハイス") );
BS.RegistString( _T("本日のハイスコ") );
BS.RegistString( _T("本日のハイスコア") );

上の場合、後ろに付け足した文字のみが新規作成されます。一般にこの時間は極わずかです。ただし、フォントを変更するなどした場合は再構築が起こります。



B フォントなど

 フォントはいわゆる「フォント名」で指定します。これは正確に指定する必要があります。私は面倒なのでWordのフォント指定欄からコピペしてしまうのですが、ちゃんと取得したい方はEnumFontFamiliesEx関数で列挙して下さい。

 以下に色々なパラメータを設定をした例を示します:

BillboardString L1( g_pD3DDev );
BillboardString L2( g_pD3DDev );
BillboardString L3( g_pD3DDev );

L1.SetMaxPixelSize( 32 );
L2.SetMaxPixelSize( 50 );
L3.SetMaxPixelSize( 55 );

L1.SetFont( _T("MS ゴシック") );
L2.SetFont( _T("MS P明朝") );
L3.SetFont( _T("HG創英角ポップ体") );

L1.SetPosition( 17, 32 );
L2.SetPosition( 37, 70 );
L3.SetPosition( 43, 125 );

L1.SetColor( 0x0000ffff );
L2.SetColor( 0x00ff0000 );
L3.SetColor( 0x00ffffff );

L1.SetAlpha( 80 );
L2.SetAlpha( 128 );
L3.SetAlpha( 255 );

L1.SetScale( 1.0f, 1.0f );
L2.SetScale( 1.0f, 1.0f );
L3.SetScale( 1.0f, 1.0f );

L1.RegistString( _T("オムレツがうまくできた・・・") );
L2.RegistString( _T("オムレツがうまくできた。") );
L3.RegistString( _T("オムレツがうまく出来た〜!!") );

いや、オムレツがうまくいったんですよ、はい(^-^;;。



C SetMaxPixelSizeメソッドとSetScaleの関係

 SetMaxPixelSizeメソッドは作成するフォントの大きさを設定します。この値が大きければ大きいほど大きなフォントが作成されます。基本的にはドットバイドットフォントになるはずです。しかし、その分大きなテクスチャが確保されるため作成負荷と描画負荷、メモリ使用量が増大します。SetScaleメソッドは板ポリゴンのサイズを変更するメソッドです。テクスチャの大きさはSetMaxPixelSizeメソッドで決めた大きさであるため、スケールを大きくすると描画が粗くなります:


これは縮小してますが、3倍スケールはもう厳しいっす



D BillboardCharクラス

 BillboardStringクラスは実は単なるマネージャです。内部では1文字のテクスチャフォントを管理するBilboardCharクラスのインスタンスを登録された文字分だけ持っています。1文字単位でフォントテクスチャを扱いたい場合はこのクラスを使用してください。メソッドはBillboardStringクラスとだいたい一緒ですが、こちらは回転もサポートしています。

 またBilboardChar::GetFontTextureメソッドで作成したフォントテクスチャを取得できます。取得時には参照カウンタが増加しますのでご注意下さい。



E バージョン情報

2007/ 10/ 31 v1.00
・ 基本描画サポート

2008/ 11/ 16 v1.00 -> v1.01
・空文字を登録するとメモリリークが発生するバグを修正
・Unicode文字セットの場合に同じ文字登録でもUpdateが発生してしまうバグを修正
・文字の右下が切れる事があるバグを修正