Unityではじめてのテトリス風落ちゲー制作記 ~その7 ブロック消去編~

Unity

Unityでテトリス風落ちゲーを作ってみたいけど、何から手を付けていいか分からない。私もそんな一人です。ここでは、自分の勉強も含めて、簡単なテトリス風落ちゲーを制作していく過程を掲載していきます。

この連載を最後まで読めば、このようなテトリス風落ちゲーが1人で作れるようになります。

別ウィンドウで開く場合はこちら

今回はブロック消去編です。

前回記事では、落下ブロックが着地したら、配置ブロックへ変換させるプログラムを作成しました。

今回は、 1列ブロックが揃ったのを判定し、ブロックを消去するまでのプログラムを解説します。

この記事はこんな人におすすめ!

  • 用意されたアセットを極力使わず、自分の力でゲームを作りたい
  • プログラミング初心者で1つ1つ丁寧に解説した記事が読みたい
  • Unity初心者がスキルを上げながらゲームを制作していく過程を見たい

本ゲーム制作方法は自己流です。もっと簡単に作る方法もあると思いますので、ご了承下さい。

消去判定

まず、1列すべてブロックが揃った列を検索して、列を消去するかどうか判定するメソッドを作成します。

private bool JudgeEraseRow()
{
    bool eraseFlg = false;
    for(int j=0; j<18; j++){
        eraseRow[j] = false;
        bool buff = true;
        for(int i=1; i<11; i++){
            if(blockStat[j,i] != 3)
            {
                buff = false;
            }
        }
        if(buff == true){
            eraseRow[j] = true;
            eraseFlg = true;
        }
    }
    return eraseFlg;
}

戻り値として、bool型のeraseFlgを返し、trueであれば1列以上ブロックが揃っていることになります。

bool型の配列eraseRowは、何列目が揃ったかの情報を格納します。

ブロック消去し、下に詰める

揃った列のブロックを消去して下に詰めるプログラムの解説です。

private void BlockErase(){
    int i,j,k;
    int eraseCount;

    eraseCount = 0;
    for(j=0; j<18; j++){
        if(eraseRow[j] == true){
            eraseCount++;
            // 1行消去
            for(i=1; i<11; i++){
                blockStat[j, i] = 0;
            }
            // 消去分、下にずらす
            for(k=j; k>0; k--){
                for(i=1; i<11; i++){
                blockStat[k, i] = blockStat[k-1, i];
                blockStat[k-1, i] = 0;
                }
            }
        } 
    }
}

最上位からブロックが揃った列を探索していき、揃った列を見つけたら、その列すべてのブロック状態を、「3」から「0」に変換します。

そして、消去した列より上の列を1マスずつ下にずらします。

ゲーム画面更新

前回までは、ブロックのゲーム画面表示をUpdate()内に記述していましたが、配置ブロックもUpdate()内に記述すると見通しが悪くなるので、メソッド化しました。

private void UpdateDisplay()
{
    // 落下ブロックのゲーム画面表示
    for(int i=0; i<4; i++){
        for(int j=0; j<4; j++){
            Destroy(fallBlockObj[j,i]);
            if(fallBlockStat[j,i] == 2){
                fallBlockObj[j,i] = Instantiate(fallBlockPfb, new Vector3(fallBlockPosX + i + OX, -fallBlockPosY -j + OY, 0), Quaternion.identity);  
            }
        }
    }

    // 配置ブロックのゲーム画面表示
    for(int i=1; i<11; i++){
        for(int j=1; j<18; j++){
            Destroy(blockObj[j,i]);
            if(blockStat[j,i] == 3){
                blockObj[j,i] = Instantiate(placementBlockPfb, new Vector3(i + OX, -j + OY, 0), Quaternion.identity);  
            }
        }
    }
}

作成したメソッドをUpdate()に追加

ゲーム設計編で作成した状態遷移図を基に、”GROUND”状態時に消去判定し、ブロックが1列以上揃ったばあいに”ERASE”状態に遷移させます。

状態遷移図があると、プログラム作成がすいすい進みます。設計は大事ですね。

void Update() {
    switch(gameStat){
        case START:
        /*
        (省略)
        */

        case GROUND:
            /*
            (省略)
            */

            // 落下ブロックの着地確定
            if(groundCountTime >= 1){
                /*
                (省略)
                */

                // 1列以上ブロックが揃ったら"ERASE"に遷移
                if(JudgeEraseRow()){
                    gameStat = ERASE;
                }
                else
                {
                    NextBlockSet(); // 次の落下ブロックをセット
                    gameStat = START;          
                }
                
            }
            break;

        case ERASE:
            BlockErase(); // 揃った列のブロックを消去し、1列下に詰める
            NextBlockSet(); // 次の落下ブロックをセット
            gameStat = START;
            break;
            
        case GAMEOVER:
            break;
    }
    /*
    (省略)
    */
    UpdateDisplay();
}

プログラムを動かしてみよう

ブロックが1列揃ったらブロックが消えるようになりました。かなりゲームになってきました!

まとめ

今回は、 1列ブロックが揃ったのを判定し、ブロックを消去するまでのプログラムを解説しました。

次回は、ブロックが1列揃ったら得点を増やし、ゲーム要素を追加していく予定です。

最後までお読み頂きありがとうございました。