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

スマゲ

スマートなゲームづくりを目指して日々精進

Unityでパズドラ風3Matchパズルを作る_その2_演出編1

前回作った3Matchパズル(ロジックのみ)ですが、ピースが消える部分や、補充される部分があまりにも味気ないので、ちょっとそれっぽくします。

■前回の内容
Unityでパズドラ風3Matchパズルを作る_その1_ロジック編 - スマゲ

■本編の完成イメージ
f:id:sanukin39:20170429230343g:plain

■コード確認用リポジトリ
github.com

■環境
Mac OS Sierra 10.12.4
Unity 5.6.0 f3
言語 C#

■実装
ここからは[その1]のつづきです。
まだ見てない方はここから確認してみてください。

■削除とピースの補充のタイミングで一定時間処理を止める
[Board.cs]の[DeleteMatchPiece]と[FillPiece]を以下のように書き換えます

    // マッチングしているピースを削除する
    public IEnumerator DeleteMatchPiece(Action endCallBadk)
    {
        // マッチしているピースの削除フラグを立てる
        foreach (var piece in board)
        {
            piece.deleteFlag = IsMatchPiece(piece);
        }

        // 削除フラグが立っているオブジェクトを削除する
        foreach (var piece in board)
        {
            if (piece != null && piece.deleteFlag)
            {
                Destroy(piece.gameObject);
            }
        }

        yield return new WaitForSeconds(1f);
        endCallBadk();
    }

    // ピースが消えている場所を詰めて、新しいピースを生成する
    public IEnumerator FillPiece(Action endCallBack)
    {
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                FillPiece(new Vector2(i, j));
            }
        }

        yield return new WaitForSeconds(1f);
        endCallBack();
    }

変更点は返り値にIEnumeratorを指定したこと、引数にActionを取るようにしたこと、最後に一秒待ってから引数に取ったActionを実行するようにしたことです。

次は[GameManager.cs] の [DeletePiece]と[FillPiece]を以下のように書き換えます

    // マッチングしているピースを削除する
    private void DeletePiece()
    {
        currentState = GameState.Wait;
        StartCoroutine(board.DeleteMatchPiece(() => currentState = GameState.FillPiece));
    }

    // 盤面上のかけている部分にピースを補充する
    private void FillPiece()
    {
        currentState = GameState.Wait;
        StartCoroutine(board.FillPiece(() => currentState = GameState.MatchCheck));
    }

変更点は[StartCoroutine]により[Board.cs]のコルーチンを実行していること、終了時のコールバックをメソッドの引数にしていることです。

■実行
ちょっとだけ処理が見やすくなりました。
f:id:sanukin39:20170424233542g:plain

■ピースが順番に消されるようにする
今のままだと、マッチングしているピースが一斉に消えてしまうので順番に消えるようにしてみます

■ピース削除の処理を変える
[Board.cs]の[DeleteMatchPiece]を以下のように編集します

    // マッチングしているピースを削除する
    public IEnumerator DeleteMatchPiece(Action endCallBadk)
    {
        foreach (var piece in board)
        {
            if (piece != null && IsMatchPiece(piece))
            {
                var pos = GetPieceBoardPos(piece);
                DestroyMatchPiece(pos, piece.GetKind());
                yield return new WaitForSeconds(0.5f);
            }
        }

        endCallBadk();
    }

そしてクラスの一番下に以下のメソッドを付け足します。

    // 特定のピースがマッチしている場合、ほかのマッチしたピースとともに削除する
    private void DestroyMatchPiece(Vector2 pos, PieceKind kind)
    {
        // ピースの場所が盤面以外だったら何もしない
        if (!IsInBoard(pos))
        {
            return;
        }

        // ピースが無効であったり削除フラグが立っていたりそもそも、種別がちがうならば何もしない
        var piece = board[(int)pos.x, (int)pos.y];
        if (piece == null || piece.deleteFlag || piece.GetKind() != kind)
        {
            return;
        }

        // ピースが同じ種類でもマッチングしてなければ何もしない
        if (!IsMatchPiece(piece))
        {
            return;
        }

        // 削除フラグをたてて、周り4方のピースを判定する
        piece.deleteFlag = true;
        foreach (var dir in directions)
        {
            DestroyMatchPiece(pos + dir, kind);
        }

        // ピースを削除する
        Destroy(piece.gameObject);
    }

やっている内容は盤面を走査し、マッチングしているピースがあれば、そのピースに隣接するピースを参照します。
そのピースがマッチングしているピースでかつ同じ種類のものであれば、削除フラグを立て、さらに走査をすすめるという方法です。

■実行
f:id:sanukin39:20170426222418g:plain

■その3_演出編2
次はピースが補充される演出を組み込もうと思いましたが、少し長くなりそうなのでその3でやってみようとおもいます。
Unityでパズドラ風3Matchパズルを作る_その3_演出編2 - スマゲ

github.com


■関連リンク
Unityでパズドラ風3Matchパズルを作る_その1_ロジック編 - スマゲ
Unityでパズドラ風3Matchパズルを作る_その3_演出編2 - スマゲ
Unityでパズドラ風3Matchパズルを作る_その4_演出編3 - スマゲ
Unityでパズドラ風3Matchパズルを作る_その5_演出編4 - スマゲ
Unityでパズドラ風3Matchパズルを作る_その6_ステータス表示編 - スマゲ