スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

std::list と boost::shared_ptr を使った弾生成、弾管理クラス

Twitter でぶつぶつ独り言のようにつぶやいてた部分について一旦まとまったので記事にしてみました。
なんてことない記事なのですが、いつものメモ代わりもこめて。

今回はシューティングを作成していることもあって、弾の生成、弾の管理についてまとめていきます。

- 弾の管理は std::list を使ってリストで管理
- 弾は動的に生成するため、スマートポインタの boost::shared_ptr を使ってみました
(C++11 の std::shared_ptr も代用はきくと思いますが、詳しくしは知りません)

弾のベースクラスを作成しよう
何はともあれ弾のメインとなる情報を持ったベースクラスを作成しました。


// 弾ベースクラス
class CBulletBase
{
public:
virtual void update() { std::cout << "CBulletBase::update()\n"; }

CBulletBase() { };
virtual ~CBulletBase() {};
};

ベースクラスから派生しよう
このクラスを派生し、自機狙いや円形弾など固有の動きをするクラスを作成してみました。



// 自機狙い弾クラス
class CBulletAiming : public CBulletBase
{
public:
virtual void update() override { std::cout << "CBulletAiming::update()\n\n"; }
CBulletAiming() { std::cout << "Create CBulletAiming\n"; };
virtual ~CBulletAiming() { };
};

// 円形弾
class CBulletCircle : public CBulletBase
{
public:
virtual void update() override { std::cout << "CBulletCircle::update()\n\n"; }
CBulletCircle() { std::cout << "Create CBulletCircle\n"; };
virtual ~CBulletCircle() { };
};


弾生成の骨組みを作成しよう
この辺をどうしようかなと思ったのですが、とりあえずファクトリクラスなるものを作成し、
弾の ID を引数として受け取り、その ID を元に、自機狙い弾、円形弾などを生成します。
簡単ではありますが、実装はこんな感じになりました。


// 弾生成
class CBulletFactory
{
public:
boost::shared_ptr<CBulletBase> create(int bulletID)
{
switch (bulletID)
{
case 0: return boost::shared_ptr<CBulletBase>(new CBulletAiming());
case 1: return boost::shared_ptr<CBulletBase>(new CBulletCircle());
}
return NULL;
}
};


case 0、case 1 とかマジックナンバーになってますが、
enum で列挙しておくと使いやすそうですね。(今回はマジックナンバーにしました)

また、スマートポインタを使わず管理してもよさそうですが、
せっかく便利な機能があるので使ってみようかなということでこうしてます。
これで、弾の生成や弾の基本情報を持ったクラスの作成が完了しました。


弾管理クラスを作成しよう
これらのクラスをどう扱うか考えたのですが、
弾の管理クラスを作成し、その中でリスト管理してみる方向にしました。
弾管理クラスはこんな実装になりました。


// 弾管理マネージャ
class CBulletMng
{
private:
CBulletFactory m_Factory; // 弾生成クラス
std::list< boost::shared_ptr<CBulletBase> > m_List; // リスト

public:
void create(int bulletID)
{
m_List.push_back( m_Factory.create(bulletID) );
}

void update()
{
std::list< boost::shared_ptr<CBulletBase> >::iterator wIt;

// リスト内を全て更新
for (wIt = m_List.begin(); wIt != m_List.end(); ++wIt)
(*wIt)->update();
}
};


std::list で弾をリストで保持するメンバ変数を用意し、
create メソッドに引数である bulletID(この例では、0か1)を渡すと、対象の弾が生成され
このリストの中に push_back されます。

update メソッドではリスト内にある弾クラスの update メソッドを呼び出しているので
自機狙い、円形弾などのバリエーションごとに更新を呼び出してます。

特に必要ないとおもいますが、メインはこんな感じで生成と更新をするようになりました。



int main()
{
CBulletMng wMng;

// ID を1→ 0→ 1→ 0 と変化させて交互に生成
for (int i = 1; i < 6; ++i)
wMng.create(i%2);

wMng.update();

return 0;
}


ID さへ渡せば中で弾の生成やリストでの管理を行ってくれます。
今回はマジックナンバーなのでベタに for文で適当に交互に ID を渡すようにしました。

この部分は一例として

wMng.create(TYPE_AIMING);
wMng.create(TYPE_NWAY);

のようにしていれば、自機狙い弾、nway弾の生成してそうだな
ってのが一目で見て分かるかな…

スマートポインタになっているので、明示的な delete をする必要も(多分)なさそうですし、
より安全に動的作成してもよさそうかなと思いました。

m_List.clear(); と呼ぶとリスト内を全て消すことも出来ますし
リスト管理は色々便利ですね。


一応出力結果は下記になります。


Create CBulletCircle
Create CBulletAiming
Create CBulletCircle
Create CBulletAiming
Create CBulletCircle

CBulletCircle::update()
CBulletAiming::update()
CBulletCircle::update()
CBulletAiming::update()
CBulletCircle::update()


それぞれの弾クラスの update メソッドが呼ばれておりますので多態勢も大丈夫そうです。


これだけではないのですが、大まかにこんな流れの骨組みをここ1-2日で作成しておりました。
現在はボタンを押すと弾が発射され、移動するというところまでの実装は出来ましたので
まずは気になっていた大きな部分を一つクリアしたかなという印象です。

プログラムやっぱり楽しいですが、知らん間に時間が経って睡眠時間が削られてたりすることが多いです。
しばらく離れていたのでなんとか進めたいです・・・

この記事へのコメント

トラックバック

URL :

検索フォーム
プロフィール

DVDM

Author:DVDM
自作ゲームの開発過程ブログ。
赤髪愛なら誰にも負けない。

 
Pixiv バナー


ブロとも申請フォーム
最新記事
カテゴリ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
ブロとも一覧
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。