監督スクリプトを記述しよう
このページでは、前回に引き続き、ゲームの監督スクリプトを記述していきます。監督スクリプトの主なお仕事は以下のような感じでしたね。
・トランプ山札をシャッフルして、各プレイヤーにカード配布
・手札に7のカードがあった場合は開始前に場に出す
・自分のターンに場に出すカードを選択、出せない場合はパス
・CPUが(とあるルールにのっとり)場に出すカードを選択、出せない場合はパス
・各プレイヤー0枚になったらあがり、順位表示
今回は上記リストの赤字部分に当たる箇所をスクリプト化していきます!
スクリプトを書こう1(シャッフル&配布)~続き~
前回、山札のシャッフルまでスクリプト化出来ましたね。今回はその続きで各プレイヤーに配布する段階からスクリプト化していきましょう!
各プレイヤーにカード配布
各プレイヤーへのカード配布はこんな感じでしょうか。イメージとしては山札の上から1枚ずつ順に各プレイヤーに配布している感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Startメソッド前に定義 List<TrumpCard> MYcards = new List<TrumpCard>(); List<TrumpCard> CPU1cards = new List<TrumpCard>(); List<TrumpCard> CPU2cards = new List<TrumpCard>(); List<TrumpCard> CPU3cards = new List<TrumpCard>(); //4人に手札配布(1枚ずつ順番に配っていく感じ) this.MYcards.Clear(); this.CPU1cards.Clear(); this.CPU2cards.Clear(); this.CPU3cards.Clear(); for (i = 0; i < 13; i++){ this.MYcards.Add(this.deckcards[4*i]); //0,4,8,…枚目を配布 this.CPU1cards.Add(this.deckcards[4*i+1]); //1,5,9,…枚目を配布 this.CPU2cards.Add(this.deckcards[4*i+2]); //2,6,10,…枚目を配布 this.CPU3cards.Add(this.deckcards[4*i+3]); //3,7,11,…枚目を配布 } |
なお、今回各プレーヤーの手札を表す配列に、動的配列を使用しました。今後のことも考えて動的配列にしたのですが、動的配列???という方はこちらのページに別途纏めましたので併せて参考にして下さい。m(_ _)m
次に、配布されたカードを各プレイヤーの手札位置に配置していきます。配置場所は制作手順1-2の時に決めたように、右図のような配置になりますので、それを数式化すると下のようなスクリプトになります。
あと、カードが配布されたついでにカードの整列、手札枚数表示の更新、CPUの手札カード裏返し、などの作業も併せてスクリプト化しておきましょう。
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 |
//Startメソッド前に定義 Vector3[] MYcardpos = new Vector3[13]; //手札位置座標 Vector3[] CPU1cardpos = new Vector3[13]; Vector3[] CPU2cardpos = new Vector3[13]; Vector3[] CPU3cardpos = new Vector3[13]; GameObject mycardnum; //各プレイヤーの手札枚数表示 GameObject CPU1cardnum; GameObject CPU2cardnum; GameObject CPU3cardnum; //手札位置を定義…手札位置が変更なってもココを変更するだけでOK for (i = 0; i < 13; i++){ this.MYcardpos[i] = new Vector3(1.3f * i, 0.2f, -4.0f); this.CPU1cardpos[i] = new Vector3(12.1f + 0.3f * i, 0.2f + 0.001f * i, 10.0f); this.CPU2cardpos[i] = new Vector3(6.1f + 0.3f * i, 0.2f + 0.001f * i, 10.0f); this.CPU3cardpos[i] = new Vector3(0.1f + 0.3f * i, 0.2f + 0.001f * i, 10.0f); } //配布結果を画面上に表示 SetPlayerCards(this.MYcards,this.MYcardpos,this.mycardnum); SetPlayerCards(this.CPU1cards,this.CPU1cardpos,this.CPU1cardnum); SetPlayerCards(this.CPU2cards,this.CPU2cardpos,this.CPU2cardnum); SetPlayerCards(this.CPU3cards,this.CPU3cardpos,this.CPU3cardnum); for (i = 0; i < 13; i++){ //表向き this.MYcards[i].cardobject.transform.rotation = Quaternion.Euler(0, 0, 0); //裏向き this.CPU1cards[i].cardobject.transform.rotation = Quaternion.Euler(0, 0, 180.0f); this.CPU2cards[i].cardobject.transform.rotation = Quaternion.Euler(0, 0, 180.0f); this.CPU3cards[i].cardobject.transform.rotation = Quaternion.Euler(0, 0, 180.0f); } //以下はStartメソッド外 void SetPlayerCards(List<TrumpCard> PlayerCards,Vector3[] cardpos,GameObject cardnum){ //手札の整列(左に詰める) for (int i = 0; i < PlayerCards.Count; i++){ PlayerCards[i].cardobject.transform.position = cardpos[i]; } //残り枚数表示の更新 cardnum.GetComponent<Text>().text = "残 " + PlayerCards.Count.ToString("D2") + " 枚"; return; } |
ちょっと長いですが、基本同じようなスクリプトを4回ずつ(各プレイヤーごとに)書いているだけですので、スクリプト中にあるコメント文を参考にして、一つ一つ確実に理解していって下さい。
なお、最後に書きましたSetPlayerCardsメソッド(手札の整列&残り枚数の更新)については、今後も含めて呼び出し頻度が高いため、今回は別メソッド化しております。本メソッドは次回以降もよく登場しますので、役割をしっかりおさえておきましょう。
スクリプトを書こう2(開始前に7カード出し)
今回ちょっと記事が長くなりますので、一旦ご休憩を…( ´・ω・)⊃旦
さて次に、Startメソッドの続きとして、開始前に7のカードを出す手続きをスクリプト化していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//Startメソッド前に定義 int[,] setcards = new int[4,15]; //場にカードが出たか(1)まだか(0)次出せる(2) //周期境界…setcards[*,0]=setcards[*,13],setcards[*,14]=setcards[*,1] //setcards[j,i]の初期化 for (j = 0; j < 4; j++){ for (i = 0; i < 15; i++){ this.setcards[j,i] = 0; //場に何も無い=何も出せない(全て0) } } //自分の手札に7があれば先出し for (int i = 0; i < this.MYcards.Count; i++){ if (this.MYcards[i].number == 7){ //カードに「場に出る」指示を与える(cangomoveメソッドは後述) this.MYcards[i].cardobject.GetComponent<eachcard>().cangomove(); //場に出る時は表向き this.MYcards[i].cardobject.transform.rotation = Quaternion.Euler(0, 0, 0); //表向き this.setcards[this.MYcards[i].mark,7]=1; //場にカード出た証 this.MYcards.RemoveAt(i); //注意:RemoveAt(i)により、i番目のカードを取り除いて後ろの要素を詰めたので //次はもう一度i番目を検証しないと飛ばしてしまう i = i - 1; } } //以降、CPU1、CPU2、CPU3に関して同様の手続き(省略) |
本スクリプト中にある変数setcards[j,i]は、各カード(j:マーク、i:数字)が場に出ているか(1)否か(0)次出せるか(2)を記憶させておく変数なので、何も場にカードが出ていない初期状態は全て0ですし、各マークの7が出された後は、setcards[各マーク,7]=1になります。なお、本変数については、i=0~14になっていたり、コメント中に「周期境界」という謎の言葉が書かれていたり、と気になることが色々ありますが、これらが真に効果を発揮するのは次回になりますので、今回は「フーン」で構いません。
各カードに付けるスクリプトを書こう(場にゆっくり移動)
最後に、各カードオブジェクトに付いているスクリプト「eachcard.cs」について紹介します。「eachcard.cs」内では、各カードが手札位置から場に出る挙動をスクリプト化しております。ただ場に出すだけならtransform.positionメソッドでも問題無いのですが、今回は少し工夫してゆっくり場に出る挙動になるよう、Vector3.MoveTowards メソッドをUpdateメソッド中で使ってみます。スクリプトの中身は以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Vector3 targetpos = new Vector3(0, 0, 0); int gomove = 0; // Update is called once per frame void Update () { //移動許可が下りた&まだ場に到着していない場合 if(this.gomove == 1){ if(transform.position != this.targetpos){ //Vector3.MoveTowards(スタート地点,ゴール地点,移動速度) transform.position = Vector3.MoveTowards(transform.position, this.targetpos, 1.0f); } } } public void gettargetpos (Vector3 defaultpos) { //52枚のカードを定義する際についでに本メソッドを呼び出しておく this.targetpos = defaultpos; //場に出る時の自分の行き先をここで記憶 return; } public void cangomove () { this.gomove = 1; //this.targetposへの移動許可 return; } |
監督スクリプト中で各カードのcangomoveメソッドを呼び出せば、そのカードは移動許可が下り、Updateメソッドによりトランプカードが移動し始めます。なお、gettargetpos メソッドを用いて到着地点座標(targetpos)を事前に記憶させておきます。例えば、前回52枚のトランプカードを定義する際にでも、ついでにgettargetposメソッドを呼び出しておけばOKです。
最後に
ちょっと長くなりましたが、ここまでで監督スクリプトのお仕事2つがスクリプトに実装できました。これで、ゲーム開始の準備が整った=Startメソッドの中身を書き上げた、という段階です。次回から、ゲーム開始後の各プレイヤーの挙動について(Updateメソッド中に)スクリプトを書いていきます!次回以降もよろしくお願いします!!