監督スクリプトを記述しよう(ブロック消滅仕組み作成)
このページでは、ゲームの監督スクリプトを記述していきます。ワガハイ式テトリスにおける監督スクリプトの主なお仕事を書き出すと以下のようになります。
・ブロック落下が完了次第、10ブロック分スキマ無くしき詰めた列のブロックを消滅させる
・ブロックを消した際、右上の「○○列消した」の所の数字を更新
・10列ブロックを消すごとに、左上に表示のレベルを1つ上げ、ミノの落下速度を上げる
・ブロック消滅後、残ったブロックに落下の指示
・ミノ出現位置にブロックが残っていたらゲームオーバー画面に移行
細かいことを言うとまだまだあるんですが、主な所はこんな感じです。これから順番に実装していくのですが、まずは一番上のブロック落下が完了次第、10ブロック分スキマ無くしき詰めた列のブロックを消滅させるのスクリプト文を書いていきます。
テトリスの根幹部分と言っても過言ではないゲームの最重要部分になります。ただ、ぷよぷよでのぷよ消滅スクリプトの解説が制作手順5-1~5-4と4回に渡って(苦労して)書いてきたのに比べると、有り難いことに、テトリスのブロック消滅のスクリプトはかなり単純に書けます!本当に、何故ゲーム制作の第一号にぷよぷよを選んだんですかね…(笑)。
決して難しいスクリプトは登場しませんので、落ち着いて一つずつ、ポイントをおさえていきましょう!
スクリプトを書く前の作戦会議
まずは基本の方向性を決めていきましょう。やることは10ブロック分スキマ無くしき詰めた列のブロックを消滅させる、です。なので、各列にブロックが何個配置されているかをカウントする必要がありますね。ここは、以前のぷよぷよのように悩まずに、総当たり戦で攻めていきましょう!!
右図のような方針で消えるブロックを決めていきます。簡単に説明しますと…、
①各ブロックのy座標を確認する
②各列ごとにブロックが何個ずつ置かれているかをカウントする
③②の結果、10個ブロックが置かれている列を発見次第、その列のブロックは全て消滅!
こんな具合になります。右図の例で言いますと、i=0の列(Y座標=-9.5f)と、i=2の列(Y座標=-7.5f)とでブロックが10個配置されていますので、これらの列は消滅し、残りのブロックは下で消えた列の分落下していけば、成功ですね!
ブロック消滅の仕組みをスクリプト化しよう
ではいよいよ、ブロック削除の話をスクリプトに書いてきます!ちなみに、先程最後に書きました、残ったブロックの落下指示については次回にまわします!
なお、以降のスクリプトについては、特に注記の無い限り、基本的にはミノの落下完了時に呼び出される監督スクリプト中のメソッド内に書いていきます。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
GameObject[] blocks; //フィールド中のblockオブジェクト抽出 float[] blockx = new float[1000]; //各blockオブジェクトのx座標 float[] blocky = new float[1000]; //各blockオブジェクトのy座標 float[] rowy = new float[20]; //各列のy座標(全20列) int[] checkrow = new int[20]; //各列に含まれるblockの個数(全20列) List<float> deleteyset = new List<float>(); //block削除列のy座標リスト //以下、Startメソッド内に記述 for (int i = 0; i < this.checkrow.Length; i++) { this.rowy[i] = -10.5f + i * 1.0f; //各列のブロックy座標定義 } //以下、ミノの落下完了時に呼び出されるメソッド内に記述 int i = 0; int j = 0; this.deleteyset.Clear(); //block削除列のy座標リストを調査前に初期化 for (i = 0; i < this.checkrow.Length; i++) { this.checkrow[i] = 0; //各列のblock個数を調査前に初期化 } i = 0; //現状のフィールド中の全blockオブジェクトの位置調査 this.blocks = GameObject.FindGameObjectsWithTag("block"); foreach (GameObject block in this.blocks) { this.blockx[i] = Mathf.RoundToInt(block.transform.position.x * 10.0f) / 10.0f; this.blocky[i] = Mathf.RoundToInt(block.transform.position.y * 10.0f) / 10.0f; i++; } //各列(y=-9.5,-8.5,…,8.5,9.5)のblock個数をカウント i = 0; for (i = 0; i < this.checkrow.Length; i++) { j = 0; foreach (GameObject block in this.blocks) { //全blockをy座標ごとに分類し、各列に何個blockがあるかを調査 if (this.rowy[i] == this.blocky[j]) this.checkrow[i]++; j++; } } i = 0; for (i = 0; i < this.checkrow.Length; i++) { if (this.checkrow[i] == 10) { //列のブロック数が10個に到達していたら、以下のリストにその列のy座標を追加 this.deleteyset.Add(this.rowy[i]); } } //block削除 for (i = 0; i < this.deleteyset.Count; i++){ j = 0; foreach (GameObject block in this.blocks){ //削除リスト中のy座標とblockのy座標が一致したら削除 if (this.deleteyset[i] == this.blocky[j]) Destroy(block); j++; } } |
各スクリプトの説明については近くのコメント文を参照下さい。そこまでぶっ飛んだスクリプトは書いていないと思いますので、落ち着いてお読み頂ければ難しくないハズ…!ちなみに、動的配列についてはこちらのページに別途纏めましたので併せて参考にして下さい。m(_ _)m
最後に
今回で、監督スクリプトの1つ目の仕事である10ブロック分スキマ無くしき詰めた列のブロックを消滅させるのスクリプト化まで完了しました。他のゲームでは、かなり説明に時間とページ数のかかる監督スクリプトですが、実はテトリスの監督スクリプトに関しては、もう説明が半分ぐらい終了してしまいました!早い!(笑)
という訳で、次回は監督スクリプト2つ目以降の仕事を一気にスクリプトに書き下していきます!またよろしくお願いします!