ゲームクラス設計


GUI型ゲームのクラス設計ってどうやればいいんだろう.

ってよく考えるけど,いいのが思いつかない….


#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

const unsigned SCREEN_TITLE = 0x0000;
const unsigned SCREEN_MENU  = 0x0001;

enum message {
  msg_null,
  msg_change_screen
};

// 各スクリーンクラス間で共有するデータ
struct common_data_set {
  // ...
};

// 画面インターフェイスクラス
struct base_screen {
  virtual ~base_screen() throw();
  virtual message draw() const = 0; // 描画
  virtual unsigned msg_data() const = 0; // メッセージのデータ

  // callback関数
  virtual void key_down(char key_code) const = 0;
  virtual void mouse_move(int x, int y) const{}

  // データ共有
  virtual void common_data(const common_data_set& data) = 0;
  virtual const common_data_set common_data() const = 0;

};


// タイトルスクリーン
struct title_screen : base_screen {
  ~tite_screen() throw(){}

  message draw() const{}
  // ...
};

// メニュースクリーン
struct menu_screen : base_screen {
  // ...
};



// ゲーム全体管理クラス
struct game_system {

  bool init(); // 初期化
  int main_loop(); // メインループ

private:
  // 各スクリーンクラス
  std::map<unsigned, boost::shared_ptr<base_screen> > screens_;
  // 今表示しているスクリーンへの弱参照
  boost::weak_ptr<base_screen> now_scr_;

};


int main(){

  game_system sys;
  if(!sys.init())
    return 1;

  return sys.main_loop();

}


// ここから本題

bool game_system::init(){

  boost::shared_ptr<base_screen> ptr;

  // 各スクリーンクラス生成
  ptr.reset(new title_screen);
  screens_[SCREEN_TITLE] = ptr;
  ptr.reset(new menu_screen);
  screens_[SCREEN_MENU] = ptr;

  now_scr_ = ptr[SCREEN_TITLE]; // デフォルトをtitleに

  return true;
}


int game_system::main_loop(){

  message msg = msg_null;
  unsigned msg_data = 0;
  common_data_set data_tmp;

  for(;;){

    if(boost::shared_ptr<base_screen> ptr = now_scr_.lock()){

      msg = ptr->draw();
      if(msg != msg_null)
        msg_data = ptr->msg_data();

    }else
      throw "screen not found";

    switch(msg){
      case msg_change_screen:

        if(boost::shared_ptr<base_screen> ptr = now_scr_.lock()
          data_tmp = ptr->common_data(); // 共有データを受け取る

        now_scr_ = screens_[msg_data]; // スクリーン変更

        if(boost::shared_ptr<base_screen> ptr = now_scr_.lock()
          ptr->common_data(data_tmp); // 共有データを新しいスクリーンクラスに渡す

        msg = msg_null;
        break;
    }

  }

}


今やってるのはこんな感じ.


別にweak_ptr<>にする必要はないのかな.


データ共有のとこはshared_ptr<>にすればいいのか.

結構無駄がありそう….