ページ 11

インクルードとシーケンス遷移

Posted: 2011年12月03日(土) 18:13
by haku
質問させて頂きます

Windows7 VC++2010 DXライブラリの環境下で3Dアクションゲームを作りたいと思っています

以下 ソースコードです

コード:


/**********common.h*************/

#include "DxLib.h"

//キャラクタークラス
class Character{
	public:
		int Mhandle;
		VECTOR pos;
		virtual void Move() = 0;
		virtual int load() = 0;
};

//主人公クラス::キャラクタークラスを継承
class Hero : public Character{
	public:
		void Move();
		int  load();
};



/**********main.h**************/



//ゲーム遷移状態
enum{
	 GAME_TITLE,	//ゲームタイトル
	 GAME_MAIN,		//ゲームメイン
	 GAME_INIT,		//ゲーム初期化
	 GAME_CLEAR,		//ゲームクリア
	 GAME_OVER,		//ゲームオーバー
};



//プロトタイプ宣言
int gamestatus = GAME_TITLE;

//ゲーム遷移状態関数
void GameTitle();		//ゲームタイトル
void GernalInit();		//ゲーム初期化
void GameMain();		//ゲームメイン
void GameClear();		//ゲームクリア
void GameOver();		//ゲームオーバー

//データロード
int  LoadModel();



/**********hero.h************/


#include"common.h"


//主人公移動処理
void Hero::Move(){
	// 3Dモデルを表示
	MV1SetPosition(Mhandle, VGet( 320.0f, 225.0f, -370.0f ) ) ;
	MV1DrawModel(Mhandle) ;
}

//主人公モデル読み込み
int  Hero::load(){

	// 3Dモデルの読み込み
	Mhandle = MV1LoadModel( "model/haku.pmd" ) ;

	return Mhandle;

}




/**********main.cpp*************/

#include "common.h"
#include "main.h"

//オブジェクトの宣言
Hero hero;


//キー格納配列
int Key[256];
 
//キー押下状態取得関数
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
	//全キーを取得
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );

	//全キー256個の状態を調べる
    for(int i=0;i<256;i++){
        if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
        else                            GetHitKeyStateAll_InputKey[i]=0;
    }
    return 0;
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
	

    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	//モデルファイルの読み込み
	//読み込みに失敗した場合にメッセージボックス表示
	if( LoadModel() == -1) {
		MessageBox(NULL, "ファイル読み込み失敗", "DXライブラリ", MB_OK);
		return -1;
	}


	
 
    while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない
		DrawBox(0,0,640,480, 0x808080, TRUE);

		switch(gamestatus){

			case GAME_TITLE:	//ゲームタイトル
				GameTitle();
				break;
			case GAME_INIT:		//ゲーム初期化
				GernalInit();
				break;
			case GAME_MAIN:		//ゲームメイン
				GameMain();
				break;
			case GAME_CLEAR:	//ゲームクリア
				GameClear();
				break;
			case GAME_OVER:		//ゲームオーバー
				GameOver();
				break;

		}



 
 
 
        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}


/************************************************************************************
*
*ゲームタイトル
*
*************************************************************************************/
void GameTitle(){

	// 文字列の描画
	DrawString( 250 , 240 - 32 , "GameTitle" , 0xffffff );



	if( Key[KEY_INPUT_SPACE] == 1 ){

		gamestatus = GAME_INIT;

	}

}


/************************************************************************************
*
*初期化
*
*************************************************************************************/
void GernalInit(){

	// 文字列の描画
	DrawString( 250 , 240 - 32 , "GernalInit" , 0xffffff );

	if( Key[KEY_INPUT_SPACE] == 1 ){

		gamestatus = GAME_MAIN;

	}
}

/************************************************************************************
*
*データロード
*
*************************************************************************************/
int LoadModel(){

	//主人公モデルのロード
	if(hero.load()==-1) return -1;

}

/************************************************************************************
*
*ゲームメイン
*
*************************************************************************************/
void GameMain(){
	// 文字列の描画
	DrawString( 250 , 240 - 32 , "GameMain" , 0xffffff );


	
	

	hero.Move();

	if( Key[KEY_INPUT_SPACE] == 1 ){

		gamestatus = GAME_CLEAR;

	}
}


/************************************************************************************
*
*ゲームクリア
*
*************************************************************************************/
void GameClear(){
	// 文字列の描画
	DrawString( 250 , 240 - 32 , "GameClear" , 0xffffff );

	if( Key[KEY_INPUT_SPACE] == 1 ){

		gamestatus = GAME_OVER;

	}
}


/************************************************************************************
*
*ゲームタイトル
*
*************************************************************************************/
void GameOver(){

	// 文字列の描画
	DrawString( 250 , 240 - 32 , "GameOver" , 0xffffff );

	if( Key[KEY_INPUT_SPACE] == 1 ){

		gamestatus = GAME_TITLE;

	}
}
まだモデルを表示するだけの初期段階です

今までは小規模のゲームを作っていたので上記のソースコードのような構造になっていたのですが、
今回はある程度大きな規模のゲームにする予定なのでインクルードとシーケンス遷移の仕組みを変えたいと思っています
何か良い方法はありませんでしょうか?

またシーケンス遷移では名前空間と各シーンをクラス化して管理するのがよいと聞きましたが具体的にはどのようなものでしょうか?

Re: インクルードとシーケンス遷移

Posted: 2011年12月03日(土) 20:22
by うしお
つまるところ、「状態によって処理を切り替える」
というソフトウェアでは典型的なパターンですね。

古典的なオブジェクト指向的に捉えるならば、
継承&ポリモーフィズムによって、stateパターンのような形式でやる、というのが一つあります。

コード:

class SceneBase
{
  public:
  virtual ~SceneBase(){}
  virtual void init() = 0;
  virtual void term() = 0;
  virtual void update() = 0; //戻り値か引数か何かで次の移動先シーンを決定する必要はある。
};
好みの問題もありますが、
単純に関数ポインタを使用して、
関数ポインタを書き換えることがシーン遷移である、
と解釈することもできるでしょう。

また、もっと高級な機能として、boost::functionなどの関数オブジェクトコンテナを使ってみる、
というのも継承よりラクチンでアリかも知れません。

オブジェクト指向だけが解決策でない場合もあるので、
柔軟に選択肢を出してみました。いかがでしょうか?

Re: インクルードとシーケンス遷移

Posted: 2011年12月04日(日) 09:56
by haku
オブジェクト指向の勉強も含めながら作っていきたい思っていますので、
Stateパターンはいいかもしれません
後自分は優柔不断な性格なので開発の途中からあれがしたい、これがしたいと思ってしまうので
拡張性も欲しいのですがそうゆう点でもやはりクラスを使っていったほうが良いのでしょうか?

Re: インクルードとシーケンス遷移

Posted: 2011年12月04日(日) 14:12
by うしお
クラスを使っていって問題ないと思います。
ただ選択肢の一つを取っているだけだ、ということは頭の片隅に理解しておくと良いと思います。

例えば拡張、という点においてオブジェクト指向はとても優れています。
が、逆に派生すべてに影響を及ぼす基底クラスの変更にはとても脆弱なのです。

※このあたりの考え方はプログラマによって違ったりもしますので、あくまでも私の考えというだけです。
 違った答えを出すことは勿論あって当然です。

Re: インクルードとシーケンス遷移

Posted: 2011年12月05日(月) 17:39
by haku
分かりました
クラスを使ってやってみようと思います
ご回答頂きありがとうございました。