C++
初心者
C言語
DXライブラリ
ゲーム開発

最低限これだけ知ってればゲームが作れるDXライブラリ関数集

 ゲーム制作といえば最近Unityという話が多いですが、コマンドラインのプログラムしか書いたことのないタイプの初心者があれにいきなり触れるのはなかなか難しいものがありますし、何より動かないコンピューターでは動きません。開発機も開発したアプリも。なぜならば3Dなので。2Dモードにしたって無理なものは無理です。
 ということで、最近スマートフォン出力にも対応した昔ながらのDXライブラリで初めてのゲームを作っていこうという方もまだまだいると思うのですが、その時に必要になる関数をまとめてみました。DXライブラリ公式サイトのゲームプログラム講座に載ってるもの+αという感じです。
 公式サイトに載ってるやつとはとは別の一から書いたサンプルコードも載せたので合わせて参考にしたりコピペしたりしてみてください。
 想定読者はC言語(やC++)をコマンドラインではある程度書けるようになってこれからゲームプログラムを始めてみようという段階の人です。すでにDXライブラリ使ったことあるよという人には真新しい話はあんまりないので適宜回れ右をどうぞ。

※後半未完成です。ご了承ください。

DXライブラリとは

 ということで関数集の前に。
 まず前提として、皆さんのお持ちのPCはWindowsですね? なので、WindowsのPCで動くゲームをを作りたいということになります。作ったゲームはフリーゲームが集まるサイトに上げるなり、Google Driveで直接公開するなりいろいろな方法があります。しかし、ゲームっぽいゲームを作るにはコマンドライン(コマンドプロンプトとかPowerShellとかのことです)で動くプログラムではなくちゃんとウィンドウが出てくるプログラムにしないといけない。そんなものの出し方は知らない。困る。そこで登場するのがDXライブラリです。
 DXライブラリとは、C/C++でWindows向けのゲーム製作用ライブラリです。公式サイトの概要によると

 DXライブラリ Windows版は、DirectXを使ったWindowsデスクトップアプリの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。(使用する際はC言語の知識だけで大丈夫です)
 これによってプログラマーはゲームの本質的なプログラムに専念することが出来ます。かなり本格的なソフト制作からお遊び程度のミニゲーム制作まで幅広くカバーしています!
DXライブラリ置き場

