AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

カードゲームを作ろう(8)

 #7から一年以上経ってますね(´・ω・`)
 というわけでひさしぶりにカードゲームを作ろうの続編です。
 Projectが壊れてプログラムはすべて喪失しましたので、いちから作り直しです(´・ω・`)
 1年経ってますのでUnityの知識も少しは増えてるはずなんで、そのへんを活かして行きましょう。
 カードゲームと麻雀を共用コードで作ってみようと思います。

 まずは、52枚をシャッフルして4人に5枚づつ配ります。
f:id:yasu9780:20161020170025g:plain

 裏面を非表示にするとすべてのカードが見えます。デバッグではまずはこっちで開発を進めたほうがいいですね。
f:id:yasu9780:20161020170105g:plain


 cardNo配列に場のカード番号が格納されていて、myCardNo配列に持っているカードの番号が格納されています。

 card配列は52枚のカードの実態を指します(gameObject)
 なので、card[ cardNo[ index] ]が、場のカードの実態を指します。
 同様に、card[ myCardNo[ index] ]が、手札のカードの実態を指します。

 カードを配るとは、場のカードの実態を、手札のカードの位置に移動させること。カードの実態が場から手札に移動して、cardNo配列の値がmyCardNo配列に代入されます。
 最大で手札は13枚配ることを想定して、 myCardNo[playerNo * 13 + no]とアクセスすると、任意のプレイヤーの手札が引けます。
 全体はstate変数のステートマシンで、まず配り、終わったら捨てるという状態変化で定義します。
 場は後入れ先出しLIFOのスタックみたいなもんですね。baTop変数はスタック変数みたいなもんです。

    void Update () {
        if(state==0) // deliver
        {
            if(playerNo>=4) {
                playerNo = 0;no = 0;state = 1;return;
            }
            if (no >= deliverMax) { playerNo++; no = 0; return; }
            card[cardNo[baTop]].transform.rotation = Quaternion.Slerp(card[cardNo[baTop]].transform.rotation,
                myCard[playerNo*13+no].transform.rotation, Time.deltaTime * speed);
            card[cardNo[baTop]].transform.position = Vector3.Slerp(card[cardNo[baTop]].transform.position,
                myCard[playerNo * 13 + no].transform.position + Vector3.up * no * cardAtumi, Time.deltaTime * speed);
            if (Vector3.Distance(card[cardNo[baTop]].transform.position, myCard[playerNo * 13 + no].transform.position + Vector3.up * no * cardAtumi ) < 0.01f)
            {
                myCardNo[playerNo * 13 + no] = cardNo[baTop];
                no++; baTop--;
            }
        }
        if (state == 1) // drop
        {
            if (playerNo >=4) { playerNo = 0; no = 0; state = 2; return; }
            if (no >= deliverMax) { playerNo++;no=0; return; }
            if(myCardNo[playerNo * 13 + no]==-1) { no++;return; }
            card[ myCardNo[playerNo * 13 + no] ].transform.rotation = Quaternion.Slerp(card[myCardNo[playerNo * 13 + no] ].transform.rotation,
                ba.transform.rotation, Time.deltaTime * speed);
            card[myCardNo[playerNo * 13 + no] ].transform.position = Vector3.Slerp(card[myCardNo[playerNo * 13 + no] ].transform.position,
                ba.transform.position + Vector3.up * baTop * cardAtumi, Time.deltaTime * speed);
            if (Vector3.Distance(card[myCardNo[playerNo * 13 + no]].transform.position , ba.transform.position + Vector3.up * baTop * cardAtumi ) < 0.01f)
            {
                baTop++;
                cardNo[baTop] = myCardNo[playerNo * 13 + no];
                myCardNo[playerNo * 13 + no] = -1;
                no++;
            }
        }

 あと、これは以前も出た現象ですが、カードの重なりを座標をすこしづらして表現してるのですが、この座標の写像がおかしくなる場合がありました。
 sceneでは問題ないのにGameSceneでおかしくなります。奥行きが変になる。
 カメラの問題なのか、ProjectionがOrthGraphicだと問題が出ません。なので、Perspectiveですが、Field of Viewを12にしたら問題が出なくなりました。
 カメラが広角気味だと微小な奥行き座標の射影がおかしくなるのかもしれません。原因は不明です。

f:id:yasu9780:20161020195157p:plain
上がsceneで、下がgame画面。ダイヤの7は、手札で一番手前にあるはずなのに、なぜかゲーム画面ではクローバーの4の後ろに描画されている。
 捨て札なんかも重なりが全然めちゃくちゃに描画されるので、最後にすてた札がわからなくなる。
 こんな基本的なところでなんで動作がおかしいんだろ?

 おそらく解決した。
 一枚カードを捨てるたびに、捨てたカードを全部postionを再代入すると正しい重なりで表示された。
 Objectが重なってるところに別のobjectを移動させた場合に、重なってないとみなして高速化のために再表示しない仕組みがおかしいんではないだろうか?
 個人的にはUnityのbugだと思うけど、どうだろうか?
 

 unityちゃんとAliciaちゃんを置いてみた。
f:id:yasu9780:20161020212454g:plain