note.gif (6759 バイト)Index

過去の駄文達はこちらにあります。

2000/01/23 オブジェクト指向っぽくゲーム開発(5)
2000/01/16 オブジェクト指向っぽくゲーム開発(4)
2000/01/15 オブジェクト指向っぽくゲーム開発(3)
2000/01/12 オブジェクト指向っぽくゲーム開発(2)
2000/01/11 オブジェクト指向っぽくゲーム開発(1)

 

 


オブジェクト指向っぽくゲーム開発(5) 2000/01/23

うーむ、途中だいぶ仕様変更が入りました(^_^;)。

まず、新たに爆風クラスをつけたことです。これはえむっちさんからのアイデアで、敵が破壊されたら爆発して、その爆風でまた敵が破壊されて・・・となったら面白いかも、というものがでました。これを表現するには、爆風クラスを作るのが適当かな、と思い、作ってみました。さらにもうちょっと考えて、固定砲台弾丸から爆風を生成する事にしました。というのは、固定砲台の弾丸も着弾したら爆発するからです。同じ爆発で、敵にダメージを与えるという点でも同じなので、いっそのこと同じにしてしまえっ!ということです(^_^;)

次に、インターフェースCollisionableを新たに作成しました。これはミキタさんからのアドバイス”当り判定のメソッドはくくりだすことができるのではないか”を参考に作成したものです。これによって、当る対象がどんなオブジェクトだろうが関係なくなり、さらに、にくむべき巡回依存も除去することができました。

さらに、描画関係のことも考えてみました。色々と考えた結果、”Frame”と”FrameFactory”いうインターフェースを作成する事にしました。Frameは位置と姿勢を設定するメソッド、時間を進めるメソッドを持っています。まあ、このメソッドは暫定で、今後増える可能性が高いですけど。FrameFactoryはFrameを動的に生成する機構を用意します。このクラスは、敵管理クラスや敵弾丸管理クラス等が使うことになると思います。
音は、3Dサウンドを使う方向で考えていきます。位置指定と速度指定、あと音を鳴らすタイミングを通知するメソッドがあれば十分でしょうかね。

主な変更はこんなものです。シーケンス図も書き直しました。クラス図も書き直しましたが、関連が増えたので、クラス図はごちゃごちゃで見れたものではなくなってしまいました(^_^;)。それでも良いという方はこちらです。16kもありますので、気をつけてくださいね。企画書もちょこっと更新です。

メインループのシーケンス図は、画面外まで伸びているためキャプチャ不能です(^_^;)。うーむ。

補足:

巡回依存

class B;
class A{
void operation(B& b){b.foo();}
};
class B{
void operation(A& a);
void foo();
};

このように、Aを使うためにはBが必要で、Bを使うためにはAが必要というような依存の方向が双方向になってしまっていることをさします。ちなみに、次のような場合でも巡回依存しています。こちらのほうが曲者かもしれません。

class B;
class A{
void operation(B& b);
};
class C;
class B{
void operation(C& c);
};
class C{
void operation(A& a);
};

設計上どうしても仕方のない場合を除いて、このようなことは避けるほうがよいそうです。というのは、この巡回依存はオブジェクトの再利用を妨げるからです。これを取り除くには、汎化が有効です。

class base{
virtual void foo()=0;
};
class A{
void operation(base& b){b.foo();}
};
class B:public base{
void operation(A& a);
void foo;
};

これで、AからBへの依存がなくなり、BからAへの単方向の関連だけになりました。このとき、baseをインターフェースあるいはプロトコルクラスと呼ぶそうです。後者の呼び方はあまり聞いたことがありませんが(^_^;)


オブジェクト指向っぽくゲーム開発(4) 2000/01/16

ふー、ようやくメインループのシーケンス図を書き終えました。こうして動的分析をしてみると、僕の作った企画書やクラス図の不備わかってきますね。中でも一番”しまった!”と思ったのが、スコアのことを全然考えていなかったことです。で、急遽スコア計算クラスをつくりました。これでもう不備はない・・・かなあ(自信全くなし(^_^;))。

