今回は、ゲーム制作でつまずきやすい「DirectXでフォントを読み込んで文字を表示する方法」について解説していきます。
「スコアや『GAME OVER』の文字を画面に出したい」
「DirectXって、実は文字を描く機能が標準で無いの?」
「日本語を出したら全部『□(豆腐)』になった…」
こんな悩みはありませんか?
実はDirectX本体には、「文字をそのまま描く」機能はありません。DirectXがやってくれるのは三角形やテクスチャを描くことだけ。文字は「フォントを画像(テクスチャ)に変換して、その一部を貼り付ける」という形で表示します。
この記事では、Microsoft公式の補助ライブラリDirectX Tool Kit(DirectXTK)の SpriteFont を使う、いちばん実用的な方法を解説します。読み終えると、フォント表示の仕組み・準備の流れ・実装コード・日本語対応・ハマりどころが分かるようになりますので、ぜひ最後まで読んでください。
フォント表示の仕組み|文字は「画像の貼り付け」
DirectXでの文字表示は、次の2段階で考えると分かりやすいです。
- 準備(事前)… フォントの各文字を1枚のテクスチャ(文字の集合画像)に焼き込み、「どの文字がどこにあるか」の情報も作る
- 実行時… 文字列を1文字ずつ見て、対応する部分をスプライト(2D画像)として画面に貼る
つまり文字表示はテクスチャの切り貼りです。この「文字を焼き込んだ画像」をフォントアトラスと呼びます。DirectXTKは、この面倒な仕組みをまるごと肩代わりしてくれます。テクスチャの扱いは画像フォーマットの記事も参考になります。
準備|MakeSpriteFontで .spritefont を作る
DirectXTKには MakeSpriteFont というコマンドラインツールが付いています。これで、フォントを .spritefont という専用ファイル(アトラス+文字情報)に変換します。これは事前に1回やる作業です。
# インストール済みフォント名を指定して変換(英数字用)
MakeSpriteFont "Consolas" font.spritefont /FontSize:32
# TrueTypeファイルを直接指定することもできる
MakeSpriteFont "C:fontsmyfont.ttf" font.spritefont /FontSize:32できあがった font.spritefont を、プログラムから読み込みます。exeと同じフォルダに置く(出力先へコピーする)のを忘れないようにしましょう。
実装|SpriteFontとSpriteBatchで描く
実行時に使うのは SpriteFont(フォント)と SpriteBatch(2D描画)の2つです。初期化はこれだけです。
#include <SpriteBatch.h>
#include <SpriteFont.h>
using namespace DirectX;
std::unique_ptr<SpriteBatch> spriteBatch;
std::unique_ptr<SpriteFont> spriteFont;
// 初期化(device: ID3D11Device*, context: ID3D11DeviceContext*)
spriteBatch = std::make_unique<SpriteBatch>(context);
spriteFont = std::make_unique<SpriteFont>(device, L"font.spritefont");描画は、Begin と End で挙んで DrawString を呼ぶだけです。文字列はワイド文字列(L"...")で渡します(ここは文字列リテラルのLの記事とつながります)。
// 毎フレームの描画処理の中で
spriteBatch->Begin();
spriteFont->DrawString(spriteBatch.get(),
L"SCORE: 1200", // 表示する文字列(ワイド文字)
XMFLOAT2(100, 80), // 表示位置(ピクセル)
Colors::White); // 色
spriteBatch->End();たったこれだけで、画面に文字が出ます。位置・色に加えて、回転・拡大・原点なども DrawString の引数で指定できます。文字の幅を測る MeasureString を使えば、中央寄せや右寄せも簡単です。
日本語を表示する|文字の範囲を指定する
MakeSpriteFont は、指定しないと ASCII の 32(スペース)〜126(~)しかアトラスに含めません。日本語を出すには、/CharacterRegion で使いたい文字コードの範囲を指定し、日本語グリフを持つフォント(メイリオ等)を使います。/CharacterRegion は複数回くり返して指定できます。
# ASCII + ひらがな + カタカナ を含める
MakeSpriteFont "メイリオ" jp.spritefont /FontSize:32 ^
/CharacterRegion:0x20-0x7E ^
/CharacterRegion:0x3040-0x309F ^
/CharacterRegion:0x30A0-0x30FF漢字まで全部入れるとアトラスが巨大になります。実務では「ゲームで実際に使う文字だけ」をテキストファイルにまとめて指定し、サイズを抑えるのが定番です。
他の方法との違い
- DirectXTK(SpriteFont)…今回の方法。手軽でゲーム向き。初心者はまずこれ
- DirectWrite + Direct2D…にじみのない高品質なUI文字向け。準備は多いが綺麗
- ID3DXFont(D3DX9)…昔のDirectX9でよく使われたが、今は非推奨・入手困難。新規では使わない
【重要】私が日本語表示でハマった体験談
スコア表示はすぐできたのに、日本語のメッセージを出そうとしたら画面じゅうが「□□□□」(豆腐)だらけになりました。フォント名が悪いのかと、メイリオやMSゴシックに変えても直りません。
原因はMakeSpriteFontのCharacterRegion指定漏れでした。ASCIIしかアトラスに焼いていなかったので、ひらがな・漢字が「該当なし」で豆腐になっていたんです。/CharacterRegion でひらがな・カタカナの範囲を足したら、あっさり日本語が出ました。
「文字が□になる=アトラスにその文字が入っていない」と切り分けられるようになってから、フォント周りで悩まなくなりました。
DirectXフォント表示のよくある失敗例と対処法
①日本語が□(豆腐)になる
体験談のとおり、CharacterRegionに日本語の範囲を含めていないか、元フォントに日本語グリフが無いのが原因です。範囲指定と日本語対応フォントを使いましょう。なお /DefaultCharacter を指定すると、アトラスに無い文字の代わりに表示する文字を決められます。
②.spritefontが実行時に見つからない
読み込みで落ちるパターンです。.spritefont はexeと同じ出力フォルダにコピーされるよう、プロジェクトの設定(ビルド後イベントや「出力ディレクトリにコピー」)を確認します。
③テキストの後に3D描画が乱れる
SpriteBatch は2D描画用にブレンドや深度などの描画ステートを設定します。そのため、テキストを描いたあとに3Dを描くと設定が食い違うことがあります。テキストは3D描画のあと(一番最後)に描くか、描画後に必要なステートを設定し直すと安定します。
注意点
- フォント変換(MakeSpriteFont)は事前作業。実行時に毎回やるものではない
- 文字列はワイド文字(
L"..."/wchar_t)で渡す - テキストは2Dなので最後に描くとステート事故を避けやすい
まとめ
- DirectX本体に文字描画は無く、フォントを画像にして貼るのが基本
- DirectXTKのMakeSpriteFontで.spritefontを作り、SpriteFont+SpriteBatchで描く
- 日本語はCharacterRegionで範囲指定+日本語フォントが必須
- ハマりどころは豆腐・ファイルのコピー漏れ・描画ステート
文字が出せると、スコアやメニュー、セリフなど一気にゲームらしくなります。まずは英数字のスコア表示から始めて、次に日本語へ広げてみてください。


