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

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

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

書き手:肥田野

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

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

この記事では前回の内容を理解していることを前提に進めていきます。

前回まででプレイヤーと球の動きが確立したので、今回はいよいよブロックを作ってみたいと思います。

ブロックを作るにあたって、「配列」を使用しています。

配列は決まった数のデータ型をまとめて管理できる便利な機能ですので、ぜひマスターしましょう。

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

#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 = 320,y = 240;//new
    int vecX = 0,vecY = 0;

    int px = 320,py = 400;

    bool live[5];//new

    live[0] = true;
    live[1] = true;
    live[2] = true;
    live[3] = true;
    live[4] = true;
    //newここまで

    while(ProcessMessage() != -1){
        int startTime = GetNowCount();
        ScreenFlip();
        ClearDrawScreen();
        
        DrawCircle(x,y,20,GetColor(255,255,255),TRUE);
        DrawBox(px,py,px+60,py+20,GetColor(255,255,255),TRUE);

        for(int i=0;i<5;i++){//new
            if(live[i]){
                DrawBox(80+i*100,100,80+(i+1)*100-10,140,GetColor(255,255,255),TRUE);
                if(x>80+i*100 && x<80+(i+1)*100-10 && y > 100 && y < 140){
                    live[i] = false;
                    vecX *= -1;
                    vecY *= -1;
                }
            }
        }

        if(vecX != 0 && vecX != 0){
            if(x>640)vecX = -1;
            if(x<0)vecX = 1;
            if(y<0)vecY = 1;
            if(x>px && x<px+60 && y > py)vecY = -1;
            if(y>480){
                x = 320;
                y = 240;
                vecX = 0;
                vecY = 0;
                for(int i=0;i<5;i++){
                    live[i] = true;
                }
            }
        }else{
            DrawFormatString(260,160,GetColor(255,255,255),"PUSH SPACE");
            if(CheckHitKey(KEY_INPUT_SPACE)){
                vecX = 1;
                vecY = 1;
                for(int i=0;i<5;i++)live[i] = true;//new
            }
        }
        if(!live[0] && !live[1] && !live[2] && !live[3] && !live[4]){//new
            DrawFormatString(260,120,GetColor(255,255,255),"GAME CLEAR!");
            x = 320;
            y = 240;
            vecX = 0;
            vecY = 0;
        }

        x += 5*vecX;
        y += 5*vecY;

        if(CheckHitKey(KEY_INPUT_RIGHT) == 1){
            px += 10;
        }
        if(CheckHitKey(KEY_INPUT_LEFT) == 1){
            px -= 10;
        }
        
        if(CheckHitKey(KEY_INPUT_ESCAPE) == 1)break;
        int endTime = GetNowCount();
        WaitTimer(1000/60-(endTime-startTime));
    }
    DxLib_End() ;
    return 0 ;
}

newコメントの付いた部分を中心に解説していきます。

int x = 320,y = 240;

ブロックを配置する関係で、球の初期位置を中心に持ってきました。

いや、最初からこうすればよかったんですけどね……

bool live[5];

二つの新しい要素がありますね。

まず「bool」ですが、これはデータ型の一つです。int型が整数を扱えたのに対し、boolはtrueとfalseの2種類しか扱えません。

いわばbool型はフラグ、もしくはスイッチのようなものなんです。

なお、bool型はC++の要素なので、C言語のみの環境でboolを使おうとするとエラーになると思います(試したことはありません)

そして末尾にある[5]ですが、これは配列の要素の総数を表しています。

bool型で要素が5つということは、liveと名のついたスイッチが5つ繋がっているということですね。

一つ一つの要素を扱うときは、live[0]、live[1]という風にの中で番号を指定します。

この時注意しなければならないのが、配列の添え字(の中の数字)は0から始まるということです。

一般的な感覚では1から始まるような気がしますが、0から始めるんです。これは慣れるしかありませんね。日常生活で数を数える時に0から数え始めて計算が狂うようになったら一人前です(笑)

そのため、この配列は要素の数は5つで、最後の要素の添え字は4ということになります。

コードの続きでは、liveのそれぞれの要素を順番にtrueにしています。

for(int i=0;i<5;i++){

for文の1行目で「live[i]」と書いています。

この「i」はfor文の()内で宣言したint型の変数で、添え字にint型の変数を指定することができます。これが配列を使う最大のメリットとも言えるんです。

if(live[i]){

liveは各ブロックが生きているかを判定する変数なので、生きている場合はDrawBoxによる描画と当たり判定の処理を行います。

球が当たった時にvecXとvecYを反転させるようにしています。実行してみると少し違和感を感じるかもしれませんが、これは後々修正するので今は無視して大丈夫です。

for(int i=0;i<5;i++)live[i] = true;

球が画面下に当たったら、全てのliveをtrueにして、ブロックを復活させます。

if(!live[0] && !live[1] && !live[2] && !live[3] && !live[4]){

全てのliveがfalseになったらゲームクリアです。

bool型の変数をif文の条件に使うときは、「==true」とせずに、変数名を書くだけでその変数がtrueの時に、と認識されます。

なのでfalseの時を判定させたければ、「!live[0]」のように変数名の前に「!」を付け加えることでより簡略化できます。

これでひとまず、ブロック崩しとしてはプレイできるようになりました。

しかし、だんだんwhile文の中が長くなってきて読みにくくなっていますね。

それに、ブロックを描画するDrawBoxの座標も計算が複雑で分かりにくいです。

次回はこれをより感覚的に扱えるように、「クラス」という機能を使ってより感覚的にブロックを扱えるようにします。

過去にプログラムに触れたことのある人なら「クラス…ウッ頭が」となるかもしれませんが、恐れを抱かずにもう一度向き合ってみましょう。