その5 ビルボード文字列クラス
DirectX技術編その5「高速フォント文字」に関して多くの方から実装方法についてご質問を頂いておりました。日本語を扱う上でやはりフォントテクスチャは需要が高いようです。そこでここではその章の理屈を利用したビルボード文字列クラスをどどんと提供致します!
このクラスはDirectX上で動作するツールで、指定のフォントでスクリーン座標上に文字列を描画します。機能はID3DXFontインターフェイスと似ておりますが、もう少し簡略に扱えるようにして、さらに登録された文字列からフォントテクスチャを作成して描画するので効率が高くなっています。
@ 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が発生してしまうバグを修正
・文字の右下が切れる事があるバグを修正