シーン管理 コーディング2

最近書いてないので続き書こうと思う。
前回で IGameScene と SceneController を書いた。
(前回はここ id:selvaggio:20060821:1156148509 )
間違ってたら遠慮なく指摘してください。
知らない間に修正します。

シーンクラスの実装

端的に何をしたいかと言えば、

SceneController *sc = new SceneController();
IGameScene *somescene = new SomeScene(sc);
sc->regist(somescene);
while(!sc->empty()){
	sc->act();
}

こんな感じで使えるシーンクラスを作りたいわけだ。

このための外部仕様、すなわちインターフェイスは前回の IGameScene で規定してある。
すなわち、初期化・実行・後処理を行うわけだ。
後は、実行する中身を処理する関数を書けばいいわけだ。

最もシンプルな例

例えば、単に Hello, World! と表示するだけのシーンならば次のような感じになる。

#include <iostream>
class HelloScene : public IGameScene { // IGameScene を public 継承
public:
	HelloScene(SceneController* sc){}
	int init(){} // なーんもせぇへん
	int play(){ std::cout << "Hello, World!" << std::endl; }
	int fin(){} // なーんもせぇへん
};

int main(int, char**){
	SceneController *sc = new SceneController();
	IGameScene  *hs     = new HelloScene(sc);
	sc->regist(hs);
	while(!sc->empty()){
		sc->act();
	}
	delete hs;
	delete sc;
	return;
}

こうすれば、 SceneController::act() から HelloScene::play() が呼び出されて、
Hello, World! と表示されるはずだ。

解説

クラス宣言の識別子の後の ": public IGameScene" というのが継承の構文だ。
public 継承によって、HelloScene は IGameScene として扱うことができる。
つまり SceneController にとっては、 IGameScene だけ扱えば済むということ。
これは何が嬉しいかと言えば、つまりはシーンが増えても SceneController を修正する必要がないってことだ。
超嬉しいね。

問題。

さて、実行してみれば分かると思うが(自分は試してない)、上の例は停止しない。
なぜかと言えば、 SceneController のスタック上にいつまでも HelloScene が居座り続けるからだ。
これをどうにかするためには、 play() を次のように書き換える。

int play()
{
	std::cout << "Hello, World!" << std::endl;
	sc->unregist(this);
	return;
}

この変更によって、 HelloWorld の表示の後、自分自身(this)が SceneController のスタック上から取り除かれる。
これで無限ループが発生することはなくなる。

次のステップ

さて、ココまでで無限ループのシーン(笑)と一度で正しく終了するシーンが書けたわけだ。
これを応用して五回 HelloWorld を表示(すなわち特定回数ループ)した後に終了するシーンが書ける。
これは宿題にしておこう!(飽きたとも言う)