シーケンス図は大きすぎてキャプチャーできなかったので、シーケンス図の画像はありません。すいません。(・・・って、ここ見ている人いるのかなあ(^_^;))

その代わりといっては何ですが、クラス図は更新しました。こちらです。企画書はこちらです。

次は、そろそろ描画関係のことを考えてみたいと思います。ゲームプログラミングにおいては本来こちらがメインなので、さらに時間がかかりそうです。


オブジェクト指向っぽくゲーム開発(3) 2000/01/15

うーん、半分ゲーム開発日記と化してきましたね。まあ、それはそれでいいですか(^_^;)

予定通り、クラス間関連を調べました。関連を調べていくうちに、どういう風に敵が出現するのかが全く触れられていないことに気が付いて、企画書を修正。これで、敵管理クラスには敵を生成するという役目も負ってもらうことにしました。

それと、HUDはどうも問題領域外のクラスのような気がしてきたので、除外しました。HUDが登場するのはまだ先ということですね。

さらに、戦車、ロケット車、攻撃ヘリ、戦闘機のような敵の種類はまだ暫定で、今後変更されたり数が増えたりする可能性があります。ので、具体的なクラスに依存しないために抽象クラスとして”敵クラス”を作りました。これで敵が増えようが変更されようが、全く問題無く運用できるようになります・・・というのはまだ早いですね。このままでは敵管理クラスは相変わらず具体的なクラスに依存しているので、これを改善しなければなりません。

うーん、どのように変更しましょうかねえ・・・。そうだ、敵管理クラスはオブジェクトを生成するときに具体的なクラスに依存しているようなので、AbstractFactoryFactoryMethodを使えばよさそうな気がします。普通なら拡張性、再利用性ともに優れたオブジェクトコンポジションであるAbstructFactoryを採用しますけど、今回はそこまでする必要はなさそうです。というわけで、継承を使ったFactoryMethodを使うことにします。

できたクラス図はこちらです。サイズは10kbぐらいありますので、気をつけてくださいね。僕はUMLを知らないので、かなり適当です(^_^;)。こんなあやふやでいいのかなあ・・・なんか心配になってきました。名前がすべて日本語なのは勘弁してください(^_^;)

ふーむ、そろそろメソッドの引数、戻り値や考えないといけませんね。あと、表示関連の問題もあります。普通の分析では画面表示やら音を鳴らすという処理は入れないらしいのですが、なんせ僕が作っているのはゲームなので、あまりに効率の悪いことはできませんし。

補足:

AbstarctFactory

今巷で話題のデザインパターンの一つ、クラスの生成に関するパターンです。言葉での説明は僕の理解不足からできないので、サンプルを書いておきます(うーむ(^_^;))。

class 動物{virtual void 鳴く()=0;};
class 猫:public 動物{void 鳴く(){/*・・・*/}};
class 犬:public 動物{void 鳴く(){/*・・・*/}};

class ペットショップ{virutal 動物* 売る()=0;};
class 猫のペットショップ:public ペットショップ{動物* 売る(){return new 猫;}};
class 犬のペットショップ:public ペットショップ{動物* 売る(){return new 犬;}};

class 動物が欲しい人{
void 動物を飼う(ペットショップ* p){
  動物* d=p->売る();
  d->鳴く();
  delete d;
}
};

こうすれば、”動物が欲しい人”はその動物が何であるかわからなくても、生成することができます。つまり、”動物が欲しい人”は、”ペットショップ”のサブクラスを定義することによって再利用ができるようになるのです。

FactoryMethod

これまた話題のデザインパターンの一つです。上のパターンと似たようなものですが、これは基底クラスでオブジェクト作成メソッドをvirtualで定義しておき、それを派生クラスがオーバーライトすることで実現しています。またサンプルを書いてみます。

/*動物のクラスは同じ*/

class 動物が欲しい人{
virtual 動物* 動物を買ってくる()=0;
void 動物を買ってその動物を鳴かせる(){
動物* d=動物を飼ってくる();
d->鳴く();
delete d;
}
};

