ブラックジャックの作り方3 トランプの山札・カードを引く処理を作る

Unity カードゲームの作り方


Unityの本格ゲーム制作講座はこちら
【30日間の全額返金保証付き】

前回の記事でシーンに必要なものが配置できました。

前回の記事:

ブラックジャックの作り方2 ディーラーとプレイヤーのフィールドとUIを作る
前回の記事ではカードオブジェクトの作成を行い、数字や絵柄が書かれたカードの作り方を習得しましたね。 前回の記事: 今回の記事では、ディーラーやプレイヤーのカードフィールドを作成していきます。場のカード枚数が変わっても、対応できるよう...

で、今回の記事ではトランプのカードを配れるように山札を作り、カードを引く処理を作っていきます。

ここまでできるとデッキからカードを引いて戦うようなゲームの基本部分も作れるようになりますね。


【Unity入門の森の最新ゲーム開発講座もお届け】

まずはシーンを管理するSceneManagerを作ろう!

先にシーンを管理するゲームオブジェクトを作成します。

シーンに空のGameObjectを作成し、名前を「SceneManager」にしてください。

次にスクリプトをファイル名を「SceneManager」として作成してゲームオブジェクトにアタッチしておきましょう。

この段階ではスクリプトはいじらなくてOKです。

これから機能を順に追加していきます。

カード用のコンポーネントを作ろう!

今回の記事ではカードを配れるようにしていきますが、まずカードを表すスクリプトを作成しましょう!

スクリプトを新しく作成してください。ファイル名は「Card」として作成します。

作成したスクリプトは「Card」プレハブにコンポーネントとしてアタッチしてください。

Cardコンポーネントには次のメンバを定義しています。

  • IsReverseフィールド:裏向きかどうか?
  • Numberフィールド:トランプの数字。
  • Markフィールド:トランプのマーク。
  • SetCardメソッド:カードの内容を設定するメソッド

トランプの数字はNumberフィールドで表しています。

注意点としてトランプのAは1として、Jack,Queen,Kingはそれぞれ11,12,13として表現しています。

コンポーネントのフィールドが変更されたらプレハブの内容も変更するようにする

このままだとCardコンポーネントのフィールドをInspectorから変更しても「Card」プレハブの見た目は変更されません。

なので、Cardコンポーネントを修正し、プレハブのGameObjectの親子階層を調べてコンポーネントから設定できるようにしましょう!

少し長いコードになってしまいましたが、SetCardメソッドでは次の3つのことを行なっています。

  • IsReverseの値を見て「Card」プレハブの背景色を変更し、子GameObjectをアクティブ・非アクティブ化している。
  • CurrentMarkの値を見て「 Card」プレハブの「Mark」のテキストと色を変更している。
  • Numberの値を見て「Card」プレハブの「NumberText」のテキストを変更している。

また、次のGameObject及びTransformのメンバを使用して「Card」プレハブのGameObjectにアクセスしています。

  • GameObject.GetComponent<T>()メソッド: T型のコンポーネントをGameObjectから取得する
  • Transform.FInd(string)メソッド:引数に渡した名前の子GameObjectを検索し取得する。

ここまでできたら、Cardコンポーネントのパラメータに合わせてプレハブの内容も変更されるようになっています。

コンポーネントは再生しないと実行されないですが、毎回再生するのもめんどうなので、OnValidateメソッドを追加し、Inspectorから入力した時でもプレハブに入力内容が適応されるようにしましょう!

トランプ山札を実装しよう カードの初期化・生成・山札を切る処理

カードの実装もできたので、次はカードを配れるようにするためシーンに山札を追加したいと思います。

ただし実際に山札をシーンに配置するのではなくて、SceneManagerコンポーネントの中のメンバフィールドとして用意します。

そのため画面からは内容を確認できないので注意してください。

それではトランプのカードをデータとして表現するために先にCardコンポーネントにDataクラスを追加します。

DataクラスはCardコンポーネント以外でカードを扱うためのクラスになります。

このクラスのリストをSceneManagerに追加することで山札を表現します。

上のサンプルコードでは次のことを行なっています。ループ文や乱数などが入り、少し複雑なコードになっていますが、頑張って実装してください。

  • AwakeメソッドでInitCardsメソッドを呼び出し山札を初期化している。
  • InitCardsメソッドではCard.Dataクラスをトランプの枚数分だけ作成している。
  • InitCardsメソッドの最後でShuffleCardsメソッドを呼び出し作成したカードの順番を適当にシャッフルしている。
  • ShuffleCardsメソッドでは乱数を表すSystem.Randomクラスを使用し、ShuffleCountフィールドに設定した回数分cardsフィールドの要素の順番を一枚づつ入れ替えている

ShuffleCardsメソッドのループ分にあるカードの位置を入れ替えるというコメントの部分で実際に山札のカードを入れ替えています。

