【Unity ゲーム制作】神経衰弱ゲームを作ろう!〜その10 (Enumを使ってゲームの進行を管理しよう!)
スポンサーリンク
前回は、タイマー機能を追加しました。
今回は「Enum」を使用してゲームの進行 ( ステート ) を管理したいと思います、。
1. カードの種類を増やそう
まずは神経衰弱で使うカードを増やしましょう。
現時点では12枚のカードが表示されていると思うので、新たに「3つ」の新規カードを導入します。
今回は「いらすとや」さんにて、フリー画像を拝借しました。
その後、「CardCreateManager.cs」を以下のように変更します。
// Resources/Imageフォルダ内にある画像を取得する imgList.Add (Resources.Load<Sprite> ("Image/card_image_000")); imgList.Add (Resources.Load<Sprite> ("Image/card_image_001")); imgList.Add (Resources.Load<Sprite> ("Image/card_image_002")); imgList.Add (Resources.Load<Sprite> ("Image/card_image_003")); imgList.Add (Resources.Load<Sprite> ("Image/card_image_004")); imgList.Add (Resources.Load<Sprite> ("Image/card_image_005")); // forを回す回数を取得する int loopCnt = imgList.Count; for (int i = 0; i < loopCnt; i++) { // カード情報を生成する CardData cardata = new CardData (i, imgList[i]); cardDataList.Add (cardata); } this.mIndex = 0; this.mHelgthIdx = 0; this.mWidthIdx = 0; // 生成したカードリスト2つ分のリストを生成する List<CardData> SumCardDataList = new List<CardData> (); SumCardDataList.AddRange (cardDataList);
読み込むカードの種類を増やしました。
では、次はゲーム進行部分を作成したいと思います。
2 . Enum で 「EGameState」を作成する
新規で「EGameState.cs」を作成します
/// <summary> /// ゲームの進行ステート /// </summary> public enum EGameState { START = 0, READY = 1, GAME = 2, RESULT = 3 }
今回は enum を使用しました。
enum は「列挙型」と呼ばれるもので、状態管理などで使用されます。
それでは、作成した EGameState をゲームロジックに組み合わせましょう。
3 . GameSceneManager .cs でゲームステート関数を作成する
まずは「GameSceneManager.cs 」にEGameState の変数を追加します。
public class GameSceneManager : MonoBehaviour { // 一致したカードIDリスト private List<int> mContainCardIdList = new List<int> (); // カード生成マネージャクラス public CardCreateManager CardCreate; // 時間管理クラス public TimerManager timerManager; // 経過時間 private float mElapsedTime; // ゲームステート管理 private EGameState mEGameState;
そして、Start関数で初期化しましょう。
void Start () { // 一致したカードIDリストを初期化 this.mContainCardIdList.Clear (); // カードリストを生成する this.CardCreate.CreateCard (); // 時間を初期化 this.mElapsedTime = 0f; // ゲームステートを初期化 this.mEGameState = EGameState.START; }
そして、「ゲームのステートによって処理を振り分ける関数」を作成します。
/// <summary> /// ゲームステートで処理を変更する /// </summary> private void mSetGameState () { switch (this.mEGameState) { // スタート画面 case EGameState.START: break; // ゲーム準備期間 case EGameState.READY: break; // ゲーム中 case EGameState.GAME: break; // 結果画面 case EGameState.RESULT: break; } }
内容はEnum ( 列挙型 ) のEGameState をSwitch文で切り分けます。
先ほどのStart関数にmSetGameState を宣言しましょう。
void Start () { // 一致したカードIDリストを初期化 this.mContainCardIdList.Clear (); // カードリストを生成する this.CardCreate.CreateCard (); // 時間を初期化 this.mElapsedTime = 0f; // ゲームステートを初期化 this.mEGameState = EGameState.START; // ゲームのステート管理 this.mSetGameState (); }
それでは、mSetGameState 関数の Switch文に処理を追加していきましょう。
4. ゲームの準備ステート用の関数を作成し、mSetGameStateに追加する
今回は、「ゲームの準備ステート」から作成していきます。
まずは 「mSetGameReady」関数を作成し、今までStart 関数で初期化していた部分をこの関数の中に移しましょう。
/// <summary> /// ゲームの準備ステートを開始する /// </summary> private void mSetGameReady () { // 一致したカードIDリストを初期化 this.mContainCardIdList.Clear (); // カードリストを生成する this.CardCreate.CreateCard (); // 時間を初期化 this.mElapsedTime = 0f; }
そしてこの関数をmSetGameState の EGameState.Ready のswitch文に宣言します。
/// <summary> /// ゲームステートで処理を変更する /// </summary> private void mSetGameState () { switch (this.mEGameState) { // スタート画面 case EGameState.START: break; // ゲーム準備期間 case EGameState.READY: // ゲームの準備ステートを開始する this.mSetGameReady (); break; // ゲーム中 case EGameState.GAME: break; // 結果画面 case EGameState.RESULT: break; } }
これを行うことで、今までStart関数で行なっていた初期化処理を、EGameState が READY になった時に行えるようになりました。
次にStart関数で初期化していたmEGameState の初期化を「Start」から「Ready」に変更しましょう。
void Start () { // ゲームステートを初期化 this.mEGameState = EGameState.READY; // ゲームのステート管理 this.mSetGameState (); }
Start関数がサッパリしたと思います。
次は、EGameStateが 「Game」の時の処理を実装しましょう
5. UpdateにEGameState が GAME の時のみ、処理を実行するように変更しよう!
では、Update 関数に 「ゲームステートが GAME の状態の時のみ、カードの判別処理を実装する」処理を実装しましょう。
void Update () { // GameState が GAME状態なら if (this.mEGameState == EGameState.GAME) { this.mElapsedTime += Time.deltaTime; this.timerManager.SetText ((int) this.mElapsedTime); // 選択したカードが2枚以上になったら if (GameStateController.Instance.SelectedCardIdList.Count >= 2) { // 最初に選択したCardIDを取得する int selectedId = GameStateController.Instance.SelectedCardIdList[0]; // 2枚目にあったカードと一緒だったら if (selectedId == GameStateController.Instance.SelectedCardIdList[1]) { Debug.Log ($"Contains! {selectedId}"); // 一致したカードIDを保存する this.mContainCardIdList.Add (selectedId); } // カードの表示切り替えを行う this.CardCreate.HideCardList (this.mContainCardIdList); // 選択したカードリストを初期化する GameStateController.Instance.SelectedCardIdList.Clear (); } } }
これで、GAMEステートの時 ( ゲーム中 )のみ、タイマーが加算され、カード処理が実装されるようになりました。
最後にREADYの処理が完了したら、GameStateをGAME に変更する処理を実装しましょう。
まずはCardCreateManager.csにカードのアニメーションが終了した時に呼ぶコールバック関数を作成しましょう。
public class CardCreateManager : MonoBehaviour { // 生成するCardオブジェクト public Card CardPrefab; // 「カード」を生成する親オブジェクト public RectTransform CardCreateParent; // 生成したカードオブジェクトを保存する public List<Card> CardList = new List<Card> (); // カード情報の順位をランダムに変更したリスト private List<CardData> mRandomCardDataList = new List<CardData> (); // GridLayoutGroup public GridLayoutGroup GridLayout; // カードの生成アニメーションが終わった時 public Action OnCardAnimeComp;
そして、「mSetDealCardAnime」関数のアニメーションが終了した処理部分に、コールバックが呼ばれる処理を追加しましょう。
// DOAnchorPosでアニメーションを行う card.mRt.DOAnchorPos (new Vector2 (posX, posY), this.DEAL_CAED_TIME) // アニメーションが終了したら .OnComplete (() => { // 生成したカードオブジェクトを保存する this.CardList.Add (card); // 生成するカードデータリストのインデックスを更新 this.mIndex++; this.mWidthIdx++; // 生成インデックスがリストの最大値を迎えたら if (this.mIndex >= this.mRandomCardDataList.Count) { // GridLayoutを有効にし、生成処理を終了する this.GridLayout.enabled = true; // アニメーション終了時の関数を宣言する if (this.OnCardAnimeComp != null) { this.OnCardAnimeComp (); } }
そして、Ready の準備関数に「カード配布アニメーションが終了した時のコールバック処理」を作成しましょう。
private void mSetGameReady () { // カード配布アニメーションが終了した後のコールバック処理を実装する this.CardCreate.OnCardAnimeComp = null; this.CardCreate.OnCardAnimeComp = () => { // ゲームステートをGAME状態に変更する this.mEGameState = EGameState.GAME; this.mSetGameState (); }; // 一致したカードIDリストを初期化 this.mContainCardIdList.Clear (); // カードリストを生成する this.CardCreate.CreateCard (); // 時間を初期化 this.mElapsedTime = 0f; }
ここまで出来たら UnityでGameを実行してみましょう。
カードの配布アニメーションが終了してからタイマーが起動したら成功です!