Unityテトリスの作り方-8

※当サイトはアフィリエイト広告を使用しています。

テトリス作成

テトリスの作り方-8に入りました。

前回は、Gridを作成してminoの上にminoを積み上げるところまでは、完成しました。

しかし、minoが一列そろってもminoが消えません。

今回は、1列そろったらminoも消えるという処理を追加します。

スポンサーリンク

minoが1列そろったら消す処理を追加

まずは、コードをすべて載せます。
確認しつつ、どういう処理になっているのか?確認しましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Mino : MonoBehaviour
{
    public float previousTime;
    // minoの落ちる時間
    public float fallTime = 1f;

    // ステージの大きさ
    private static int width = 10;
    private static int height = 20;

    // mino回転
    public Vector3 rotationPoint;

    // grid
    private static Transform[,] grid = new Transform[width, height];

    void Update()
    {
        MinoMovememt();
    }

    private void MinoMovememt()
    {
        // 左矢印キーで左に動く
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            transform.position += new Vector3(-1, 0, 0);
            
            if (!ValidMovement()) 
            {
                transform.position -= new Vector3(-1, 0, 0);
            }

        }
        // 右矢印キーで右に動く
        else if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            transform.position += new Vector3(1, 0, 0);
            
            if (!ValidMovement()) 
            {
                transform.position -= new Vector3(1, 0, 0);
            }
        }
        // 自動で下に移動させつつ、下矢印キーでも移動する
        else if (Input.GetKeyDown(KeyCode.DownArrow) || Time.time - previousTime >= fallTime) 
        {
            transform.position += new Vector3(0, -1, 0);
            
            if (!ValidMovement()) 
            {
                transform.position -= new Vector3(0, -1, 0);
                AddToGrid();
                // 今回の追加
                CheckLines();
                this.enabled = false;
                FindObjectOfType<SpawnMino>().NewMino();
            }

            previousTime = Time.time;
        }
        else if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            // ブロックの回転
            transform.RotateAround(transform.TransformPoint(rotationPoint), new Vector3(0, 0, 1), 90);
        }
    }

    // 今回の追加 ラインがあるか?確認
    public void CheckLines()
    {
        for (int i = height - 1; i >= 0; i--)
        {
            if (HasLine(i))
            {
                DeleteLine(i);
                RowDown(i);
            }
        }
    }

    // 今回の追加 列がそろっているか確認
    bool HasLine(int i)
    {
        for (int j = 0; j < width; j++)
        {
            if (grid[j, i] == null)
                return false;
        }
        return true;
    }

    // 今回の追加 ラインを消す
    void DeleteLine(int i)
    {
        for (int j = 0; j < width; j++)
        {
            Destroy(grid[j, i].gameObject);
            grid[j, i] = null;
        }

    }

    // 今回の追加 列を下げる
    public void RowDown(int i)
    {
        for (int y = i; y < height; y++)
        {
            for (int j = 0; j < width; j++)
            {
                if (grid[j, y] != null)
                {
                    grid[j, y - 1] = grid[j, y];
                    grid[j, y] = null;
                    grid[j, y - 1].transform.position -= new Vector3(0, 1, 0);
                }
            }
        }
    }

    void AddToGrid() 
    {
        
        foreach (Transform children in transform) 
        {
            int roundX = Mathf.RoundToInt(children.transform.position.x);
            int roundY = Mathf.RoundToInt(children.transform.position.y);

            grid[roundX, roundY] = children;
        }
        
    }

    // minoの移動範囲の制御
    bool ValidMovement()
    {

        foreach (Transform children in transform)
        {
            int roundX = Mathf.RoundToInt(children.transform.position.x);
            int roundY = Mathf.RoundToInt(children.transform.position.y);

            // minoがステージよりはみ出さないように制御
            if (roundX < 0 || roundX >= width || roundY < 0 || roundY >= height)
            {
                return false;
            }
            if (grid[roundX, roundY] != null)
            {
                return false;
            }
            

        }
        return true;
    }
}

今回追加したコードのみ抜粋します。

CheckLinesメソッドを追加

// 今回の追加
public void CheckLines()
    {
        for (int i = height - 1; i >= 0; i--)
        {
            if (HasLine(i))
            {
                DeleteLine(i);
                RowDown(i);
            }
        }
    }

for (int i = height – 1; i >= 0; i–)は、
iが0に以下になるまで繰り返すということです。

詳しくはfor文の文法を勉強してみてください。

HasLineメソッドを追加

// 今回の追加 列がそろっているか確認
    bool HasLine(int i)
    {
        for (int j = 0; j < width; j++)
        {
            if (grid[j, i] == null)
                return false;
        }
        return true;
    }

HasLineメソッドではminoの数を元に横の列がそろっているかを確認しています。

for (int j = 0; j < width; j++)は、
j が width以内であればfalseを返してminoがそろっていないということになり、width以上になるとtrueを返してminoがそろっているということになります。

DeleteLineメソッドを追加

// 今回の追加 ラインを消す
    void DeleteLine(int i)
    {
        for (int j = 0; j < width; j++)
        {
            Destroy(grid[j, i].gameObject);
            grid[j, i] = null;
        }

    }

DeleteLineメソッドでは、
j が width の値を超えるとそろった列を削除します。

RowDownメソッドを追加

// 今回の追加 列を下げる
    public void RowDown(int i)
    {
        for (int y = i; y < height; y++)
        {
            for (int j = 0; j < width; j++)
            {
                if (grid[j, y] != null)
                {
                    grid[j, y - 1] = grid[j, y];
                    grid[j, y] = null;
                    grid[j, y - 1].transform.position -= new Vector3(0, 1, 0);
                }
            }
        }
    }

RowDownメソッドでは、
minoの列がそろっていたら、一列さげて下さい。

という処理を追加しました。

UdemyでUnityを学習する

個人的に、最初のUnityでの開発は動画を見ながら行うことをオススメします。

Udemyには初心者向けから中級者向けなどUnityを教えてくれる教材が揃っていて、割引期間だと数千円で講座を受講できます。

スペシャリストの方の講義が数千円で学べると思うと本当に安いと感心します。

実際に私もいくつかUdemyで課金をして色々学んでいます。

また、Udemyを使ったことがない方も30日返金保証もついているので安心して始めることができます。
まずはお試しで講座を受講してみましょう。

今回のまとめ

今回は、一番難易度が高かった気がします。
Gridの概念を理解してないとわかりづらい部分もあったと思います。

今回でテトリスの基本動作の処理は完了しました。
次回からスコア表示やゲームオーバー画面の表示などUIの部分に入っていきます。

次回はスコアを追加して、列が消えるごとにスコアを追加する処理を追加します。
最後まで読んでいただきありがとうございました。

⭐️あわせて読もう!
Unityテトリスの作り方-9

コメント

タイトルとURLをコピーしました