簡単なゲーム作成の第7回目を進めていきます。今回は「カード勝敗判定」を繰り返すために、利用したカードを消していきます。とりあえず、今回で一旦はカードゲーム作成は終了です。
はじめに
今回は第7回目です。第1回目は下記から。
ゲーム作成開始
前回までで、とりあえずの形が出来ました。現状だと一回カードを出して判定したら終わりなので、何度も繰り返しできるように変更していきます。
カードを削除
まずは「場に出して判定が終了したカードを消します」。OperatorのOpenCard内、カードの勝敗判定後にDestCardを追加。

DestCard内で場に出ているカードオブジェクトを削除するのですが、敵の場に出ている対象のカードオブジェクトが分からないので、どのカードが選択されているのかEnemyクラスを下記のように変更。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Enemy : MonoBehaviour { public int intEnemyCardNumber; public int intRamNumber; public List<GameObject> EmCardlist = new List<GameObject>(); public void EnemyCardSelect() { EmCardlist.Clear(); foreach (Transform child in transform) { EmCardlist.Add(child.gameObject); } intRamNumber = Random.Range(0, EmCardlist.Count - 1); EmCardlist[intRamNumber].transform.localPosition = new Vector3(400, -400, 0); intEnemyCardNumber = EmCardlist[intRamNumber].GetComponent<CardScript>().iCardNumber; } }
DestCardを下記のように作成。自分が選んだカードと敵の選んだカード(場に出ているカード)をDestroyしています。

private void DestCard() { GameObject playercardObject = Cards.GetComponent<Cards>().SelectCard; int emlistNum = EmCards.GetComponent<Enemy>().intRamNumber; GameObject enemycardObject = EmCards.GetComponent<Enemy>().EmCardlist[emlistNum]; Destroy(playercardObject); Destroy(enemycardObject); Text txtResult = Result.GetComponent<Text>(); txtResult.text = ""; }
実行してみます。当然ですが、カードが直ぐに消えてしまいます。

DestCardをInvokeで遅延させて実行します。秒数は適当で良いかと。

これで実行。判定結果が出た後に場に出たカードが消えればOK。これで一応、何度か実行できるようになります。
バグ修正:例.カードリストのクリア
とりあえずのゲームの形となりましたが、現状ではバグを含め修正する箇所が山のようにあります。
例えば、敵カードのリストをクリアしていないので、動きがおかしくなる場合があります。下記のようにカードをランダムで選ぶ前にリストクリアを追加。

まだまだ直す部分は多いですが、ここからはゲームの根幹部分というよりはバグ修正や機能追加になるので一旦カードゲーム作成はここまで。最後にここまでのソースをのせておきます。
ソースのまとめ
まずは「カードを配る、判定する」などの役目を持つオペレーター。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Operator : MonoBehaviour { public GameObject CardPrefab; public GameObject Cards; public GameObject EmCards; public GameObject Result; public Sprite[] m_Sprite; private void Start() { //Player dealCards(1, -700, Cards); dealCards(2, -350, Cards); dealCards(2, 0, Cards); dealCards(2, 350, Cards); dealCards(3, 700, Cards); //Enemy dealCards(1, -700, EmCards); dealCards(2, -350, EmCards); dealCards(2, 0, EmCards); dealCards(2, 350, EmCards); dealCards(3, 700, EmCards); } void dealCards(int iNumber,float fPosition,GameObject objParent) { GameObject prefab = (GameObject)Instantiate(CardPrefab); prefab.GetComponent<CardScript>().iCardNumber = iNumber; prefab.transform.SetParent(objParent.transform, false); prefab.transform.localPosition = new Vector3(fPosition, 0, 0); SpriteRenderer m_SpriteRenderer; m_SpriteRenderer = prefab.GetComponent<SpriteRenderer>(); m_SpriteRenderer.sprite = m_Sprite[iNumber - 1]; } public void OpenCard() { EmCards.GetComponent<Enemy>().EnemyCardSelect(); JugeCard(); Invoke("DestCard", 2f); } private void JugeCard() { int myCardNm = Cards.GetComponent<Cards>().intCardNumer; int enCardNm = EmCards.GetComponent<Enemy>().intEnemyCardNumber; Text txtResult = Result.GetComponent<Text>(); //1がグー、2がチョキ、3がパー if ((myCardNm - enCardNm + 3) % 3 == 0) { //引き分け txtResult.text = "DRAW"; } else if ((myCardNm - enCardNm + 3) % 3 == 1) { //負け txtResult.text = "LOSE"; } else { //勝ち txtResult.text = "WIN"; } } private void DestCard() { GameObject playercardObject = Cards.GetComponent<Cards>().SelectCard; int emlistNum = EmCards.GetComponent<Enemy>().intRamNumber; GameObject enemycardObject = EmCards.GetComponent<Enemy>().EmCardlist[emlistNum]; Destroy(playercardObject); Destroy(enemycardObject); Text txtResult = Result.GetComponent<Text>(); txtResult.text = ""; } }
ここで直す必要があるのは、プレイヤーがカードを選択せずにOPENボタンを押した時に「カード選択を促すメッセージを表示」したり、初めのカードを配る部分はループを使ったりでもう少し綺麗にまとめたり。途中の勝敗状況や最終結果なども表示するべきですね。
次が「カードが選択されたとき」のスクリプト
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class CardScript : MonoBehaviour { public int iCardNumber; public void ChoiceCard() { GameObject objCards = this.transform.parent.gameObject; if (objCards.GetComponent<Cards>().SelectCard != null) { objCards.GetComponent<Cards>().SelectCard.GetComponent<Transform>().localPosition = objCards.GetComponent<Cards>().InitPosition; } objCards.GetComponent<Cards>().SelectCard = this.gameObject; objCards.GetComponent<Cards>().InitPosition = this.transform.localPosition; objCards.GetComponent<Cards>().intCardNumer = iCardNumber; this.transform.localPosition = new Vector3(-400, 400, 0); } }
次が「敵のカードを自動で選択する」スクリプト。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Enemy : MonoBehaviour { public int intEnemyCardNumber; public int intRamNumber; public List<GameObject> EmCardlist = new List<GameObject>(); public void EnemyCardSelect() { EmCardlist.Clear(); foreach (Transform child in transform) { EmCardlist.Add(child.gameObject); } intRamNumber = Random.Range(0, EmCardlist.Count - 1); EmCardlist[intRamNumber].transform.localPosition = new Vector3(400, -400, 0); intEnemyCardNumber = EmCardlist[intRamNumber].GetComponent<CardScript>().iCardNumber; } }
次が「プレイヤーのカードを管理」しているCardsクラス。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Cards : MonoBehaviour { public GameObject SelectCard; public Vector3 InitPosition; public int intCardNumer; }
こうしてみると計画性ゼロで作ったので、ぐちゃぐちゃですね。
ゲームを作る前には簡単なクラス図的なのを作って、どこにどんな役割を持たせるのか、どんな感じに切るのか、ある程度考えてから進めた方が良いですね。当たり前ですが(笑)
次にカードゲームを作る機会があればもっと綺麗に分かりやすく、かつ面白いのが作れたら理想だけど、素人なのでいきなりは難しいですかね。