ページ 11

ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 17:54
by かわ
現在DXライブラリでボードゲームを製作しています。

マスに配置できる様々なオブジェクトがあるのですが、
その種類によって持つデータが違い、それをプログラムに実装する方法が分かりません。

オブジェクトが持つデータというのは、
宝箱なら入っているアイテムのID、
爆弾なら爆発するまでの時間
壁ならデータを持たない
などです。

今までは全てのマス(12×12程度)に
・オブジェクトの種類(無しも含む)
・宝箱用のアイテムID
・爆弾用のint型データ
・その他のオブジェクトに必要なデータ
など全てのデータを持たせていました。
ですが、明らかに優れた方法ではないので、より良い方法をご存知なら教えてください。

また、以前のトピックで、RPGのマップデータ作成にPlatinumなどのマップエディタが良いとありましたが、
フィールドが限定されているボードゲームなどにも有用なのでしょうか?

C++はポリモーフィズム、STLなどなら出来ます。
長文失礼しました。よろしくお願いします。

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 18:16
by usao
よくわからないけど
例えば,すごろくみたいなのでキャラクタ(?)がマスに止まった際の処理が
そのマスに存在するオブジェクトによって異なるみたいな話であれば…

コード:

class IEventObject
{
public:
  virtual ~IEventObject();
  virtual void OnCharactorStop( CPlayer & ) = 0;  //止まったときの処理
};

class CTreasureBoxEvent : public IEventObject
{
public:
  virtual void OnCharactorStop( CPlayer &rPlayer )
  {  rPlayerがm_ItemIDで表されるアイテムを獲得;  }
  
private:
  unsigned int m_ItemID;
};
…とか?

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 20:04
by softya(ソフト屋)
>また、以前のトピックで、RPGのマップデータ作成にPlatinumなどのマップエディタが良いとありましたが、
>フィールドが限定されているボードゲームなどにも有用なのでしょうか?

使えるとは思います。試すのは簡単ですので、試してみて使えそうなら採用されてはどうでしょうか?
マップ(絵)レイヤとマスやアクションマスは別レイヤになると思います。

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 20:39
by かわ
皆さん返信ありがとうございます。

>usaoさん
IEventObject 型のポインタを各マスに持たせて、
そのマスのオブジェクトに対応した子クラスのOnCharactorStop関数を呼び出す・・・(文章が下手ですみません)
という解釈でいいんでしょうか?

今まではフィールドとキャラクターはただのデータで、それらのデータをメンバとして管理クラスに持たせ、データ操作を行っていました。

コード:

class GameManager
{
private:
  Field m_fieldData[12][12];//全てのマスのデータ
  Character m_character[4];//4人のプレイヤーのデータ(持っているアイテムなど)

public:
  void SetBomb( int x, int y );//データ操作関数
  //省略
}
の様な感じです。
Field クラスは最初の投稿で述べたようなデータの集合です。
このようなやり方では、オブジェクトの種類毎に違うデータを違和感無く持たせることは難しいでしょうか?


>softyaさん
分かりました。
とりあえず試してみます。

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 21:44
by みけCAT
かわさんが「違和感無く」と思うかはわかりませんが、共用体を利用するのはどうでしょうか?

コード:

struct TreasureInfo {
    // 略
};

struct BombInfo {
    // 略
};

enum FieldType {
    FIELD_TREASURE,
    FIELD_BOMB,
    FIELD_WALL
};

struct Field {
    FieldType type;
    union {
        TreasureInfo ti;
        BombInfo bi;
    } info;
};
[search=google]共用体 C言語[/search]

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 22:23
by かわ
>みけCATさん
共用体ってこういう風に使えるんですね!
これで実装を試してみます。

皆さん教えてくださって本当にありがとうございました。

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 22:34
by milfeulle
usaoさんの例はまさしくポリモーフィズムです。オブジェクトの種類によらず共通するデータ構造や共通する処理をまとめた抽象クラスを定義し、それを継承して実装しています。(usaoさんのは、イベントの実行に着目したインターフェイスかもしれません)

似ていない種類のものを一緒にしようとすると、共通の判断基準を設ける必要があります。例えば宝箱のマスと壁のマスには共通点がありません。マスに必ず移動できるならまだしも、壁には移動できないのですよね? この判定は移動するところで、プレイヤーが移動可能かどうかをオブジェクトに問いたださないといけません。そこでOnCharactorStopだけでなく、canEnterなど判定用のメソッドを用意したりします。これは便利ですね。1つのマスにあるイベントに「ここに移動できますか?」「ここに止まったら何か効果はありますか?」と常にきけばいいだけですからね!
オフトピック
爆弾を踏んだらその周囲のプレイヤーに影響が出ると仮定したら、クラス構成を変える必要が出てきますね。イベントはそのマスのプレイヤーに対して何かするだけではなく、周囲のマスにイベントが起こったことを通知しなければなりません。通知を受けたマスは該当プレイヤーがいれば何か対処をします。(妄想)
オフトピック
そもそも壁はイベントだろうかとか、プレイヤーの行動やステータス等の変化など様々な側面を洗い出して、適切なクラス構成を考える必要があるとは思います。
実際には、usaoさんの例を用いますと、IEventObject&(やIEventObject*)をFieldのメンバにします。となると、実態をどこかに確保しなければなりません。
オフトピック
おそらく可変個にするとおもうのでnewするかと思います。予め全ての種類とその個数が分かっているなら、std::vectorなりで連続したイベントオブジェクトを確保して、それらの参照(やポインタ)をFiledのメンバに入れればいいと思います。
今回の場合は実行効率を考える必要はないと思いますが、仮想関数を使ったりポインタを使ったりしてメモリも速度も微妙ですが、全てをオブジェクトにするという、オブジェクト指向にこだわるなら現状の情報ではこのようにするのがいいと思います。

オブジェクト指向こそが最強で崇高で唯一神というわけではないので、みけCAT さんのようにデータを詰めて省メモリの点で違和感をなくされてもいいですし、上記のようにオブジェクトとして違和感なく扱ってもいいですし、両者のいいとこ取りをしてもいいと思います。

―― 書いている途中で解決されたみたいですね;;すみません

Re: ボードゲームの一部のマスにデータを持たせる

Posted: 2014年2月25日(火) 23:46
by かわ
>milfeulleさん
非常に分かりやすく説明していただきありがとうございます!
多くの実現方法からどれを取捨選択するかの選択は私にはまだ難しいですが、
それぞれの方法のメリットなどを実際に確かめてみようかと思います。