UnityとPhotonで対戦型ボードゲーム「犬猫将棋」を作成したい(2):カード駒をひっくり返す

犬猫将棋ソースコード、素材、遊べるリンクはこちら

駒ができたところで、駒にスクリプトをアタッチして、裏面の駒、表面の駒、成った状態の駒の三種類を切り替えれるようにしたいと思います。

駒表と成駒にはスプライトの配列を用意してあげて、cardIndexという値を与えてあげることで任意の駒を表示するという仕掛けにしています。ToggleFaceという関数ではShowFaceという 整数の引数をとって、それが0の時は表面、1の時は成った状態、2の時は裏面が表示されるようにします。

これは、以前のポーカーゲームで使っていたスクリプトを流用したものです。KomaModel.csとして前回作った駒にアタッチします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomaModel : MonoBehaviour
{
    SpriteRenderer spriteRenderer;
    
    public Sprite[] faces;  
    public Sprite komaBack;
    public Sprite[] komaNaru;

    public int cardIndex; 
    public int komaBackIndex;

    public void ToggleFace(int showFace) //外部アクセス可能なToggleFaceというメソッドの定義 引数に真偽値としてshowFaceを取る。
    {
        if (showFace == 0) 
        {
            spriteRenderer.sprite = faces[cardIndex]; 
        }
        else
        {
            if (showFace == 1)
            {
                spriteRenderer.sprite = komaNaru[komaBackIndex];
            }
            else
            {
                spriteRenderer.sprite = komaBack; 
            }

        }
    }

    void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }
}
各Face,KomaBack,KomaNaruにスプライトをD&Dする。

次に、マウスのクリックとドラッグで場所を移動できるスクリプトをアタッチします。これも以前のポーカーゲームで使用したスクリプトになります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Mouse : MonoBehaviour
{
    private Vector3 screenPoint;
    private Vector3 offset;

    void OnMouseDown()
    {
            this.screenPoint = Camera.main.WorldToScreenPoint(transform.position);
            this.offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
    }

    void OnMouseDrag()
    {
        Vector3 currentScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
        Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + this.offset;
        transform.position = currentPosition;
    }
}

続いて、カードをひっくり返すアニメーションを作成します。これも以前のポーカーゲームで使用したものをそのまま流用します。詳しい解説はこちらからどうぞ。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CardFlipper : MonoBehaviour
{

    SpriteRenderer spriteRenderer;  
    KomaModel model;  

    public AnimationCurve scaleCurve;  。
    public float duration = 0.5f;   

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();  
        model = GetComponent<KomaModel>(); 
    }

    public void FlipCard(Sprite startImage, Sprite endImage, int cardIndex)  
    {
        StopCoroutine(Flip(startImage, endImage, cardIndex));    
        StartCoroutine(Flip(startImage, endImage, cardIndex));  
    }
    IEnumerator Flip(Sprite startImage, Sprite endImage, int cardIndex)  //コールーチンで動くメソッドFlipの定義。
    {
        spriteRenderer.sprite = startImage;   

        float time = 0f;       
        while (time <= 1f)      // time が1と等しいか小さい場合下記処理を繰り返す
        {
            float scale = scaleCurve.Evaluate(time);    //小数点scale の宣言とtimeに対応するAnimationCurveグラフでのScaleの値の代入。
            time = time + Time.deltaTime / duration;    //time に time+PCの単位時間をdurationで割ったものを代入

            Vector3 localScale = transform.localScale;  //localScaleというVector3の宣言と現在のtransformlocalScaleの値の代入。
            localScale.x = scale;             //localScaleのx成分だけ上で定義したscaleを代入する。
            transform.localScale = localScale;      //現在のtransformにx成分変更後のlocalscaleを代入する。

            if (time >= 0.5f)                     //もしtimeが0.5以上の場合
            {
                spriteRenderer.sprite = endImage;  //次の面をレンダー
            }

            yield return new WaitForFixedUpdate();  // 一定間隔待って次のwhile処理に移ります。
        }
        if (cardIndex == -1)  //もしcardIndex が-1と等しい場合
        {
            model.ToggleFace(1); //裏面をレンダーします
        }
        else    //それ以外の場合は
        {
            model.cardIndex = cardIndex;  //  modelのカードインデックスの値をcardIndex とし、
            model.ToggleFace(0);  // 表面をレンダーします
        }
    }
}

インスペクター上でアニメーションカーブを下記のように変更します。これによって滑らかにカードフリップのアニメーションが実行されるようになります。

真ん中で右クリックAddKeyを押す
0.0のところまで下に引っ張る。

それから、マウスオーバーで自分の駒を確認できるように、スクリプトを追加します。 これも以前のポーカーゲームで使用したスクリプトの流用です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class MouseOverAlways : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    CardFlipper flipper;
    KomaModel cardModel;
  
    private void Awake()
    {
        flipper = GetComponent<CardFlipper>();
        cardModel = GetComponent<KomaModel>();
    }

    // オブジェクトの範囲内にマウスポインタが入った際に呼び出されます。
    public void OnPointerEnter(PointerEventData eventData)
    {
         cardModel.ToggleFace(0);
              
    }

    // オブジェクトの範囲内からマウスポインタが出た際に呼び出されます。
    public void OnPointerExit(PointerEventData eventData)
    {
          flipper.FlipCard(cardModel.faces[cardModel.cardIndex], cardModel.komaBack, -1);
    }
}

この時、UI>EventSystemをヒエラルキーに追加します。

忘れずにイベントシステムを追加します。

それからメインカメラには2D Raycasterを追加します。

最後に、ダブルクリックで駒を裏返せるようにするスクリプトをアタッチします。ダブルクリックの数を数えてあげて、それが3で割った時の余りが幾つかで表示する面を変えるということをしています。これは後々Photonを使用するときにClickNumという値を渡してあげて、対戦相手に対しても同様の面が見えるように工夫しています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class DoubleClick : MonoBehaviour, IPointerClickHandler
{
    KomaModel cardmodel;
    public int clickNum = 0; //外部参照用のクリック数の宣言
    private int i = 0;

    void Awake()
    {
        cardmodel = GetComponent<KomaModel>();
    }

   public void OnPointerClick(PointerEventData eventData)
   {

        if (eventData.clickCount > 1)
        {
            i++;
            if (i % 3 == 1)
            {
                Debug.Log(eventData.clickCount);
                clickNum = i; //外部参照用のクリック数(PlayerNetwrokMoverで取得する)
                cardmodel.ToggleFace(0);
                GetComponent<MouseOverAlways>().enabled = false;
            }
            else if (i % 3 == 2)
            {
                Debug.Log(eventData.clickCount);
                clickNum = i; 
                cardmodel.ToggleFace(2);
                GetComponent<MouseOverAlways>().enabled = false;
            }
            else
            {
                Debug.Log(eventData.clickCount);
                clickNum = i;
                cardmodel.ToggleFace(1);
                GetComponent<MouseOverAlways>().enabled = true;
            }
        }
    }
}

これで、 駒の移動、駒のマウスオーバー、ダブルクリックが出来るようになりました。次回は盤面を加えてPhotonを使用し対戦の準備を整えたいと思います。

おすすめの記事