画面遷移の実装法

yuki
記事: 5
登録日時: 14年前

画面遷移の実装法

投稿記事 by yuki » 14年前

ゲームを作る上で画面遷移というのはとても重要なものです。
が、その実装方法というものがどうしても泥臭くなりがちです。
皆さんは画面遷移するとき、どういう実装にするのでしょうか。
(正直に言うと、ここが一番知りたいところです)
例えばこんな感じでしょうか。

CODE:

enum SCENE_ID
{
	SCENE_ID_DUMMY = 0,
	SCENE_ID_LOADING,
	SCENE_ID_TITLE,
	SCENE_ID_GAMEMAIN,
	SCENE_ID_GAMEOVER,
};
 
namespace
{
	SCENE_ID CURRENT_SCENE;
}
 
 
void mainloop()
{
	
	for(;;)
	{
		switch(CURRENT_SCENE)
		{
			case SCENE_ID_LOADING:
				loading_update();
				loading_draw();
				break;
			
			case SCENE_ID_TITLE:
				title_update();
				title_draw();
				break;
			
			case SCENE_ID_GAMEMAIN:
				loading_update();
				loading_draw();
				break;
			
			case SCENE_ID_GAMEOVER:
				gameover_update();
				gameover_draw();
				break;
			
			case SCENE_ID_DUMMY:
			default:
				break;
		}
	}
	
}

これでも悪くはないのですが、画面にも細かい状態があり、初期化中であったり終了中であったりするはずです。
そうなるとloading_updateの中にさらにswitch文が重なっていくことになります。
そこで、画面を一つのインターフェイスとし、そこから派生して行けば楽ではないか?
ということで書いてみます。

CODE:

class IScene
{
public:
	Scene();
	virtual ~Scene();
	
	virtual void update()		= 0;
	virtual void draw() const	= 0;
};
 
namespace
{
	IScene		*CURRENT_SCENE;
}
 
void mainloop()
{
	for(;;)
	{
		CURRENT_SCENE->update();
		CURRENT_SCENE->draw();
	}
}

限りなく正解に近い気がしてきました。
でも、これだと肝心の画面遷移が出来ません。
だったら、ISceneのリストを持っておいて、画面遷移時にリストに新しいISceneを追加して、updateでfalseを返すと勝手に消してくれるようにすればうまくいきそうじゃないか。

CODE:

class IScene { /* 省略 */ };
 
namespace
{
	typedef std::vector	SceneList;
	SceneList	CURRENT_SCENE;
}
 
void mainloop()
{
	for(;;)
	{
		// 更新
		for(SceneList::iterator it = CURRENT_SCENE.begin(); it != CURRENT_SCENE.end(); /* empty */ )
		{
			if(!it->update())
			{
				it = CURRENT_SCENE.erase(it);
			}
			
			++it;
		}
		
		// 描画
		for(SceneList::iterator it = CURRENT_SCENE.begin(); it != CURRENT_SCENE.end(); ++it )
		{
			it->draw();
		}
	}
}

結局タスクみたいなことをしてるだけですが、最初のswitch文よりは保守性も可読性も上がったと思います。
(正直画面遷移に保守性も糞も無いと思うのですが……)

ということで、私はこんな感じでやってますが、皆さんはどんな実装なのでしょうか。
もっと良い実装があれば教えて欲しいです。
最後に編集したユーザー yuki on 2010年10月27日(水) 00:35 [ 編集 1 回目 ]

コメントはまだありません。