読者です 読者をやめる 読者になる 読者になる

ここまでの冒険を記録しますか?

長岡技大ソフトウェア開発サークルの開発ブログ

【ゲーム製作入門】C/C++でブロック崩しを作る①【DXライブラリ】

書き手:肥田野

プログラミング初心者向けに、簡単なゲームの制作を通してC/C++の基本を解説していきます。

当サークルに所属しない方でも参考にしていただければ幸いです。

前準備として、DXライブラリの公式サイトからDXライブラリをDLし、お持ちの開発環境に合う形で設定をしてください。

この記事ではint型変数の定義と、while文の役割を理解していることを前提に進めていきます。

今回解説するコードです。

#include<DxLib.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);
    if( DxLib_Init() == -1 )return -1 ;
    SetDrawScreen(DX_SCREEN_BACK);
    
    int x = 40;
    int y = 40;

    while(ProcessMessage() != -1){
        int startTime = GetNowCount();
        ScreenFlip();
        ClearDrawScreen();
        
        DrawCircle(x,y,10,GetColor(255,255,255),TRUE);
        
        if(CheckHitKey(KEY_INPUT_ESCAPE) == 1)break;
        int endTime = GetNowCount();
        WaitTimer(1000/60-(endTime-startTime));
    }
    DxLib_End() ;
    return 0 ;
}

実行すると、画面の左上に丸い玉が表示されるかと思います。

サークルでは紙媒体のテキストで説明した部分もありますが、ウェブ版第1回ということで、1行目から順番に説明していきます。

#include<DxLib.h>

DXライブラリの情報を引用する指示をしています。

この作業はソースコードを読む作業の一番最初に実行されます。

int WINAPI WinMain(HINSTANCE hInstance,……

C言語の解説サイトでは「main()」を使っている場合が多いと思います。

WinMain()はmain()をWindowsで使いやすくした物で、WinMain()の内部にmain()が含まれています。

また、()内の要素(引数と言います)は深く考えなくても大丈夫なのでコピペしてしまいましょう。

ChangeWindowMode(TRUE);

ウィンドウサイズで起動したいときにこの関数を使います。

フルスクリーンで実行すると、もし無限ループに陥った時などに厄介なので、極力ウィンドウサイズで実行することをお勧めします。

if( DxLib_Init() == -1 )return -1 ;

DXライブラリを使うために必要な処理です。もしここでエラーが発生した場合はreturn -1でWinMain()を抜けることができます。

SetDrawScreen(DX_SCREEN_BACK);

動くゲームを作るためには座標を少しずつずらして描画した画像を高速で表示する必要があります。

ところが画像の表示と切り替えを同じ画面上で実行すると、切り替わる瞬間が見えてしまいチカチカとしてしまいます。

そのため、「裏画面」を作り、その裏画面でゲームの画像を描画します。

SetDrawScreen()はその設定をするための関数です。

int x = 40;int y = 40;

今回表示する円の中心座標です。

while(ProcessMessage() != -1){

単純な無限ループならwhile(1)でいいのですが、Windowsのアプリを実行するときにはProcessMessage()という関数を定期的に呼び出さなくてはいけません。

そこでエラーが発生しない限りはwhile文をループさせます。

int startTime = GetNowCount();

GetNowCount()は、呼び出された時点での時間をミリ秒単位で返してきます。

ちなみにこの時間はパソコンが起動された瞬間にカウントが始まるのですが、int型の最大値(2の32乗-1)に達した場合はどうなるんでしょうね……f^_^;

ScreenFlip();

先述した裏画面を表に表示する関数です。

ClearDrawScreen();

裏画面をクリアします。

DrawCircle(x,y,10,GetColor(255,255,255),TRUE);

今回メインとなる、円を描く関数です。

引数は中心のX座標、Y座標、半径、色、塗りつぶすか否かです。

GetColor()は光の三原色からint型の色識別番号を変換してくれます。

if(CheckHitKey(KEY_INPUT_ESCAPE) == 1)break;

CheckHitKey()は、引数で指定するキーが押されているかどうかを判断します。

押されていれば1を返すので、これはEscが押されたときにwhile文を脱します。

int endTime = GetNowCount();

やっていることはstartTimeと同じです。

この二つはwhile文が1周するごとに生じる時間差を修正するために使用します。詳しくは次項で。

WaitTimer(1000/60-(endTime-startTime));

WaitTimer()は、ミリ秒単位で指定した時間、処理を停止する関数です。

今回は60FPS(1秒間にwhile文を60回実行させる)ので、1秒=1000ミリ秒。1000/60ミリ秒が60回連続したら1000ミリ秒になりますね。

あとはwhile文の処理中に経過した時間を差し引いてやれば、正確に1/60秒で1周が終わります。

DxLib_End();

DXライブラリを終了させる関数です。

return 0;

WinMainが無事終了したことを表しています。

この回では、DXライブラリでゲームを作るための下地を用意しました。

次回はif文で変数の動きを制御し、画面上の物体を動かしてみたいと思います。