シーン管理 コーディング

昨日のシーン管理、何のためか言ってなかった。
何のためかというと、つまりはゲームプログラミングにおけるシーン管理なんだけど。
日記タイトル見れば分かるか。すんません。
さて、今回は長いぞう。
実際にシーン管理のコーディングを泥沼でやってみたから。

シーン管理クラス

とりあえず何より、扱うものの細部よりも扱い方を決めたほうが設計が楽だ。(と自分は信じている。)
というわけでシーン管理クラスを作るわけだね。
実装は前の日記で、スタック付オートマトン*1で実装することに軍曹が決めたからその通りにする。

さて、シーン管理クラスの仕事はシンプルだ。

  • シーンを登録する
  • シーンを破棄する
  • シーンを実行する

あと、仕事の進み具合も報告してほしい。つまり次の機能もほしい。

  • シーンが全て無くなったか調べる

こんなところだろうかね。
それでは、仕様は大体まとまったので早速クラス宣言部を書く。

#include <stack>
#include "IGameScene.h" // シーンを扱うからインクルード

class SceneController{
public:
	SceneController();
	~SceneController();
	void regist(IGameScene* gs); // シーン登録
	void unregist();             // シーン削除
	void act();                  // シーン実行
	bool empty();                // シーンが空っぽかどうか
private:
	std::stack<IGameScene*> sceneStack; // シーンを積むスタック
};

そして、シンプルな実装。

void SceneController::regist(IGameScene* gs){
	gs->init();
	sceneStack.push(gs);
}
void SceneController::unregist(){
	sceneStack.top()->fin();
	sceneStack.pop();
}
void SceneController::act(){
	if(!empty()){
		sceneStack.top()->play();
	}
}
bool SceneController::empty(){
	return sceneStack.empty();
}

実装は非常にシンプルだが、コーディングの途中でいくつか決定したことがある。

  1. シーンの登録時、初期化を自動で行う。
  2. シーンを削除するときは、後処理を自動で行う。
  3. シーンの初期化関数名はinit()
  4. シーンの後処理関数名はfin()
  5. シーンの実行関数名はplay()

まぁ、とりあえず使うときはこんな感じだろう。まだシーンの実体を定義していないのでどうしようもないが。

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

シーンインターフェイス

シーンの外部から見た仕事は決まっている。すなわち

  • 初期化
  • 実行
  • 後処理

である。よってこの3つの関数を持つインターフェイスを作る。


さらに、シーンは他のシーンを登録する操作もありえる。
ゆえに、シーン管理クラスへのポインタも保持することにする。
簡単に言えば、上司(自分を管理する人)の連絡先を覚えとく。
このほうが色々都合が良い。

これをコードで表現すればこうなる。

class SceneController; // クラスの前方宣言、これは便利だ!
class IGameScene{
public:
	IGameScene(SceneController *sc):sc(sc){}
	// 全て純粋仮想関数
	virtual ~IGameScene(){};
	virtual int init() = 0; // 初期化
	virtual int play() = 0; // 実行
	virtual int fin()  = 0; // 後処理
protected:
	SceneController *sc; // 管理者の連絡先
};

インターフェイスだからメンバ関数は全て純粋仮想関数に(virtual & 0で初期化)してある。


そして、次に実際にシーンを定義する。
のだが、長いのでまた次回。

*1:プッシュダウンオートマトン