その部分のコードは2つの変数の値を入れ替える処理になっています。

入れ替えの時に変数が2つだけだとどちらかが上書きされてしまい入れ替えできないので、tmp変数を新しく用意し、片方の変数の値を記録しているのに注目してください。

乱数の使い方

C#において乱数を使用する際はSystem.Randomクラスを使うのが一番簡単です。

System.Randomクラスの使い方は次のサンプルコードのようなものになります。

一般的なプログラミングおよびコンピュータの世界において完璧な乱数を作ることはできません。

そのため数値の計算を工夫した擬似的な乱数が使用されています。

上のサンプルコードの下にあるコードではSystem.Randomクラスのコンストラクタにシード値を渡していますが、それは擬似的な乱数を計算する上での初期値を渡すことになります。

擬似的な乱数はあくまで1+1みたいな普通の数値計算を行なっているため、System.Randomクラスの内部のデータが同じならSystem.Random.Nextメソッドが返す値は同じになってしまいます(乱数の種となるシード値は有限の数であるため、真の乱数は作れない)。

C#ではシード値を渡さなければ、毎回異なるシード値が使用されるのでそこまで気にしなくてもいいようになっています。

が、擬似的な乱数ということを覚えておくと乱数を多用した際に同じような数値が出てきても慌てずに済みます。

(C#の標準ライブラリより精度の高い乱数生成器なども存在します。メルセンヌツイスタなどが有名どころで、もし乱数のパターン化を避けたい場合にはこうした上質な乱数生成器を利用しましょう)

トランプのカードを配る処理を実装する

それでは山札をSceneManagerに組み込みましたので、ひとまず簡単にシーン上にあるディーラーとプレイヤーにカードを渡してみましょう!

こちらもSceneManagerコンポーネントに処理を追加します。

上のサンプルコードでは次のものをSceneManagerコンポーネントに追加しています。

  • 「Card」プレハブを表すフィールド
  • ディーラーのカードのルートGameObjectを表すフィールド
  • プレイヤーのカードのルートGameObjectを表すフィールド
  • カードを一枚配るDealCardメソッド
  • カードをシーン全体に配るDealCardsメソッド

フィールドを追加しているのでシーンにあるSceneManagerコンポーネントに忘れずアタッチするようにしてください。

  • CardPrefab:「Card」プレハブ
  • Dealer:シーンの「Dealer」GameObject
  • Player:シーンの「Player」GameObject

また、動作確認用にUpdateメソッドの中でスペースキーを押すとDealCardsメソッドを呼び出すようにしています。

この処理は動作確認用なため後々Updateメソッドごと削除します。

注意点として、ボタンを押し続けていくと山札のカードがなくなってDealCardメソッドがnullを返すようになってしまいます。

そうなるとサンプルコードではnullデータに対応していないので例外が発生してしまいます。

実際のブラックジャックではそこまでカードを引くことはないのでこの講座では問題が出るまでこのまま進めていきます。

ここまでできたら、山札からカードをシーン上に配れる状態になっているはずです。

スクリプト上からプレハブを複製する方法

DealCardsメソッドの中で「Card」プレハブを複製しています。

スクリプト上でプレハブを複製するにはUnityEngine.Object.Instantiateメソッドを使用します。

UnityEngine.Object.Instantiateメソッドにはいくつかメソッドのオーバーロードが用意されています。

この記事では複製するプレハブと複製した際の親にするGameObjectを指定するものを使用しています。

まとめ

今回の記事でトランプのカードを表すプレハブとそれを制御するコンポーネントを追加しました。

また、まだ仮ではありますがシーンにカードを配れるようにもしました。

今回の記事をまとめると次のようになります。

  • Transform.Findメソッドを使用すると子GameObjectを名前で検索できる。
  • 乱数を扱うにはSystem.Randomクラスを使用する。
  • プログラミング上の乱数は擬似的なものなので、内部データによっては同じ値を返すこともある。
  • スクリプト上でプレハブを複製するときはUnityEngine.Object.Instantiateメソッドを使用する。

それでは次の記事に行ってみましょう!

次回の記事:

ブラックジャックの作り方4 ゲームシステムとbet(賭け金)システムを作る
前回の記事でカードを配れるようになりました! 前回の記事: 今回の記事では実際にブラックジャックのゲームの流れを作っていきましょう! 賭け金を決めてベットする処理やコルーチンを用いたゲームの管理システムを構築していきます。 ブラ...

Unityカードゲーム開発講座へ戻る>>

参考用:スクリプトの完成図

ちなみに今回の記事で作成したスクリプトの最終的な内容は次のものになります。

Unityカードゲーム開発講座へ戻る>>


【Unity入門の森の最新ゲーム開発講座もお届け】

コメント

タイトルとURLをコピーしました