class 猫を買ってきた動物が欲しい人:public 動物が欲しい人{動物* 動物を買ってくる(){return new 猫;}};
class 犬を買ってきた動物が欲しい人:public 動物が欲しい人{動物* 動物を買ってくる(){return new 犬;}};

void foo(動物が欲しい人* d){
d->動物を買ってその動物を鳴かせる();
}

あんまりいい例ではないですか(^_^;)。こういうのをまともに説明できる人ってすごいですね。

オブジェクトコンポジション

正確な定義は知りません(^_^;)。僕はメンバ関数を使う代わりにオブジェクトを使ってしまおうという考え方だと認識しています。この考え方が威力を発揮するのはポリモフィズムを使うときです。継承を使ったポリモフィズムを使った場合、例えばオーバーライトしなければならない仮想関数が多数あったとします。このときに問題になることは、関数を独立して拡張できないということです。さらに、継承は静的なので実行時に一部だけの振る舞いを変更、という真似はできません。それともう一つ、拡張した関数を再利用できないということがあります。

お気づきだと思いますが、オブジェクトコンポジションという考え方は、このすべてを解決してくれます。

2000/01/06修正:

とういか、この説明だったらStrategyパターンの説明になりますね(^_^;)。言い直すと、 僕はオブジェクトコンポジションは継承をオブジェクトを持つ、あるいは知ることで実装しようという考え方、という認識でいます。

これらの正確な定義についてはソフトバンクパブリッシング出版の”オブジェクト指向における再利用のためのデザインパターン”を参照してください・・・といって逃げておきます(^_^;)。


オブジェクト指向っぽくゲーム開発(2) 2000/01/12

なにか形が無ければ”またか”と思われるので、一応、企画書っぽいものを作ってみました。こちらです。折り返し機能のあるテキストエディタで見てくださいね。HTMLにしなかったのは、今後変更される可能性があるからです。未定義な部分がかなりありますが、これは作っていくうちに考えていくということで・・・って、こんなあやふやなことをしているから挫折しちゃうんですよね(^_^;)。自分がまともに設計して完成させたのってLightmapサンプルだけですし。(しかもかなり妥協がある)

まあいいです。とりあえず企画書からクラス候補になりそうな名詞を抽出してみましょう。ここではまだ、描画関連のクラスについては扱いません。

砂漠、研究所、固定砲台、固定砲台の弾丸、HUD、敵(戦車、ロケット車、攻撃ヘリ、戦闘機)、敵の弾丸

こんなものですかねぇ・・・っと、そういえば弾丸や敵は複数いましたよね。管理クラスを作ったほうが妥当そうです。

固定砲台の弾丸管理、敵の弾丸管理、敵管理

これもクラスになりそうですね。というわけで、次はクラス間関連を調べてみることにします。このフェーズで新たにクラスが見つかることもあるようなので、頑張ります。


オブジェクト指向っぽくゲーム開発(1) 2000/01/11

一応、僕の今年の目標は”ゲームを完成させる”ということです。しかし、はっきりいって今のレベルでdelta(現在開発停滞中の3D対戦シューティング)を完成できるとは全く思っていません(^_^;)。というわけで、もっと簡単なものを作ろうと思っています。
でも、やっぱりただ完成させるだけでは面白くないので、色々と目標を設けます。

  • 僕の知識を総動員して(っていっても少ないけど)、オブジェクト指向で開発する。
  • 知っている方もいますでしょうが、僕はオブジェクト指向にかなり力をいれて勉強しています。今ならオブジェクト指向でアプリケーションが組めると思う(気がするだけかも(^_^;))ので、オブジェクト指向で組みたいと思います。

  • 途中経過をプログラミング・ノートとして随時発表する。
  • これは自分の挫折対策です(^_^;)。プレッシャーを与えると同時に、人様に見せられるコートを心がけさせる目的があります。(なんか他人事みたい)

  • ソースコード公開
  • もしかしたらものすごい人が僕のコードを見てくれて、なにかよいアドバイスをくれるかもしれないという、なんとも奇妙な期待からです(^_^;)。

     

    では、企画書作りから始めることにします。作ろうとするゲームは大体頭の中で固まっていて、すでに少し文章化しているので、これは早く終わりそうです。