返信いただき、ありがとうございます。
説明文だけでは不足していたようですので、コード全体を載せます。
シーケンス管理につきましては、
http://dixq.net/g/sp_06.html こちらを参考にして作成しました。
//main.cpp
コード:
//デバッグ用
#define DEBUG_MODE
#define _CRT_SECURE_NO_WARNINGS
#include "DxLib.h"
#include "CSequenceMgr.h"
#include "key.h"
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
#ifdef DEBUG_MODE
AllocConsole();
freopen("CONOUT$", "w", stdout);
#endif
//ウィンドウ or 全画面
if (ChangeWindowMode(TRUE) == -1) {
return -1;
}
//DXライブラリ初期化
if (DxLib_Init() == -1) {
return -1;
}
//裏画面へ書き込み
if (SetDrawScreen(DX_SCREEN_BACK) == -1) {
return -1;
}
CSequenceMgr SequenceMgr;
SequenceMgr.Init();
//メインループ。画面更新、他アプリケーションとの連携処理、画面消去
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
UpdateKey(); //キー情報の更新
SequenceMgr.Calc(); //計算
SequenceMgr.Draw(); //描画
}
SequenceMgr.End();
//DXライブラリ終了
DxLib_End();
#ifdef DEBUG_MODE
FreeConsole();
#endif
return 0;
}
//CSequenceMgr.h
コード:
#ifndef _INCLUDE_GUARD_CSEQUENCEMGR_
#define _INCLUDE_GUARD_CSEQUENCEMGR_
#include "ISequenceChanger.h"
#include "CBaseSequence.h"
class CSequenceMgr : public ISequenceChanger, CSequenceTask {
private:
CBaseSequence* mSequence; //シーケンス管理変数
ESequence mNextSequence; //次のシーケンス管理変数
public:
CSequenceMgr();
void Init() override; //初期化
void End() override; //終了処理
void Calc() override; //更新
void Draw() override; //描画
// 引数 NextSequence にシーケンスを変更する
void ChangeSequence(ESequence NextSequence) override;
};
#endif
//ISequenceChanger.h
コード:
#ifndef _INCLUDE_GUARD_ISEQUENCECHANGER_
#define _INCLUDE_GUARD_ISEQUENCECHANGER_
typedef enum {
Sequence_Menu, //メニュー画面
Sequence_Game, //ゲーム画面
Sequence_Config, //設定画面
Sequence_None //無し
} ESequence ;
//シーケンスを変更するためのインターフェイスクラス
class ISequenceChanger {
public:
virtual ~ISequenceChanger() = 0;
//指定シーケンスに変更する。
virtual void ChangeSequence(ESequence NextSequence) = 0;
};
#endif
//CBaseSequence.h
コード:
#ifndef _INCLUDE_GUARD_CBASESEQUENCE_
#define _INCLUDE_GUARD_CBASESEQUENCE_
#include "CSequenceTask.h"
#include "ISequenceChanger.h"
//シーケンスの基底クラス。
class CBaseSequence : public CSequenceTask {
protected:
int mImageHandle; //画像ハンドル格納用変数
ISequenceChanger* mSequenceChanger; //クラス所有元にシーケンス切り替えを伝えるインターフェイス
public:
CBaseSequence(ISequenceChanger* changer);
virtual ~CBaseSequence(){}
virtual void Init() override {}; //初期化処理をオーバーライド。
virtual void End() override; //終了処理をオーバーライド。
virtual void Calc() override {}; //更新処理をオーバーライド。
virtual void Draw() override; //描画処理をオーバーライド。
};
#endif
//CSequenceTask.h
コード:
#ifndef _INCLUDE_GUARD_CTASK_
#define _INCLUDE_GUARD_CTASK_
//共通処理のクラス
class CSequenceTask {
public:
virtual ~CSequenceTask(){}
virtual void Init(){} //初期化処理は実装してもしなくてもいい
virtual void End(){} //終了処理は実装してもしなくてもいい
virtual void Calc() = 0; //更新処理は必ず継承先で実装する
virtual void Draw() = 0; //描画処理は必ず継承先で実装する
};
#endif
//CBaseSequence.cpp
コード:
#include "CBaseSequence.h"
#include "DxLib.h"
CBaseSequence::CBaseSequence(ISequenceChanger* changer) : mImageHandle(0) {
mSequenceChanger = changer;
}
void CBaseSequence::End() {
//共通処理
}
void CBaseSequence::Draw() {
//共通処理
}
//ISequenceChanger.cpp
コード:
#include "ISequenceChanger.h"
ISequenceChanger::~ISequenceChanger(){
}
//CSequenceMgr.cpp
コード:
#include "DxLib.h"
#include "Config.h"
#include "Game.h"
#include "Menu.h"
#include "CSequenceMgr.h"
CSequenceMgr::CSequenceMgr() : mNextSequence(Sequence_None) {
mSequence = (CBaseSequence*) new Menu(this);
}
//初期化
void CSequenceMgr::Init() {
mSequence->Init();
}
//終了処理
void CSequenceMgr::End() {
mSequence->End();
}
//更新
void CSequenceMgr::Calc() {
//次のシーケンスがセットされていたら
if (mNextSequence != Sequence_None) {
//現在のシーケンスの終了処理を実行
mSequence->End();
delete mSequence;
//シーケンスによって処理を分岐
switch(mNextSequence){
case Sequence_Menu:
mSequence = (CBaseSequence*) new Menu(this);
break;
case Sequence_Game:
mSequence = (CBaseSequence*) new Game(this);
break;
case Sequence_Config:
mSequence = (CBaseSequence*) new Config(this);
break;
}
//次のシーケンス情報をクリア
mNextSequence = Sequence_None;
//シーケンスを初期化
mSequence->Init();
}
//シーケンスの更新
mSequence->Calc();
}
//描画
void CSequenceMgr::Draw(){
//シーケンスの描画
mSequence->Draw();
}
// 引数 NextSequence にシーケンスを変更する
void CSequenceMgr::ChangeSequence(ESequence NextSequence){
//次のシーケンスにセットする
mNextSequence = NextSequence;
}
//Menu.h
コード:
#ifndef _INCLUDE_GUARD_MENU_
#define _INCLUDE_GUARD_MENU_
#include "CBaseSequence.h"
//メニュー画面クラス
class Menu : public CBaseSequence {
public :
Menu(ISequenceChanger* changer);
void Init() override;
//void End() override;
void Calc() override;
void Draw() override;
};
#endif
//Menu.cpp
コード:
#include "Menu.h"
#include "DxLib.h"
//CBaseSequence(changer) の意味は、mSequenceChanger = changer
Menu::Menu(ISequenceChanger* changer) : CBaseSequence(changer) {
}
//初期化
void Menu::Init() {
//画像のロード
mImageHandle = LoadGraph("images/Sequence_Menu.png");
}
//更新
void Menu::Calc() {
if(CheckHitKey(KEY_INPUT_G)!=0){//Gキーが押されていたら
mSequenceChanger->ChangeSequence(Sequence_Game);//シーケンスをゲーム画面に変更
}
if(CheckHitKey(KEY_INPUT_C)!=0){//Cキーが押されていたら
mSequenceChanger->ChangeSequence(Sequence_Config);//シーケンスを設定画面に変更
}
}
//描画
void Menu::Draw() {
//親クラスの描画メソッドを呼ぶ
CBaseSequence::Draw();
DrawGraph(0, 0, mImageHandle, TRUE);
DrawString(0, 0, "メニュー画面です。", GetColor(255,255,255));
DrawString(0, 20, "Gキーを押すとゲーム画面に進みます。", GetColor(255,255,255));
DrawString(0, 40, "Cキーを押すと 設定画面に進みます。", GetColor(255,255,255));
}
// Config, Game, key は不要かな?と思いますので、省略します。
usao さんが書きました:
>enum 定数で管理し、ChangeScene 関数にそれを渡せるようにする
ChangeScene(CBaseScene* pNextScene); //遷移先シーンを直接渡す
みたいな直接的な形ではなく
(遷移先シーンを表すための?)enumを一旦間に挟む形としている理由があると思いますので,
そこら辺を説明した方が良いのではないかと.
特に理由は考えておらず、冒頭のURLのページに書かれているソースコードを参考にさせていただいたのみです。
hide さんが書きました:
シーケンスが主でシーンが従なのでしょうか?具体的にそれぞれ何をしているんでしょう。
シーケンスが、タイトル画面とかの括りで シーンがタイトル画面のロード処理とかの括り ですか?
だとすると、ESceneというのがシーンと言われているものの実態を示すもの?
シーケンスが主、シーンが従になります。
シーケンスだけでは括りが大きいので、もう少し小さい括りをシーンとしています。
シーケンスは、タイトル画面、ゲーム画面、設定画面などの大きな括りで、
タイトル画面には、「オープニングムービー再生」のシーンのみ
ゲーム画面には(とりあえず、スーファミのスーパーマリオワールドを例にとります。ご存知でしょうか)、「ステージ選択画面」、「ステージ1」、「ステージ2」…のシーン
設定画面には、「設定画面の表示」「設定1の詳細」「設定2の詳細」…のシーン
という感じです。
hide さんが書きました:
上記の解釈であっているならば、外部にESceneを公開する必要性に疑問を感じます。
継承を利用するならば、外から見て等しい操作ができなければいけません。
すみません、うまく伝わらなかったかも知れません。
外部には EScene を公開しません。
シーケンスごとに内部で(シーケンスのスコープ内で or シーケンスはシーケンスごとに class を作っているので、その中で)シーンの名前のリスト EScene (ゲーム画面の例では、Scene_SelectStage, Scene_Stage1, Scene_Stage2 など)を用意します。
これでうまく具体例になっていて、伝わると良いのですが…