今回はテトリスブロックが一列揃ったら消える処理を作っていきます。
前回の記事↓
一列揃ったら消える処理の作り方
BlockのTagの追加
まずは、Hierarchyに存在するブロックを取得しやすくするため、プレハブのBlockに「block」タグを追加しましょう。
プレハブのBlockを選択して、InspectorのTagからAdd Tagを選択してください。
Tagsから「block」を追加してください。
最後にもう一度プレハブのBlockを選択して、Tagを「block」に変更してください。これでTagの登録は完了です。
コードの追加
ではコードに移ります。
まずは、Field.csのUpdate()を次のように変更してください。Fallが完了した後にShotではなくDeleteに遷移するようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void Update() { switch (GameStatus.status) { case "Shot": waitCnt = MAXWAIT; break; case "Wait": waitCnt--; //1秒ブロックが当たらなかったらShot状態に戻す if( waitCnt<=0 ) { GameStatus.status = "Shot"; } break; case "Fall": Debug.Log("Fall Stauts"); if (!FallBlocks()) { GameStatus.status = "Delete"; } break; case "Delete": CheckLines(); break; } } |
ここで、CheckLines()という新しい関数を記述しています。これは、揃っている列があるかどうかをチェックしてその列のブロックを削除する関数になります。実際の
CheckLines()は次のようになります。
こちらでは、y座標降順にblocksを走査して、そろっている列がないかチェックしています。そして、そろっている列があれば、列を削除する関数DeleteBlocks()と消えた分だけブロックをずらす関数DropBlocks()を実行させるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//消えるラインがあるかどうかチェック void CheckLines() { for (int i = 0; i < 20;i++) { bool isDelete = true; for (int j = 0; j < 10;j++) { //上から順に調べたいため、「i」ではなく「20-i-1」を使用する if(!blocks[j,20-i-1]) { isDelete = false; break; } } //削除できる列であれば削除 if(isDelete) { //一列ブロックを削除 DeleteBlocks(20-i-1); //消えた分だけブロックを下げる DropBlocks(20-i-1); } } } |
DeleteBlocks()は、次のようなコードになります。
ここでは、先ほど設定したBlockのタグ「block」を利用して、GameObject.FindGameObjectsWithTag(“block”)によりHierarchy上のBlockをすべて取得させるようにしています。それらをすべてチェックし、指定した座標のブロックであれば削除するようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//一列ブロックを削除する処理 void DeleteBlocks(int h) { //一列ブロックのGameObjectを削除する GameObject[] glist = GameObject.FindGameObjectsWithTag("block"); foreach(GameObject go in glist) { if(go.GetComponent<Block>().y == h) { blocks[go.GetComponent<Block>().x, h] = false; Destroy(go); } } } |
さらに、DropBlocks()は次のようになります。
こちらでもTagを利用してBlockのゲームオブジェクトをすべて取得しています。その配列を一度リストに変換しています。変換する理由は、y座標降順にソートさせるためです。ソートはOrderBY()で実行されます。ここでは、ラムダ式を用いて「(x) => x.GetComponent<Block>().y 」によりソートさせています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System.Linq; // // 省略 // //消した列より高い位置のブロックを落下させる処理 void DropBlocks(int h) { //落下させるブロックを登録 List<GameObject> glist = new List<GameObject>(GameObject.FindGameObjectsWithTag("block")); glist.OrderBy((x) => x.GetComponent<Block>().y ); foreach(GameObject go in glist) { if(go.GetComponent<Block>().y > h) { //blocksを更新 int x = go.GetComponent<Block>().x; int y = go.GetComponent<Block>().y; blocks[x, y] = false; blocks[x, y-1] = true; //y座標をずらす go.GetComponent<Block>().y -= 1; //GameObjectの座標をずらす go.transform.position += Vector3.down * 0.1f; } } } |
これで設定は完了です。実行してみましょう。
次のように一列揃ったらブロックが消えるようになったでしょうか?
次回予告
実際にプレイしてみるとわかると思いますが、このままではかなり操作性が悪いと思います。そのため、次回はブロックが衝突する位置を可視化するコードを作成していきます。
次回の記事↓
コメント