とのこと。ちなみに今気づいたのですがDXライブラリのDXは正しくは全角ですね。でもQiitaのタグが半角でできているので検索の都合上ここでは半角で表記させていただきます。
 さて、ということで、DXライブラリとはコマンドライン(繰り返しになりますがコマンドプロンプトとかPowerShellとかのことです)ではなく普通のウィンドウを制御する点で面倒なところをまるっと解決してくれるライブラリです。普通のウィンドウを作るのはもちろんのこと、コマンドラインのプログラムでは画面に文字列を表示するだけだったのが、DXライブラリに与えられた関数を使えば画像を表示したり音を鳴らしたりといったことができるようになります。そして、それに伴ってあとはゲームのルールとかを記述していけばWindows向けのゲームが完成。話が早いですね。そういう素敵なライブラリです。
 ですが。
 DXライブラリには実に様々な関数があります。それはもちろん様々なことができるということを意味しているのですが、初心者がいきなり関数リファレンスページとかを読むと「?(´,,•﹏•,,`)??」となってしまいます。ということで、以下にとりあえず最初のゲームを作ろうと思ったらこれだけ知ってれば大丈夫だと思うよ、という関数をまとめました1。大きく「制御系」「画像系」「音声系」「入力系」の四区分に分けてあります。いくつかサンプルコードも載せてみました2のでそちらも合わせてご利用ください。コピペ利用OKです。

補足1:ライブラリの使い方

 ライブラリの使い方については公式で詳しく書いてあるので解説していませんが、コンパイラはVisual Studio、bcc、g++に対応しています。Visual Studioは初期設定が妙に面倒なので初心者の方はフォルダに突っ込んで#include "Dxlib.h"するだけのbccをBCC Developerと一緒に使うのがおすすめです3。Visual Studioも入力補完とかがあって初期設定さえ突破できれば便利なんですけどね。

補足2:返り値について

 以下いろいろな関数例が出てきますが、特筆されていない場合は

状態
成功 0
失敗 -1

という返り値が帰ってきます。
 いいですか、成功が0で失敗が-1です。言い方を変えましょう。成功がfalseで失敗がtrueです。わかりますね。C/C++では0がfalseで0以外の値がtrueなのでそういうことになります。この辺trueとfalseで雑にif文を書くと大変なことになるのでくれぐれも気を付けて下さい。

制御系

DxLib_Init

int DxLib_Init(void);

 DXライブラリを使ったWinMain関数(main関数みたいなものです。サンプルコードのコメント参照)の上の方で呼び出す関数です。DXライブラリを使用するためのセットアップを自動でやってくれます。
 この関数を書かずに動かしてみるとわかるのですが、だいたいWindowsのウィンドウを作ってくれる関数だと思っておいてください。まあ、初期設定を何もせずにこれを呼び出すとウィンドウではなくフルスクリーンが出るのですが。「フルスクリーンじゃなくて普通のウィンドウが良い!」みたいな初期設定をやる関数をこの関数の上に書いておくとそういう設定でウィンドウが作られます。詳しい関数名はすぐ出てくるのでもう少しお待ちください。
 あと、実行してるコンピューターが事故るとDxLib_Initが失敗することがあります。その時はあきらめてプログラムを即時終了してあげましょう。WinMain関数で呼び出してるならreturn -1;、それ以外ならexit(-1);です。

DxLib_End

int DxLib_End(void);

DxLib_Initが開始時に呼び出す処理なのに対し、DxLib_Endは終了時に呼び出す処理です。こちらは事後処理とかはないのでWinMain関数の一番下、return 0;の直前に書いてください。これは書かないで実行してみても見た目は違いが全くわからないのですが、Windowsが気持ちよくプログラムを終了できるようにいろいろな便宜を図っていると思ってください。書かないとWindowsが怒って青い画面を出してくるかもしれません。最近Windowsも丸くなったのでそんなことそうそうないですけどね。

ProcessMessage

int ProcessMessage(void);

 こちらもWindowsのご機嫌取り関数ですが、開始と終了で一度だけ呼び出せば良い上二つの関数とは違い、ProcessMessageは1秒間に60回の頻度で呼び出してあげないといけません。これだけ聞くと「そんな殺生な……」と思うのですが、ゲームというのはアニメと同じですべからくパラパラ漫画の要領で動いていて、普通は1秒に60枚の画面が切り替わるようにできています。その辺はwhile文のループとかで実装していくことになるのですが、そのループで一回は呼び出してくださいね、ということです。ちなみにこのwhile文のループ1回を「1フレーム」と言ったりします。専門用語なのでとりあえず覚えておきましょう。
 話がそれましたが、パラパラ漫画をめくるみたいな関数もwhile文1ループにつき1回、すなわち1フレームに1回呼び出さないといけないので(あたりまえ)、その手の処理の近くに書いておけば忘れることもないでしょう。

ChangeWindowMode

int ChangeWindowMode(int Flag);
変数名 内容
Flag true:ウィンドウモード
false:フルスクリーンモード

 DxLib_Initのところで予告したDXライブラリの初期設定関数の一つがこちら。初期設定関数なのでDxLib_Initよりも前で呼び出します。
 DXライブラリが作るウィンドウは何もしないとフルスクリーンモードで起動するのですが、この関数を引数をtrueにして先に呼び出しておくとウィンドウモードで起動されるようになります。
 実はこの関数、DxLib_Initよりも後で呼び出すこともでき、その場合フルスクリーンモードの時にChangeWindowMode(true);とやるとその場でウィンドウモードに、ウィンドウモードの時にChangeWindowMode(false);とやるとその場でフルスクリーンモードになるのですが、なにぶん初期化を含む処理なのですべての設定が飛びます。読み込んだ画像とか音声とか(画像や音声を読み込むとはどういうことなのかは後で説明します)。とにかく、そういう初期設定がこの関数を呼ぶとその場で全部やり直しになり、ちゃんとやり直せれば問題ないのですがその辺をしっかり管理をしておかないとバグの温床となるため、ChangeWindowModeを呼び出すのは起動時のみにしておくのが無難です。設定画面とかでウィンドウモードとフルスクリーンモードが切り替わったりした場合は、次回起動時から反映されますという仕様にしておきましょう。

WaitTimer

int WaitTimer(int WaitTime);
変数名 内容
WaitTime 停止したい秒数×1000

 引数にミリ秒、すなわち0.001秒の単位で時間を指定し、処理を停止させる関数です。
 実際のゲームプログラムでは1フレーム(while文1ループ)を1/60秒に抑えるときぐらいにしか使いません。どちらかというとこれが重宝するのはテストプログラムで、最初のwhileループとかに至る前の学習段階では、この関数で画面を止めて実行結果を見るなどしながら関数の挙動を確認していきます。公式関数リファレンスのサンプルプログラムでもそこそこ使われています。
 ちなみに、Windowsが用意している関数でSleepという表面的には全く同じ挙動をするSleepという関数があるのですが(#include <windows.h>で使えるようになります)、SleepとWaitTimerの大きな違いは、プログラムが止まっている間に裏でどういう挙動をしているかです。具体的に言えば、WaitTimer関数はプログラムが止まっていても例のご機嫌取りのProcessMessage関数が定期的に呼び出されているのですが、Sleep関数にはそれがありません。WindowsのC言語に用意されている汎用関数なのであたりまえではあるのですが、それゆえにDXライブラリを使ったプログラムで処理を止めたいときにSleepを呼び出すとWindowsが怒って変なことが起こります。ということで、Sleep関数の存在を知っている方も、文字数が多いからと言って忌避してないでちゃんとWaitTimer関数を使ってあげてください。

【サンプルプログラム1】

 今までの起動・終了・ウィンドウ制御・停止の関数を踏まえて、黒いウィンドウが出てきてちょっとしたら消えるだけのプログラムを作ってみます。

sample01.cpp
#include "DxLib.h"

// Windowsプログラムでは、main関数の代わりにWinMain関数を使います。
// 引数がやたら長いですが特に意味は理解する必要がないので適宜コピペしてください。
// このサンプルプログラムも公式サイトのサンプルプログラムのWinMain関数をコピペして作っています。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードに設定
    ChangeWindowMode(true);

    //DXライブラリを初期しウィンドウを作る
    int init_check = DxLib_Init();          //trueかfalseではなく0か-1が返ってくるのでbool型にしないように

    //初期化に失敗していた場合は-1が返ってきているのでその場合は強制終了
    if(init_check == -1)return -1;          //ちなみにif文は処理が一つしかないときはこんな感じで一行で書けます

    //この辺で小さいウィンドウが出ます

    //5秒停止
    WaitTimer(5000);                        //ProcessMessage関数はこの裏側で1秒に60回ずつ呼び出されている

    //DXライブラリを終了
    DxLib_End();

    //Windowは理論上ここで消えます

    return 0;
}

 冒頭に#include "DxLib.h"がありますが、もちろんのこと公式サイトに書いてある各コンパイラごとのライブラリ使用初期設定をしておかないとコンパイルエラーになって何もできないのでその辺は注意しておいてください。以下に出てくるサンプルプログラムもすべて同様ですよ。

SetGraphMode

int SetGraphMode(int SizeX , int SizeY, int ColorBitNum);
変数名 内容
SizeX ウィンドウの横幅
SizeY ウィンドウの縦幅
ColorBitNum 使いたい色のビット数(16 or 32)
返り値 DX_CHANGESCREEN_OK:成功
DX_CHANGESCREEN_RETURN:失敗(この関数を実行する直前の状態まで巻き戻し)
DX_CHANGESCREEN_DEFAULT:失敗(DXライブラリの初期設定まで巻き戻し)

 画面モードを変更する関数です。ChangeWindowModeはウィンドウモードかフルスクリーンモードかの切り替えですが、こちらはウィンドウモードにおいて何×何のサイズでやっていくかという切り替えです。初期設定では640×480の4:3画面になっていますが、「そんなのは小さすぎる!」とか「16:9がいい!」みたいな人はこの関数で設定変更できます。
 そのほか、使いたい色のビット数を16か32で指定できますが、16ビットは256色のことで画面が本当にむちゃくちゃなことになるのでおとなしく32と書きましょう。白と黒の二色しか使わないゲームとかなら別に16でもいいですけど。
 この関数もChangeWindowModeと同じでDxLib_Initまえに呼んでおいて初期設定をするという使われ方が主です。ChangeWindowModeと違いこれを読んでも読み込んだデータなどは飛んだりはしないのですが、増えたサイズ分は拡大されるということもなく単に黒い画面が出てしまうだけなのでやはり実行中に呼び出すメリットはあんまりありません。画像の座標とかサイズとかを全部変数で管理して逐一補正するとかなら……いや、やめておいた方がいいですね。ここでは紹介しませんがウィンドウの端をマウスでつまんで拡大縮小できるようにする関数とかもあるのでウィンドウサイズの拡大縮小がやりたい場合はそっちを使ってください。

SetMainWindowText

int SetMainWindowText(char *WindowText);
変数名 内容
WindowText ウィンドウの名前として設定したい文字列

 こちらもDxLib_Init前の呼び出し推奨関数。ウィンドウモードの時にウィンドウの上に表示される「ウィンドウ名」を設定できます。これを書かないとウィンドウ名はDxLibなんとかかんとかみたいな味気ない感じになってしまったはずです。せっかくなので設定しておきましょう。
 ちなみにこの関数もDxLib_Init後にかけ、しかも今まで紹介した関数よりも割と気軽に呼び出せます。呼び出すとその場でウィンドウ名が変わるだけで、悪い影響とかは発生しません。ゲームの流れで敵キャラクターが世界を侵食しているみたいなときにウィンドウ名をバグらせたい! みたいになったときはこの関数のことを思い出してあげてください。

【サンプルプログラム2】

 ウィンドウとフルスクリーンで遊びます。画像読み込みとかをやっていないので気軽にウィンドウモードとフルスクリーンモードを行ったり来たりします。びっくり系マルウェア(いわゆるコンピューターウイルス)に分類されかねないので変な方法で配布とかしないように。

sample02.cpp
#include "DxLib.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードの初期設定
    ChangeWindowMode(true);                 //ウィンドウモード
    SetMainWindowText(" ");                 //ウィンドウ名は半角スペース

    //DXライブラリを初期しウィンドウを作る
    if(DxLib_Init() == -1)return -1;        //if文の中で関数を呼び出すと行数が節約できる(公式サイトのサンプルもこのパターン)

    //3秒停止
    WaitTimer(3000);                        //ProcessMessage関数はこの裏側で1秒に60回ずつ呼び出されている

    //少しずつウィンドウ名を書いていき「お前を見ているぞ」にする
    SetMainWindowText("お"); 
    WaitTimer(1000);
    SetMainWindowText("お前"); 
    WaitTimer(1000);
    SetMainWindowText("お前を"); 
    WaitTimer(1000);
    SetMainWindowText("お前を見"); 
    WaitTimer(1000);
    SetMainWindowText("お前を見て"); 
    WaitTimer(1000);
    SetMainWindowText("お前を見てい"); 
    WaitTimer(1000);
    SetMainWindowText("お前を見ている"); 
    WaitTimer(1000);
    SetMainWindowText("お前を見ているぞ"); 
    WaitTimer(5000);

    //フルスクリーンモード
    ChangeWindowMode(false);
    WaitTimer(2000);

    //ウィンドウモード
    ChangeWindowMode(true);
    WaitTimer(2000);

    //ウィンドウサイズを少しずつ大きくしていく
    SetGraphMode( 800,  600, 32);  WaitTimer(1000);
    SetGraphMode(1024,  768, 32);  WaitTimer(1000);
    SetGraphMode(1280,  720, 32);  WaitTimer(1000);
    SetGraphMode(1280, 1024, 32);  WaitTimer(1000);
    SetGraphMode(1920, 1080, 32);  WaitTimer(1000);
    WaitTimer(2000);

    //再びフルスクリーンモード
    ChangeWindowMode(false);
    WaitTimer(5000);

    //おわり
    DxLib_End();
    return 0;
}

画像系

LoadGraph

int LoadGraph(char *FileName);
変数名 内容
FileName 読み込む画像の名前(正確にはパス)
返り値 -1:失敗
-1以外:グラフィックハンドル

 ゲームで画像を表示するには、いったんフォルダの中に入っている画像をプログラムの方に読み込む必要があります。ゲームをやってるとよく出てくる「Now Loading...」というやつです。そのLoadingをやるのがこのLoadGraph関数です。
 使い方は簡単で、引数に読み込みたい画像の名前を書けばそれが読み込まれます。ただし拡張子(.pngとか)までちゃんと書くこと。公式サイトによると

尚、読み込むことの出来る画像形式は BMP,JPEG,PNG,DDS,ARGB,TGA の6種類です。

とのことですが、BMPは読み込んだときに重くなるのでなるべくPNGかJPEGにしましょう。特に理由がなければPNGにしましょう。
 そして、返り値が返ってきますが、この帰ってきた返り値が「グラフィックハンドル」と呼ばれ、画像表示に必要になります。C言語でファイル入出力とかをやったことのある方はわかるかと思いますが、FILE型のファイルポインタみたいなものです。あれはFILE型ポインタですが、こちらは普通にint型の値としてかえってきます。いずれにせよ、数値自体には意味はありませんがちゃんと保存しておかないと動かなくなるので加減乗除とかはやらないように。グラフィックハンドルの使い方は次のDrawGraph関数をご覧ください。

DrawGraph

int DrawGraph(int x, int y, int GrHandle, int TransFlag);
変数名 内容
x, y 表示したい画像の左上の点を置きたい座標
GrHandle グラフィックハンドル
TransFlag true:透明度を有効
false:透明度を無効

 読み込んだ画像を左上の点を指定する形で表示します。例えばウィンドウサイズが640×480で、全画面表示したい640×480の画像があった場合、int gh = LoadGraph("画像.png"); DrawGraph(0,0,gh,true);みたいにやります。この例からもわかるように、グラフィックハンドルというのはLoadGraphで帰ってきた引数の値のことです。画像を1枚読み込むごとにグラフィックハンドルが1つ返ってくるので、それぞれの値を変数に保存しておいて、DrawGraphのような描画系関数で引数に渡すことでそれが画面に表示される、というのがDXライブラリの流儀です。
 最後に、透明度を有効にするかどうかの引数がありますが、よくわからなければこれは常にtrueにしておいてください。画像がPNG形式(拡張子が.png)である限りとりあえずtrueにしておけば見た通りのまま表示されてくれますし、それで困るということもそうそうありません。

【サンプルプログラム3】

 画像を読み込んで、表示します。読み込む画像「画像.png」はBCC Developerを使っているならDebugフォルダの中に、Visual Studioを使っているならソースコードがあるフォルダの中にそのまま入れておいてください。ちなみにBCC DeveloperのDebugフォルダは一度コンパイルしないと発生しないのでコンパイルをやってフォルダが作られてからその中に画像を入れる、という感じでお願いします。
 「画像.png」は画面に表示したい好きな画像ファイルをその名前に書き換えて使ってもらえれば中身はなんでも良いのですが、一応サイズは640×480以下が望ましいです。適宜ペイントなどのソフトで雑な画像を生成するか、インターネットで拾ってきて大きかったらペイントで縮小するなどしてください。拾ってきた画像の拡張子が.jpgだった場合でもソースコードのLoadGraphを書き換えれば大丈夫です。

sample03.cpp
#include "DxLib.h"
#include <stdlib.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモード
    ChangeWindowMode(true);

    //DXライブラリを初期
    if(DxLib_Init() == -1)return -1;

    //画像を読み込む(※ghは graphic handle の略)
    int gh = LoadGraph("画像.png");       //画像の拡張子が.jpgなら「int gh = LoadGraph("画像.png");」とすればよい

    //雑な位置に画像を20枚表示する
    for(int i=0; i<20; ++i){
        int x = rand() % 640;
        int y = rand() % 480;
        DrawGraph(x, y, gh, true);

        //1枚表示するごとに1秒待つ
        WaitTimer(1000);
    }

    //鑑賞用に5秒待つ
    WaitTimer(5000);

    //おわり
    DxLib_End();
    return 0;
}

ClearDrawScreen

int ClearDrawScreen(void);

 さて、DrawGraphで普通に画像を出すことはできるようになりましたが、ゲームを作るにはパラパラ漫画の要領で出てきた画像を少しずつ右に動かすとか、画像がいっぱいあるなら1秒間に60回の割合で新しい画像をどんどん出していくとか、そういうことが必要になります。全画面に新しい画像を出すとかならまあいいのですが、画像を少しずつ動かすとなった場合は、画面上に出ている画像をいったん全削除する必要があります。それを実現するのがClearDrawScreen関数です。
 使い方はそのまま、引数とかもなく単に呼び出すだけで画面上の描画された画像などをきれいさっぱり排除して元の真っ黒な画面に戻してくれます。そのうえで、座標を変えたりして新しい画像を……とやればアニメーションができます。
 ただ、これには少し問題があって、いったん画像をすべて消して真っ黒にしてしまうため、目力のある人間にはアニメーションのコマとコマの間に黒い画面がちらちらと挟まっているのがばれてしまいます。その辺を解決するのが次に出てくるSetDrawScreen関数とScreenFlip関数、ということになります。

SetDrawScreen

int SetDrawScreen(int DrawScreen);
変数名 内容
DrawScreen DX_SCREEN_FRONT:これ以降は表画面に描画
DX_SCREEN_BACK:これ以降は裏画面に描画

 ClearDrawScreenで画像を消すと真っ黒い画面が挟まってしまうという問題、この解決策としてDXライブラリが用意しているのが「裏画面」というシステムです。
 そもそも、1秒に60枚絵のあるアニメーションというのは、最終的に用意する絵は当然1秒につき60枚のはずです。その過程でまず真っ黒い画面を用意して、その上に背景を描画して、ある座標にキャラクターを描写して……とかやっているこの「中間工程」はゲームをプレイする側は別にみる必要はありません。その見る必要のない工程を直接画面の中でやってしまっているから問題が発生するのであって、であれば「見せたい1枚の絵」になるまではちょっと別の隠れたところで作業をして、完成してから初めてプレイヤーが見られるウィンドウの方に表示する、とすれば良いのです。この「中間工程の作業するためのちょっと隠れた場所」というのがDXライブラリが言う「裏画面」です。
 前置きが長くなりましたが、SetDrawScreen関数は描画先を表画面にするか裏画面にするかを変更する関数です。引数にDX_SCREEN_FRONTを指定して呼び出せば以降描画先は表画面に、DX_SCREEN_BACKを指定して呼び出せば以降裏画面に描画されるようになります。ゲームを作るのであれば、まず裏画面にいろいろ描画してそれを表画面に反映する、というのが基本の流れとなるので、プログラム起動直後にSetDrawScreen(DX_SCREEN_BACK);とやってさっさと描画先を裏画面に指定する必要があります。この関数はDxLib_Initの前には書けないので、DxLib_Initの直後あたりですぐ呼び出しておくとよいでしょう。

ScreenFlip

int ScreenFlip(void);

 SetDrawScreenで裏画面に描画先を設定したとして、どうやって「完成した絵」を表画面に持ってくるのか。その答えがScreenFlip関数です。ClearDrawScreenから始まったすべての描画が終わり、絵が完成したと思ったらScreenFlip関数を呼び出してください。そうすると裏画面の内容が表画面に反映されます。その後、while文のループが次に進み、また裏画面でClearDrawScreenで真っ黒になった画面から「絵作り」が始まる、ということになります。この辺りは次に出てくるサンプルプログラムを動かすと実感が湧いてくるかと思います。

DrawRotaGraph

int DrawRotaGraph(int x, int y, double ExtRate, double Angle, int GrHandle, int TransFlag, int TurnFlag);

CreateFontToHandle

int CreateFontToHandle(char *FontName, int Size, int Thick);
変数名 内容
FontName 使いたいフォントの名前
Size 文字サイズ(ほぼドット数)
-1でデフォルト設定
Thick 0~9の10段階での文字の太さ
-1でデフォルト設定
FontType フォントのタイプ
-1でデフォルト設定
返り値 -1:失敗
-1以外:フォントハンドル

 コマンドプロンプトなどのコマンドラインのプログラムではprinfで簡単に文字が画面に出せましたが、DXライブラリのプログラムでは画像が出せるようになった代償としてちゃんとした文字を表示するには最初にフォントを登録しておくことが必要となりました。そのフォントの作成を行うのがCreateFontToHandle関数です。
 フォントの作成といっても難しいものではなく、要するに初心者的には文字の大きさを設定する程度の意味です。ゲーム内には様々な大きさの文字がすると思いますが、それらは一つずつフォントという形で管理され、文章一つにつき一つのフォントを指定して画面に文章を表示します。
 第一引数のFontNameは文字通りフォントの名前です。フォントといっても大量にありますが、特にこだわりがなければ「メイリオ」「MS ゴシック」あたりを書いておけば見慣れたフォントが出てきます。こだわりがある人は好きなフォント名をここに文字列で書いておけばそれが表示されます。ただし、ゲームプレイヤーのPCに入っていないフォントを指定してしまうとうまく動かないのであまりマイナーなフォント名を書くのはやめておきましょう。
 第二引数のSize、第三引数のThickはそれぞれ文字の大きさと太さです。文字の大きさはまあ自分で決めたいとは思いますが、「太さ……太さ?」みたいになる方も多いかと思います。その場合は、-1を書いておくとデフォルトの妥当な太さに自動で設定してもらえるので、迷ったら-1と書いておきましょう。ちなみにSizeの方も-1でデフォルトのサイズになります。
 第四引数のFontTypeも特にこだわりがなければ-1と書いておいてください。ここにいろいろ書くことでフォントが綺麗になるのですが、-1だからと言って別に汚いというわけでもなく(頑張って観察すると角がギザギザになってるのがわかるという程度です)、文字なんて読めればなんだっていいみたいな場合は-1で十分です。公式サイトの引数一覧の説明がわかる程度にこの辺りに詳しい人は設定してみてください。
 作成されたフォントの情報はフォントハンドルとして返り値でわたされます。LoadGraph関数でグラフィックハンドルが返ってきてそれを変数に保存していて表示したいときに受け渡したのと同じように、CreateFontToHandle関数では作成したフォントのフォントハンドルが返り値として返ってきて、それを変数に保存しておいて文字列を描画する関数を呼び出すときに渡して使用します。フォントの実際の使い方に関しては次のDrawFormatStringToHandle関数をご覧ください。

GetColor

unsigned int GetColor(int Red, int Green, int Blue);

DrawFormatStringToHandle

int DrawFormatStringToHandle(int x, int y, unsigned int Color, int FontHandle, char *FormatString, ...);

SetDrawBlendMode

int SetDrawBlendMode(int BlendMode , int Pal);

LoadSoundMem

int LoadSoundMem(char *FileName);
変数名 内容
FileName 読み込む画像の名前(正確にはパス)
返り値 -1:失敗
-1以外:グラフィックハンドル

 画像と同様に、ゲームで音を鳴らすにはいったんフォルダの中に入っている音声ファイルをプログラムの方に読み込む必要があります。LoadGraphの音声版ですね。
 LoadGraphと同じように、こちらも使いたい音声の名前を引数に書けば読み込まれます。画像ファイルと同様に音声ファイルにも種類がありますが、この関数で読み込める音声は

音ファイル形式は WAV, MP3, Ogg, Opus

とのことです。ゲームを作る際はフリー素材の音声などを利用することになると思いますが、効果音素材でよく使用されている形式がWAV、BGMにつかえる曲素材で良く使用されている形式がMP3です。つまり、普通のフリー素材配布サイトからとってきた音声であればそのまま読み込み可能です。ただし、一部の曲素材は「midi」という形式で配布されていますが、こちらはLoadSoundMem関数では読み込めないので注意してください。PlayMusic関数で読み込まずに直に鳴らすことはできます。

PlaySoundMem

int PlaySoundMem(int SoundHandle, int PlayType, int TopPositionFlag);

StopSoundMem

int StopSoundMem(int SoundHandle);

ChangeVolumeSoundMem

int ChangeVolumeSoundMem(int VolumePal, int SoundHandle);

入力系

GetHitKeyStateAll

int GetHitKeyStateAll(char *KeyStateBuf);
変数名 内容
KeyStateBuf キーボードの入力状態を格納する256要素char型配列のポインタ

 キーボードのすべてのキーに対してどのキーが押されているのかを確認する関数です。一つ一つのキーが押されているのか押されていないのかを確認する関数もあるのですが、入力取得は処理が重く大量に実行すると処理落ちしてしまうため、一度だけすべてのキーの入力状態を取得してそれを配列に格納しておき、使いたいときはそれを参照するというスタイルで入力の確認を行うのが一般的です。
 キーボードのキーは大量にあり、そのすべての情報を関数実行時に返す必要があるのですが、C言語の返り値は値一つ分しか返せないため、代わりに引数に結果を入れたい変数のポインタを渡しておいてそこに入れてもらうというC言語ではよくあるパターンの情報受け渡し方式が採用されています。身近な例としてはscanf関数の格納先変数の指定とかと同じ原理ですね。
 結果は256要素の配列に格納されていますが、目的のキーの入力状態を見たい場合に何番の要素にアクセスすればいいかというと、ここの解説のところに載っているdefineの値の要素にアクセスすればわかります。1になっていれば押されており、0なら押されていません。trueなら押されており、falseなら押されていない、ということですね。
 ちなみに、「キーボードにキーなんて256個もあるわけないだろwwwwうぇwwうぇうぇwwwwww」とか言ってchar型の配列を128要素とかに削減したりするとエラーになってプログラムが落ちたりします。必ず256個の配列を用意しましょう。逆に256要素を超えて用意しても理論上は問題ありませんが別のソースコードで変なことをやると変なことになったりするのでおとなしく256要素配列を定義して引数に渡しましょう。

GetJoypadInputState

int GetJoypadInputState(int InputType);

おわりに

 いかがでしたでしょうか。以上の関数があればとりあえずDXライブラリでWindows向けのゲームが一本作れます。プレイヤーを動かすための処理だとか図形(つまりキャラクター)同士が接触しているかどうかの判定のアルゴリズムだとかそういうのは別途学ぶか自力で考え出すかしないといけないのですがそれはそれとして。
 DXライブラリには今回は省略した3D関係の関数とか、スマートフォンで必要なタッチパネル関連の入力とか、その他こまごまとした高度な処理をやりたいときにちょうど良い関数などが多く用意されています。さらに、関数リファレンスページに載っている関数は実装されているものの1/10程度で、ソースコードを読める人だけがわかる数多くの便利な隠し関数が眠っているとか……。4
 しかし、いずれにせよ上記の関数さえあれば最初のPC向けゲームとしてはちょうど良いものが作れるはずです。そのあとで、関数リファレンスを読んで多くの便利機能を使えるようになったり、ソースコードから隠された関数を発掘したりできるようになれば良いのです。いや隠し関数は使えなくても良いですが。

参考文献


  1. アドベントカレンダーの締め切りに間に合わないのでまだほとんどがまとめただけですが、少しずつ関数の内容説明も追記していきます。すべての追記が完了した場合この注釈は消えます。 

  2. アドベントカレンダーの締め切りに間に合わないのですべてのソースコードは未デバッグです。デバッグが完了し次第随時この注釈は書き換えられ、すべてのデバッグが完了した場合この注釈は消えます。 

  3. 公式サイトで案内されている「C++Builder 10.1 Berlin Starter Edition」なるものがbccのはずですがなんかそもそもこのコンパイラに開発環境がくっついているような書かれ方をしているのでBCC Developerは不要かもしれません。2004年のソフトだから最新のbccで動くかわからんし。わけわからなくなったらVisual Studioを使いましょう。 

  4. 昔リファレンスページにあったキーボード入力とコントローラー(ジョイパッド)入力を対応付ける関数がいつの間にか消えていたのですが、それを使っていた手元のソースコードは今でもちゃんと動くので、公開関数から隠し関数に格下げされたんだと思います。