カードゲーム基盤 / 設計

はじめに

ここから一連のページでカードゲームの基盤を作成します。カードを用いた遊びとしてトランプやUNO、トレーディングカードゲームなど様々ありますがそれらに共通する点、カードの位置変更をUnity上で実装します。この作業で完成したパッケージを用いることで、様々なカードゲームの作成が容易になるはずです。

以降のページを読み進める際、特定のカードゲームをターゲットにして作成しているわけではないことに注意してください。あくまでカードオブジェクトの基盤機能を作成することが目標であるため、完成品には何のゲーム性もありません。



設計

まずは最も大切な情報である「どのカードがどこに存在するのか」の表現方法についてです。これは下図の表のように表すことにします。


この表から、オブジェクト番号1,4,6,7,9のカードはデッキに存在することが分かります (他の位置に関しても同様)。ここでオブジェクト番号とは、カードオブジェクト固有の番号のことです。カード生成時に自動で割り振られるため、同じ種類のカードでもインスタンス毎に異なる番号となります。例えばワイルドドロー4が2枚存在していたとしても、両者のオブジェクト番号は異なります。ただし、オンライン対戦で、プレイヤーAの端末のオブジェクト番号とプレイヤーBの端末の番号は完全に一致しています。


このような約束をすることで、お互いの端末の「表」が一致していることを確認するだけでチートをある程度防止することができます。


次にゲームの進行に伴う表の変化についてです。ドローやプレイを行うと、表は次のように変化します。


「番号1」のカードをドローした場合、デッキから1が消える代わりに手札に追加されます。「番号8」をプレイした場合は、手札から8が消えてフィールドに追加されます。実は表の更新はこのような数字の移動のみであり、非常にシンプルです。あえて言うなら、初期化時に必要な「数字の追加」も必要ですが、基本的に使うのは「移動」がほとんどです。よって、カードゲームの核は次の図のようになります。


場面の情報を表現する表、カードの移動を行うMoveCard()メソッド、そしてカードを追加するAddCard()メソッドです。ちなみに引数のindexは、カードを何番目に挿入するかを表す整数です。

以上で、メソッド二つでやりたいことが実現出来てしまうことが分かりました。ただ使い勝手を考えるといまいちです。実際にMoveCard()メソッドを使用する状況を想像してください。第一引数にはオブジェクト番号を渡す必要があるため「動かしたいカードとオブジェクト番号を紐づける何か」が必要となります。必要がある、とは「自前で用意する必要がある」ということです。これは非常に使いにくく、パッケージとしては失格です。これを解決するためCardObjectクラスを定義します。


このクラスには自分のObjectIdを覚えてもらい、かつMoveCard()メソッドを公開してもらいます。メソッド内部では、自身が持っているObjectIdと、引数として受け取って位置情報をもとに、DataManagerMoveCard()メソッドを呼びます。この改良は、オブジェクト番号を指定するという作業を、CardObjectのインスタンスを選択するという作業に変換したことに相当します。同様の変更をAddCard()メソッドでも行いましょう。


Positionクラスを作成しました。これによりAddCard()の引数にposを渡す作業を、Positionクラスのインスタンスを指定する作業に変換しました。

ついでに便利機能を追加します。


CardObjectクラスには、インスタンスがどこに存在するかを取得するPos , Indexを追加しました。そしてPositionには、存在するカード全てを返すCardsと、この位置にさらにカードを追加できるかを判定するCanAddを追加しました (手札の枚数制限などが実装しやすくなります)。



以上で説明が終了です。次回以降もよろしくお願いします。