次はシーン遷移管理マネージャーの作成でもと
// シーン定義構造体
// シーン情報は一箇所にまとめる
struct SceneDefine {
int sceneid;
string scenename;
GameScene::Scene* scene;
};
// シーン一覧
SceneDefine gSceneList[] = {
{ SCENE_1 , "シーンその1" , new Scene_1() } ,
{ SCENE_2 , "シーンその2" , new Scene_2() } ,
{ SCENE_3 , "シーンその3" , new Scene_3() } ,
{ SCENE_4 , "シーンその4" , new Scene_4() } ,
};
シーンが切り替わるたびにインスタンス破棄→生成をする方法もあるけど
今回は利用するシーンを最初にすべて生成する方法で作ります。
まずはシーンマネージャー
class SceneManager {
private :
enum SCENE_STATE{
STATE_NONE ,
STATE_INIT ,
STATE_FI ,
STATE_UPDATE ,
STATE_FO ,
STATE_RELEASE ,
};
GameScene::Scene* m_currentScene;
list m_scene;
vector m_sceneHistory;
int m_startsceneid;
int m_state;
int m_stateNext;
int m_nextsceneid;
bool m_isfirst;
bool m_prevSceneChanged;
FadeListener* m_whiteFade;
static SceneManager* instance;
SceneManager(){
m_currentScene = NULL;
m_startsceneid = SCENE_NONE;
m_state = STATE_NONE;
m_stateNext = STATE_INIT;
m_isfirst = false;
m_prevSceneChanged = false;
m_whiteFade = new WhiteFadeListener();
m_nextsceneid = SCENE_NONE;
}
void _dumpSceneHistory(){
APP_PRINT( "**dump scene history \n" );
for( int i = 0 ; i OnPreInit();
m_currentScene->OnInit();
m_stateNext = STATE_FI;
break;
case STATE_FI :
{
if( m_currentScene->getFadeIn() == NULL ){
m_stateNext = STATE_UPDATE;
break;
}
bool isFadeEnd = m_currentScene->getFadeIn()->FadeIn( m_isfirst );
if( isFadeEnd ){
m_stateNext = STATE_UPDATE;
}
}
break;
case STATE_UPDATE :
if( m_isfirst ){
m_currentScene->OnUpdateFirst();
}
m_currentScene->OnUpdate();
m_nextsceneid = m_currentScene->getNextSceneID();
if( m_nextsceneid != SCENE_NONE ){
m_stateNext = STATE_FO;
}
break;
case STATE_FO :
{
if( m_currentScene->getFadeOut() == NULL ){
m_stateNext = STATE_RELEASE;
break;
}
bool isFadeEnd = m_currentScene->getFadeOut()->FadeOut( m_isfirst );
if( isFadeEnd ){
m_stateNext = STATE_RELEASE;
}
}
break;
case STATE_RELEASE :
if( m_isfirst ){
if( m_sceneHistory.size() >= 128 ){
m_sceneHistory.erase( m_sceneHistory.begin() );
}
if( !m_prevSceneChanged ){
m_sceneHistory.push_back( m_currentScene->getSceneID() );
}
m_currentScene->OnRelease();
m_currentScene = findScene( m_nextsceneid );
m_stateNext = STATE_INIT;
}
break;
}
}
↓
フェードイン
↓
更新処理(ゲームループ)
↓
フェードアウト(次のシーンが指定されたら)
↓
開放処理
↓
初期化ステートへ戻る
の順番で処理が呼ばれる。
フェードインとフェードアウトは前回の日記でリスナーを定義していたけど、
このフェードイン・アウト処理はシーン毎に用意する必要がある。
シーン毎に用意するのが面倒であれば初期値でデフォルトのフェードリスナーをセットすれば( `д´)b オッケー!
・次のシーンへ進む場合はシーン履歴にスタックを積む
・前のシーンに戻る場合はシーン履歴のスタックを解決する
で前回と次回のシーンを持つことが可能
2つ前のシーンに戻りたい場合は2回ポップを呼べばオッケー☆⌒d(´∀`)ノ
基底シーンクラスに1歩前のシーンに戻れる関数を追加します。 継承先は関数一発で前のシーンに戻れるようになります。
次のシーンへも関数一発
フェードイン・アウトは種類を増やすならその分定義する必要がある。
仮に白くフェードイン・アウトするものを作ってみる
// 白フェードリスナー
class WhiteFadeListener : public GameSystem::FadeListener {
private :
int m_colorR;
int m_colorG;
int m_colorB;
public :
WhiteFadeListener();
virtual bool FadeIn( bool trigger );
virtual bool FadeOut( bool trigger );
};
// 白フェードリスナー
WhiteFadeListener::WhiteFadeListener(){
m_colorR = 0;
m_colorG = 0;
m_colorB = 0;
}
// フェードイン処理。
// フェードインが終了したタイミングでtrueを返す
bool WhiteFadeListener::FadeIn( bool trigger ){
if( trigger ){
m_colorR = 255;
m_colorG = 255;
m_colorB = 255;
}
m_colorR -= 5;
m_colorG -= 5;
m_colorB -= 5;
DrawBox( 0 , 0 , 640 , 480 , GetColor( m_colorR , m_colorG , m_colorB ) , TRUE );
if( m_colorR = 255 && m_colorG >= 255 && m_colorB >= 255 ){
return true;
}
return false;
}
各シーンを仮に作ってみる
とりあえずはキー入力でシーン遷移するだけ
バックスペースで前のシーンに戻る
const int SCENE_1 = 1;
const int SCENE_2 = 2;
const int SCENE_3 = 3;
const int SCENE_4 = 4;
class Scene_1 : public GameScene::Scene {
public :
virtual void OnInit(){
printfDx( "%s 初期化\n" , getName().c_str() );
}
virtual void OnUpdate(){
DrawFormatString( 0 , 0 , 0xFF00FF , "%s" , getName().c_str() );
if( CheckHitKey( KEY_INPUT_BACK ) ){
this->prevSceneChange();
}
if( CheckHitKey( KEY_INPUT_2 ) ){
this->setNextSceneID( SCENE_2 );
}
if( CheckHitKey( KEY_INPUT_3 ) ){
this->setNextSceneID( SCENE_3 );
}
}
virtual void OnRelease(){
printfDx( "%s 開放\n" , getName().c_str() );
}
};
class Scene_2 : public GameScene::Scene {
virtual void OnInit(){
printfDx( "%s 初期化\n" , getName().c_str() );
}
virtual void OnUpdate(){
DrawFormatString( 0 , 0 , 0xFF00FF , "%s" , getName().c_str() );
if( CheckHitKey( KEY_INPUT_BACK ) ){
this->prevSceneChange();
}
}
virtual void OnRelease(){
printfDx( "%s 開放\n" , getName().c_str() );
}
};
class Scene_3 : public GameScene::Scene {
virtual void OnInit(){
printfDx( "%s 初期化\n" , getName().c_str() );
setFadeIn ( GameScene::SceneManager::Instance()->getWhiteFadeListener() );
setFadeOut( GameScene::SceneManager::Instance()->getWhiteFadeListener() );
}
virtual void OnUpdate(){
DrawFormatString( 0 , 0 , 0xFF00FF , "%s" , getName().c_str() );
if( CheckHitKey( KEY_INPUT_2 ) ){
this->setNextSceneID( SCENE_2 );
}
if( CheckHitKey( KEY_INPUT_4 ) ){
this->setNextSceneID( SCENE_4 );
}
if( CheckHitKey( KEY_INPUT_BACK ) ){
this->prevSceneChange();
}
}
virtual void OnRelease(){
printfDx( "%s 開放\n" , getName().c_str() );
}
};
class Scene_4 : public GameScene::Scene {
virtual void OnInit(){
printfDx( "%s 初期化\n" , getName().c_str() );
setFadeIn ( GameScene::SceneManager::Instance()->getWhiteFadeListener() );
setFadeOut( GameScene::SceneManager::Instance()->getWhiteFadeListener() );
}
virtual void OnUpdate(){
DrawFormatString( 0 , 0 , 0xFF00FF , "%s" , getName().c_str() );
if( CheckHitKey( KEY_INPUT_1 ) ){
this->setNextSceneID( SCENE_1 );
}
if( CheckHitKey( KEY_INPUT_2 ) ){
this->setNextSceneID( SCENE_2 );
}
if( CheckHitKey( KEY_INPUT_BACK ) ){
this->prevSceneChange();
}
}
virtual void OnRelease(){
printfDx( "%s 開放\n" , getName().c_str() );
}
};
最後にWinMain関数
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nShowCmd ){
ChangeWindowMode( TRUE );
DxLib_Init();
SetDrawScreen( DX_SCREEN_BACK );
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// シーン初回設定
GameScene::SceneManager* scene = GameScene::SceneManager::Instance();
for( int i = 0 ; i setupScene( name , id );
scene->entryScene( gSceneList[i].scene );
}
// 初期データの設定
// システム定義が増える度に追加
scene->setStartSceneID( SCENE_3 );
scene->setup();
// 以下更新処理
while( ProcessMessage() == 0 ){
ClsDrawScreen();
scene->update();
ScreenFlip();
}
scene->finalize();
delete scene;
DxLib_End();
return 0;
}
ゲームを作るときはこんな感じの骨格を先に作っておくと楽です。
特にフェードイン・フェードアウトは自由に組み替えられるようにしておくとメンテしやすいです。
次回からはゲームオブジェクトに関してどうのこうの書く予定なのかもしれない。
ではでは