監督スクリプトを記述しよう
このページでは、前回に引き続き、ゲームの監督スクリプトを記述していきます。監督スクリプトの主なお仕事は以下のような感じでしたね。
・ゲーム開始直後、数球オブジェクトを初期配置に並べる
・自分のターンにて、パワーや方向などを調節し、手球を発射
・CPUが(とあるルールにのっとり)パワーや方向などを調節し、手球を発射
・発射後、手球や数球の状況によって、次の番が自分かCPUかを決定する
前回から、自分のターン時の作業をスクリプト化しています。スクリプトの全体概要については前回の前半を参考にして下さい。このページでは、詳細部分の説明の残りについて、順番に解説してきます!
スクリプトを書こう2-2(自ターンの動き 続き)
自ターンの挙動について、残りは④手球発射前の準備スクリプト、⑤手球移動可能時の手球位置調整スクリプトになります。⑤は少し話が長くなりますが、しっかり理解していきましょう!
④手球発射前の準備
ここでは、手球発射前に、待ち時間中は不要なオブジェクトを削除します。また、この後待ち時間中に使う変数のリセットを行います。変数リセットについては、ここで初めて出てくる変数が色々ありますが、内容の詳細は全て制作手順2-5、2-6の方で説明しますので、ここでは省略しておきます。いつもの「フーン」で大丈夫です。
スクリプトは、以下のような感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void beforeshot(){ this.waittime = 1; //待ち時間に移行 //上矢印君、赤丸強調表示君、キュー削除 Destroy(this.arrow); Destroy(this.redcircle); Destroy(this.cue); //変数リセット this.beforeballnum = this.remaininglist.Count; this.collidelist.Clear(); this.allstopball = false; for (int i = 0; i < this.remaininglist.Count; i++){ this.stop_numball[i] = false; } } |
⑤台上で手球の位置調整(移動可の時)
setting=2かつcanmove=0 or 2の時に台上の手球を動かせる、という処理についてです。注意が必要なのは、canmove=0(ファール後の次のターン)では台上全体を移動出来ますが、canmove=2(一番最初のショット時)では手球の移動可能範囲は左1/4程度のみになります(右図も参照)。その点を上手に書けるようなスクリプトにしようとすると、こんな感じでしょうか?
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 |
//Updateメソッド中 if (this.setting == 2) { //矢印手球位置の時は手球の位置調整(canmove=1では移動不可) if (this.canmove == 0) moveplayerball(7.35f, -7.35f); if (this.canmove == 2) moveplayerball(7.35f, 3.8f); } //以下、別メソッド void moveplayerball(float leftedge,float rightedge){ //手球の位置調節 float upperedge = 3.55f; float loweredge = -3.55f; Vector3 moveup = new Vector3(0f, 0.05f, 0f); Vector3 movedown = new Vector3(0f, -0.05f, 0f); Vector3 moveleft = new Vector3(0.05f, 0f, 0f); Vector3 moveright = new Vector3(-0.05f, 0f, 0f); if (Input.GetKey(KeyCode.UpArrow) && this.player_ball.transform.position.y < upperedge){ //上端にいなければ上(Y軸正方向)移動 moveball(moveup); } if (Input.GetKey(KeyCode.DownArrow) && this.player_ball.transform.position.y > loweredge){ //下端にいなければ下(Y軸負方向)移動 moveball(movedown); } if (Input.GetKey(KeyCode.LeftArrow) && this.player_ball.transform.position.x < leftedge){ //左端にいなければ左(X軸正方向)移動 moveball(moveleft); } if (Input.GetKey(KeyCode.RightArrow) && this.player_ball.transform.position.x > rightedge){ //右端にいなければ右(X軸負方向)移動 moveball(moveright); } } void moveball(Vector3 movevec){ //手球、上矢印君、キューが併せて移動 this.player_ball.transform.Translate(movevec, Space.World); this.arrow.transform.Translate(movevec, Space.World); this.cue.transform.Translate(movevec, Space.World); } |
ただ、これで実装してみると分かるのですが、これでもまだ不十分です。というのも、手球の移動が自由過ぎて、台上の数球を動かしてしまうからです。これは現実では禁止行為であり、ファールになります。
そこで、このワガハイ式ビリヤードでは、台上の数球を動かさない範囲で、手球を自由に移動出来る、というスクリプトに変更します。具体的には、上記moveplayerballメソッド中で、各矢印キーを押した時の対処が書いてあるif文の中身を以下のように修正します。以下では、代表で「上(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 30 31 32 33 34 35 36 37 |
bool[] notnear = { true, true, true, true, true, true, true, true, true }; bool allnotnear = false; //moveplayerballメソッド中 if (Input.GetKey(KeyCode.UpArrow) && this.player_ball.transform.position.y < upperedge){ //上端にいなければ上(Y軸正方向)移動 movecheck(moveup); if (this.allnotnear) moveball(moveup); } //手球移動後に、数球と干渉しないか確認→結果はnotnear[i]へ void movecheck(Vector3 movevec){ float[] dist = new float[9]; for (int i = 0; i < this.remaininglist.Count; i++){ //台上に残っている全数球と手球移動先との中心間距離を計測 dist[i] = Vector3.Distance(this.player_ball.transform.position + movevec, this.number_balls[this.remaininglist[i] - 1].transform.position); if (dist[i] > this.diam){ this.notnear[i] = true; //中心間距離が直径以上なら移動OK } else { this.notnear[i] = false; //中心間距離が直径以下なら移動NG } } ifnotnear(0); } //各数球の確認結果(notnear[i]に保存)をallnotnearへとりまとめ void ifnotnear(int num){ if (this.notnear[num]){ if (num == this.remaininglist.Count - 1){ this.allnotnear = true; //notnear[i]が全てtrueならOK } else { ifnotnear(num + 1); //再帰呼び出し } } else { this.allnotnear = false; } } |
movecheck というメソッド内で、手球の移動先と数球が干渉し合わないかどうかのテストを行っています(注:まだ実際には移動していない)。干渉し合うか否かは、お互いの中心間距離(Vector3.Distance(2点の座標)で計測します)が球直径diam以下なら干渉=手球移動不可、という判定を下します。
各数球との確認結果は、notnear[i]というbool型配列に入り、それらを全部確認して総合的な結論を下すのがallnotnearというbool型変数になります。配列notnear[i]の中に、1つでもfalse、つまり移動NGが出ていると、allnotnear=falseになる、という仕組みです。ここの手続きにはメソッドの再帰呼び出しを使用しています。再帰呼び出しについてはぷよぷよ制作手順5-2にて詳しく解説しましたのでそちらを参照下さい。その時とは再帰呼び出しの使い方が異なりますが、こういうbool型配列の総合判断を下す時は、このような再帰呼び出しを活用してみるのも良さそうです。
最後に
やっと、自ターンの挙動について、Updateメソッド中にスクリプトを書きあげることが出来ました!長かった…。次回は、相手ターンでのCPUの挙動について、スクリプト化していきます!!