ポーズメニューの作り方について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
mj

ポーズメニューの作り方について

#1

投稿記事 by mj » 12年前

現在、メニューの作り方を勉強しています。
メニューなどの基本的な作り方は[ゲームプログラミングの館]にてだいたい理解できました。
ゲーム実行中に特定のキーを押した際に処理をメインループからポーズ画面に移行させる方法は
何とか実装できたのできたのですが私が今実装したいと思っているものはゲーム実行中にポーズキーを
押したときにゲームプレイ画面を一時停止させて、ゲームプレイ画面上にポーズメニューを表示させる
という処理です。
具体的にはシューティングゲームをプレイ中にポーズキーを押すとプレイ画面が停止して画面遷移はせずに
プレイ画面上に[メニューへ戻る],[ゲームを続行する],[オプション]といったポーズメニューを表示させるといった
ものです。このような仕様にするにはどのようにすればよいのでしょうか。
どなたかご教授お願い致します。

derok
記事: 51
登録日時: 12年前

Re: ポーズメニューの作り方について

#2

投稿記事 by derok » 12年前

ゲームプログラミングの館では更新処理と描画処理が分かれていますよね?
これがヒントです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#3

投稿記事 by softya(ソフト屋) » 12年前

ゲームメイン中に部分的に遷移するしか無いでしょうね。
1)更新処理のシューティング部分を停止。
2)更新処理でポーズメニュー処理を呼び出す。
3)描画処理でポーズメニューの描画を追加。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#4

投稿記事 by mj » 12年前

>derokさん、softya(ソフト屋) ご返信ありがとうございます。

以下のようにゲーム実行部分を作成してみました。Aキーを押すとポーズを行いBキーを
押すとポーズを解除するという処理を作りました。
(Bキーはメニューの呼び出しに失敗したらループを抜けられなくなると思いとりあえず設定しました)
Aキーを押したら現在実行している処理を停止してポーズ状態にはなるのですがwhileループ内で
更新処理と描画処理を呼び出しても画面上にメニューが表示されません。
こちらのプレイ画面を停止させた後の処理はどのようにすればよいのでしょうか。
そもそもこのようなやりかたでポーズをさせているのですが方法として問題ないでしょうか。

コード:

 
//ループで必ず行う3大処理
int ProcessLoop()
{
        if(ProcessMessage()!=0)//ウィンドウの×ボタンが押されたら終了する
		{
			return -1;//プロセス処理がエラーなら-1を返す
		}
		if(ClearDrawScreen()!=0)//画面をクリア
		{
			return -1;//画面クリア処理がエラーなら-1を返す
		}
        GetHitKeyStateAll_2();//現在のキー入力処理を行う
		GetHitPadStateAll();  //現在のパッド入力処理を行う
        return 0;
}

int game_main()//ゲーム実行
{
	ChangeWindowMode(TRUE);//ウィンドウモード
	if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) //初期化と裏画面化
	{
		return -1;
	}
	while(ProcessLoop()==0)
	{//メインループ
				music_ini();
			    switch(func_state)
				{
					    case 0:
									load();         //データロード
									first_ini();	//初回の初期化
									func_state=99;
									break;
						case 99://STGを始める前に行う初期化
									ini();
									load_story();
									func_state=100;
									break;
					    case 100:
									calc_ch();		//キャラクタ計算
									ch_move();		//キャラクタの移動制御
									cshot_main();	//自機ショットメイン
									enemy_main();	//敵処理メイン
									shot_main();	//ショットメイン
									out_main();		//当たり計算
									effect_main();	//エフェクトメイン
									graph_main();	//描画メイン
									stage_count++;	//60カウント(60fps)で1秒
									break;
						default:
									printfDx("不明なfunc_state\n");
									break;
				}
		music_play();

		//画面停止処理とポーズメニュー呼び出し
		if(CheckHitKey(KEY_INPUT_A)==1)
		{
			while(1)
			{
				Pose_Update();//更新処理
				Pose_Draw();//描画処理
				if(CheckHitKey(KEY_INPUT_B)==1)
				{
					break;
				}
			}
			game_main();
		}

		ScreenFlip();
		count++;
	 }
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#5

投稿記事 by softya(ソフト屋) » 12年前

別にループを設けてはいけません。
それだとProcessLoop()が呼び出されないのでちゃんと動作しません。それとProcessLoop()をあちこちで呼ぶ事を考えるといけないので釘を差しておきますが、ProcessLoop()を何箇所も呼び出すのは更に危険です。

こういう場合は、ポーズキーの入力で流れを切り替えるだけです。
現在はswitch(func_state)で状態遷移してますが、更にポーズのためにif(pause_flag)とでもして呼び出す関数を切り替えましょう。

ゲームの処理中だけの問題なのでここを改造します。

コード:

                        case 100:
                                    calc_ch();      //キャラクタ計算
                                    ch_move();      //キャラクタの移動制御
                                    cshot_main();   //自機ショットメイン
                                    enemy_main();   //敵処理メイン
                                    shot_main();    //ショットメイン
                                    out_main();     //当たり計算
                                    effect_main();  //エフェクトメイン
                                    graph_main();   //描画メイン
                                    stage_count++;  //60カウント(60fps)で1秒
                                    break;
今の処理は解体して大半は上記の中に組み入れてください。

コード:

        //画面停止処理とポーズメニュー呼び出し
        if(CheckHitKey(KEY_INPUT_A)==1)
        {
            while(1)
            {
                Pose_Update();//更新処理
                Pose_Draw();//描画処理
                if(CheckHitKey(KEY_INPUT_B)==1)
                {
                    break;
                }
            }
            game_main();
        }
つまり、こんな感じです。ポーズキーの処理も書き加えてくださいね。

コード:

                        case 100:
                        			//	ポーズ中なら
                        			if(pause_flag) {
										//	考えてみましょう。
										
									} else {
	                                    calc_ch();      //キャラクタ計算
	                                    ch_move();      //キャラクタの移動制御
	                                    cshot_main();   //自機ショットメイン
	                                    enemy_main();   //敵処理メイン
	                                    shot_main();    //ショットメイン
	                                    out_main();     //当たり計算
	                                    effect_main();  //エフェクトメイン
	                                    graph_main();   //描画メイン
	                                }
                                    stage_count++;  //60カウント(60fps)で1秒
                                    break;
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#6

投稿記事 by mj » 12年前

>softya(ソフト屋) さん、プログラムのヒントを下さってありがとうございます。

ゲームの実行処理中にポーズキー入力があった場合の処理を付け加えてみました。
ポーズキー(A)が押された際にフラグをオンにしてif(pause_flag)の処理が実行され、
更新処理と描画処理を行うようにしてみたのですが下記を実行するとゲーム中に
ポーズキーを押すと画面は停止しますがその後メニューが表示されません。
ここでもループ脱出用にBキーを設定しているのでAを押すとポーズ、Bを押すと
ポーズを解除という処理はうまくいっているようです。
こちらに関しまして、実行処理中にまだ何か問題があるのでしょうか。

コード:

int ProcessLoop()
{
        if(ProcessMessage()!=0)//ウィンドウの×ボタンが押されたら終了する
		{
			return -1;//プロセス処理がエラーなら-1を返す
		}
		if(ClearDrawScreen()!=0)//画面をクリア
		{
			return -1;//画面クリア処理がエラーなら-1を返す
		}
        GetHitKeyStateAll_2();//現在のキー入力処理を行う
		GetHitPadStateAll();  //現在のパッド入力処理を行う
        return 0;
}

int game_main()//ゲーム実行
{
	ChangeWindowMode(TRUE);//ウィンドウモード
	if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) //初期化と裏画面化
	{
		return -1;
	}
	while(ProcessLoop()==0)//while文一周で1フレームを表します(60フレームで1秒:60FPS(=60F/s))
	{//メインループ
				music_ini();
			    switch(func_state)
				{
					    case 0:
									load();         //データロード
									first_ini();	//初回の初期化
									func_state=99;
									break;
						case 99://STGを始める前に行う初期化
									ini();
									load_story();
									func_state=100;
									break;
					    case 100:
									//ポーズ中なら
									if(pause_flag)
									{
										while(1)
										{
											Pose_Update();//更新処理
											Pose_Draw();//描画処理
											if(CheckHitKey(KEY_INPUT_B)==1)
											{
												pause_flag=0;//ポーズフラグオフ
												 break;
											}
										}
										game_main();
									}
                                    else 
									{
                                        calc_ch();      //キャラクタ計算
                                        ch_move();      //キャラクタの移動制御
                                        cshot_main();   //自機ショットメイン
                                        enemy_main();   //敵処理メイン
                                        shot_main();    //ショットメイン
                                        out_main();     //当たり計算
                                        effect_main();  //エフェクトメイン
                                        graph_main();   //描画メイン
                                    }
                                    stage_count++;  
                                    break;
						default:
									printfDx("不明なfunc_state\n");
									break;
				}
		music_play();

		if(CheckHitKey(KEY_INPUT_A)==1)
		{
			pause_flag=1;//ポーズフラグオン
		}
		ScreenFlip();//裏画面を表画面に反映
		count++;
	 }
	return 0;
}

derok
記事: 51
登録日時: 12年前

Re: ポーズメニューの作り方について

#7

投稿記事 by derok » 12年前

ちゃんと返信読みましたか?
ループを別に設けては行けません、と書かれているはずですが?
ScreenFlipを呼び出していないのに描画されるわけがありません。

mj

Re: ポーズメニューの作り方について

#8

投稿記事 by mj » 12年前

>derok さん、ご指摘ありがとうございます。肝心な部分を忘れておりました。

ポーズメニューの処理にswitchを使用してみました。case 0でポーズメニューの
選択肢(メインメニュー/ゲームに戻る/設定)を表示させ、何れかを選択したら
case 10へと処理を移動させる。というような感じにしてみたのですが如何でしょうか。

コード:

int ProcessLoop()
{
        if(ProcessMessage()!=0)//ウィンドウの×ボタンが押されたら終了する
		{
			return -1;//プロセス処理がエラーなら-1を返す
		}
		if(ClearDrawScreen()!=0)//画面をクリア
		{
			return -1;//画面クリア処理がエラーなら-1を返す
		}
        GetHitKeyStateAll_2();//現在のキー入力処理を行う
		GetHitPadStateAll();  //現在のパッド入力処理を行う
        return 0;
}

int game_main()//ゲーム実行
{
	ChangeWindowMode(TRUE);//ウィンドウモード
	if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) //初期化と裏画面化
	{
		return -1;
	}
	while(ProcessLoop()==0)
	{//メインループ
				music_ini();
			    switch(func_state)
				{
					    case 0:
									load();         //データロード
									first_ini();	//初回の初期化
									func_state=99;
									break;
						case 99://STGを始める前に行う初期化
									ini();
									load_story();
									func_state=100;
									break;
					    case 100:
									//ポーズ中なら
									if(pause_flag)
									{	
										switch(pause_state)
										{
											case 0:
													Pause_Update();//更新処理
													Pause_Draw();//描画処理
													//ポーズメニューの何れかが選択されたら
													if(CheckStateKey(KEY_INPUT_Z)==1)
													{
														pause_state=10;
													}
													break;
											case 10:
													SceneMgr_Update();  //更新
													SceneMgr_Draw();	//描画
													break;
										}
									}
                                    else 
									{
                                        calc_ch();      //キャラクタ計算
                                        ch_move();      //キャラクタの移動制御
                                        cshot_main();   //自機ショットメイン
                                        enemy_main();   //敵処理メイン
                                        shot_main();    //ショットメイン
                                        out_main();     //当たり計算
                                        effect_main();  //エフェクトメイン
                                        graph_main();   //描画メイン
                                    }
                                    stage_count++;
                                    break;
						default:
									printfDx("不明なfunc_state\n");
									break;
				}
		music_play();

		if(CheckHitKey(KEY_INPUT_A)==1)
		{
			pause_flag=1;//ポーズフラグオン
		}

		ScreenFlip();//裏画面を表画面に反映
		count++;
	 }
	return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#9

投稿記事 by softya(ソフト屋) » 12年前

pause_stateの初期化やら、pause_flagを無効にする処理やら肝心なものが抜けまくっている気がします。
あとpause_stateを使うなら0はポーズなしって事でpause_flagを無用に出来ると思います。

ところで、
SceneMgr_Update(); //更新
とか何をする処理でしょう?意味のある関数の名前を付けましょう。
[メニューへ戻る],[ゲームを続行する],[オプション]のどれに当たるのでしょうか?
それぞれの動作をさせるアクションも書いてないので予定している動作と書かれているコードが一致していないと思われます。

それとポーズメニュー中は、背景を描画しなくて良いのですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#10

投稿記事 by mj » 12年前

>softya(ソフト屋)さん

ポーズメニューの内容は[メニューへ戻る],[ゲームを続行する],[オプション]と
設定してあり、メニューへ戻る選択時に各要素の初期化を行う関数を呼び出し
func_stateやpause_state,pause_flag等の初期化はそこで行っております。
SceneMgr_Update();はメインメニュー(ゲーム起動時の画面)制御用の関数です。
あと、まだ背景は設定していないためブラック画面の状態です。
いろいろと外部ファイルで処理をしている部分があるのでその部分のファイルも
合わせて記載させて頂きます。

コード:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) 
	{
		return -1;//初期化と裏画面化
	}

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 )//画面更新 & メッセージ処理 & 画面消去
		{
			GetHitKeyStateAll_2();    //キーボードの更新

	        SceneMgr_Update();  //更新
		    SceneMgr_Draw();    //描画
		}

    DxLib_End();//DXライブラリ終了処理
    return 0;
}

コード:

static eScene Scene = eScene_Menu;    //シーン管理変数

//更新
void SceneMgr_Update()
{
    switch(Scene){       //シーンによって処理を分岐
    case eScene_Menu:    //現在の画面がメニューなら
        Menu_Update();   //メニュー画面の更新処理をする
        break;//以下略
    case eScene_Game:
        Game_Update();
        break;
    case eScene_Config:
        Config_Update();
        break;
	case eScene_Pause:
        Pause_Update();
        break;
    }
}

//描画
void SceneMgr_Draw()
{
    switch(Scene){      //シーンによって処理を分岐
    case eScene_Menu:   //現在の画面がメニュー画面なら
        Menu_Draw();    //メニュー画面の描画処理をする
        break;//以下略
    case eScene_Game:
        Game_Draw();
        break;
    case eScene_Config:
        Config_Draw();
        break;
	case eScene_Pause:
        Pause_Draw();
        break;
    }
}

コード:

 
// 引数 nextScene にシーンを変更する
void SceneMgr_ChangeScene(eScene NextScene)
{
    Scene = NextScene;
}

//更新
void Config_Update()
{
    if(CheckStateKey(KEY_INPUT_ESCAPE)!=0)//Escキーが押されていたら
	{
        if(func_state>0)
		{
			SceneMgr_ChangeScene(eScene_Pause);
		}
		else
		{
			SceneMgr_ChangeScene(eScene_Menu);
		}
    }
}

//描画
void Config_Draw()
{
    DrawString(0, 0,"設定画面です。",GetColor(255,255,255));
    DrawString(0,20,"Escキーを押すとメニュー画面に戻ります。",GetColor(255,255,255));
}

コード:

const static int GAME_Y   = 240;    //「ゲーム」文字のy位置
const static int CONFIG_Y = 270;    //「設定」文字のy位置

static int NowSelect = eMenu_Game;    //現在の選択状態(初期はゲーム選択中)

//更新
void Menu_Update(){
    if(CheckStateKey(KEY_INPUT_DOWN)==1)//下キーが押されていたら
	{
        NowSelect = (NowSelect+1)%eMenu_Num;//選択状態を一つ下げる(導き出される解は0/1)
    }
    if(CheckStateKey(KEY_INPUT_UP)==1)//上キーが押されていたら
	{
        NowSelect = (NowSelect+(eMenu_Num-1))%eMenu_Num;//選択状態を一つ上げる(導き出される解は0/1)
    }
    if(CheckStateKey(KEY_INPUT_Z)==1)//Zキーが押されたら
	{
        switch(NowSelect){//現在選択中の状態によって処理を分岐
        case eMenu_Game://ゲーム選択中なら
            SceneMgr_ChangeScene(eScene_Game);//シーンをゲーム画面に変更
            break;
        case eMenu_Config://設定選択中なら
            SceneMgr_ChangeScene(eScene_Config);//シーンを設定画面に変更
            break;
        }
    }
}

//描画
void Menu_Draw(){
    DrawString(200, 150,     "メインメニュー画面です。",GetColor(255,255,255));
    DrawString(200, 170,     "上下キーを押し、Zキーを押して下さい。",GetColor(255,255,255));
    DrawString(280, GAME_Y,  "ゲームスタート",GetColor(255,255,255));
    DrawString(280, CONFIG_Y,"設定",GetColor(255,255,255));
    int y=0;//初期化
    switch(NowSelect)//現在の選択状態に従って処理を分岐
	{
		case eMenu_Game://ゲーム選択中なら
			y=GAME_Y;    //ゲームの座標を格納
			break;
		case eMenu_Config://設定選択中なら
			y=CONFIG_Y;    //設定の座標を格納
        break;
    }
    DrawString(250, y, "■", GetColor(255,255,255));
}

コード:

 
//更新
void Game_Update()
{
	if(pause_flag==1)
	{	
		SceneMgr_ChangeScene(eScene_Pause);
	}
}

//描画
void Game_Draw()
{
	pause_flag=0;//ポーズフラグオフ
	pause_state=0;
	game_main();
}

コード:

const static int MENU_Y   = 240;	//「メニュー」文字のy位置
const static int GAME_Y   = 270;    //「ゲーム」文字のy位置
const static int CONFIG_Y = 300;    //「設定」文字のy位置

static int NowSelect = pMenu_Menu;    //現在の選択状態(初期はゲーム選択中)

//更新
void Pause_Update(){
    if(CheckStateKey(KEY_INPUT_DOWN)==1)//下キーが押されていたら
	{
        NowSelect = (NowSelect+1)%pMenu_Num;//選択状態を一つ下げる(導き出される解は0/1)
    }
    if(CheckStateKey(KEY_INPUT_UP)==1)//上キーが押されていたら
	{
        NowSelect = (NowSelect+(pMenu_Num-1))%pMenu_Num;//選択状態を一つ上げる(導き出される解は0/1)
    }
    if(CheckStateKey(KEY_INPUT_Z)==1)//Zキーが押されたら
	{
        switch(NowSelect){//現在選択中の状態によって処理を分岐
        case pMenu_Menu://メニュー選択中なら
			game_ini();//ゲーム内の初期化←ここで色々と初期化します
            SceneMgr_ChangeScene(eScene_Menu);//シーンをメニュー画面に変更
            break;
        case pMenu_Game://ゲーム選択中なら
            SceneMgr_ChangeScene(eScene_Game);//シーンをゲーム画面に変更
            break;
		case pMenu_Config://設定選択中なら
            SceneMgr_ChangeScene(eScene_Config);//シーンをオプション画面に変更
            break;
        }
    }
}

//描画
void Pause_Draw(){
    DrawString(200, 150,     "ポーズメニュー画面です。",GetColor(255,255,255));
    DrawString(200, 170,     "上下キーを押し、Zキーを押して下さい。",GetColor(255,255,255));
    DrawString(280, MENU_Y,  "メインメニューへ戻る",GetColor(255,255,255));
    DrawString(280, GAME_Y,"ゲームに戻る",GetColor(255,255,255));
    DrawString(280, CONFIG_Y,"設定",GetColor(255,255,255));
    int y=0;//初期化
    switch(NowSelect)//現在の選択状態に従って処理を分岐
	{
		case pMenu_Menu://メニュー選択中なら
			y=MENU_Y;    //メニューの座標を格納
			break;
		case pMenu_Game://ゲーム選択中なら
			y=GAME_Y;    //ゲームの座標を格納
			break;
		case pMenu_Config://設定選択中なら
			y=CONFIG_Y;    //設定の座標を格納
        break;
    }
    DrawString(250, y, "■", GetColor(255,255,255));
}
こちらのソースを記載しましたがsoftya(ソフト屋)さん達の指摘を受けて
色々と修正している最中であるため実行はできるのですが不具合が
いくつか発生しております。分かっているのは以下の通りです。
①ポーズメニューを表示させた際、ゲームに戻るを2度押さないゲームプレイ画面に戻れない
②ポーズメニューからメインメニューへと戻った後、メインメニューから設定を選択し
 Escキーで設定を抜けるとポーズメニューへと移行してします。

色々と試しながらプログラムを作成しているため色々と読みにくいソースとなっており申し訳ありません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#11

投稿記事 by softya(ソフト屋) » 12年前

すいません。こちらの都合で明日回答します。

【回答】
変わりすぎてて見逃しているところがあるかも知れませんが、ポーズメニュー中の
game_ini();//ゲーム内の初期化←ここで色々と初期化します
は、ちゃんと今まで読んだデータを破棄しているか不安です。

それとポーズからコンフィグに遷移した場合に、ゲームに戻れないですが良いのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#12

投稿記事 by mj » 12年前

>softya(ソフト屋) さん、ご解答ありがとうございます。

softya(ソフト屋) さんのおっしゃっている破棄といのは初期化と解釈してよろしいのでしょうか。
game_ini();は以下のようにして現在オンになっているフラグをオフにしたり、情報を
リセットしているのです問題ないでしょうか。
(まだ修正や追加しなければならないところがいろいろとありますが)

コード:

void game_ini()
{
	func_state=0;	//ゲームを最初からスタート
	pause_state=0;	//ポーズを解除
	first_ini();	//ボタン、弾の初期化
	ini();			//ゲームの初期化
	//敵の初期化
	for(int t=0;t<ENEMY_ORDER_MAX;t++)
	{
		if(enemy[t].flag==1)
		{
			enemy[t].flag=0;
		}
	}
	//敵の弾データの初期化
	for(int n=0;n<SHOT_KND_MAX;n++)
	{
		for(int i=0;i<SHOT_BULLET_MAX;i++)
		{
			if(shot[n].bullet[i].flag==1)
			{
				shot[n].bullet[i].flag=0;
			}
		}
	}
	//キャラショットの初期化
	for(int j=0;j<CSHOT_MAX;j++)
	{
		if(cshot[j].flag==1)
		{
			cshot[j].flag=0;
		}
	}
}
また、ゲームプレイ中にポーズメニューを表示させてコンフィグ(設定)に遷移したときですが、コンフィグ(設定)
内にてEscキーを押せばポーズメニュー表示画面へと戻ることが可能です。そこからゲームに戻るを
選択してゲームプレイ画面へと戻れるようになっています。

前回の設定画面での不具合に関連してのことですがポーズメニュー内でメインメニューへ戻るを選択した
ときにgame_main()内のwhileループを抜けるにはどのような処理をすればよいのでしょうか。
おそらくwhileループ内でif(メインメニューへ戻るが選択されたされたとき)break;という処理を
行えばループを抜けてくれると思うのですが良い条件文の書き方思いつきません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#13

投稿記事 by softya(ソフト屋) » 12年前

初期化に関しては、それだけでは分かりませんが画像を読み込んでいないならOKです。読み込んでいたら読み込む前に破棄してください。
コンフィグに関しては、if(func_state>0)を見て戻るよりは戻るstateを何処かに格納しておいて、それを使ったほうが分かりやすいかと思います。

>前回の設定画面での不具合に関連してのことですがポーズメニュー内でメインメニューへ戻るを選択した
>ときにgame_main()内のwhileループを抜けるにはどのような処理をすればよいのでしょうか。
>おそらくwhileループ内でif(メインメニューへ戻るが選択されたされたとき)break;という処理を
>行えばループを抜けてくれると思うのですが良い条件文の書き方思いつきません。

game_main()内にwhileループが有ってはいけません。
WinMainで呼び出されるwhile(ProcessLoop()==0)以外は無いと言うルールを必ず守ってください。
守らず作ろうとするとややっこしいことになります。

それと現状がソースがごちゃごちゃしているので、zipファイルでどこかのアップローダにアップ出来ませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#14

投稿記事 by mj » 12年前

>softya(ソフト屋) さん

メインメニューやポーズメニューに関しましてはまだ、背景画像を用意していないので
プログラミングの館で行っていた画像の情報の破棄は現時点では行っておりません。
後々に背景画像も入れようと思っています。

前回までにメニュー回りのソースを記載しましたが確かに部分的なソースでは分かりにくいので
現状でのソースが全て記載されたものを見て頂けるのであればとてもありがたいです。
ただ、申し訳ありませんが私はアップローダというものを使用したことがないためアップの方法等が
よく分かりません。可能であるならば以前この掲示板にてプログラムのzipファイルをアップしていた
方がいたのでその方と同じ方法でアップしたいのですがどのようにアップしたらよいのでしょうか。
この掲示板にzip等をアップロードする機能があるのでしょうか。

因みに私はMicrosoft Visual C++ 2010 Expressにてソースの作成を行い、プロジェクトのファイル
容量は約195MBあります。DxLibはファイルの中に組み込まれております。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#15

投稿記事 by softya(ソフト屋) » 12年前

ここのmixc++会員登録してもらうと投稿時にzipファイルとを添付できるようになります。
会員登録は、このページ一番下に「ユーザー登録 (登録で機能拡張)」で出来ます。

あと195MBは多いですね。サーバの負荷になると思いますので全部は止めておきましょう。
ソースだけなら1MBいらないと思うので、ソースだけお願いします。

>メインメニューやポーズメニューに関しましてはまだ、背景画像を用意していないので
>プログラミングの館で行っていた画像の情報の破棄は現時点では行っておりません。
>後々に背景画像も入れようと思っています。

その他のゲーム中で使う画像も読み込む予定ではないでしょうか?
画像を再読み込みする場合は破棄しないと行けないので、それを忘れないでください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj

Re: ポーズメニューの作り方について

#16

投稿記事 by mj » 12年前

> softya(ソフト屋)さん、お早いご返答ありがとうございます。

それではヘッダファイル(.h)とソースファイル(.cpp)をまとめたものをアップしたいと思います。
mixc++での会員登録を行うのでしばしお待ちください。

>その他のゲーム中で使う画像も読み込む予定ではないでしょうか?
こちらはシーンが切り替わる毎に前シーンの画像情報を破棄するということでしょうか。
現在考えているのはメインメニューでは背景用の画像及びゲームスタート,ステージ選択,
設定等の選択肢用の文字画像を用意して設置しようと思っています。(今はDrawStringで
選択肢は表示させています。)
このメインメニューの何れかの選択肢が選択されてシーンが切り替わった場合に
メインメニューで使用された画像は破棄してシーンの切り替えを行うというようなイメージで
捉えていたのですが問題ないでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#17

投稿記事 by softya(ソフト屋) » 12年前

ポーズメニューで[メニューへ戻る]を選ぶとgame_ini();を呼び出すようなので、こういうところの資源管理(画像等)がちゃんと出来ているかが気になったのです。
気をつけるべきこととして、今の状態が後の状態への影響をあたえる場合は出来るだけややこしい手続きなしに、別の状態に移行できる仕組みを用意しておかないと面倒なバグを引き起こします。

なので、資源管理の処理は出来るだけ分かりやすい流れで動作したほうが問題を引き起こしませんし、既に読み込まれていたら破棄すると言う動作もgame_ini();内で処理したほうが良いかもしれません。

[追記]それと[メニューへ戻る]でメインメニューに戻った時にgame_ini();が自動で呼び出される仕組みと成っていたほうがシンプルな構造になる気がします。もちろん、起動後のメインメニュー時もgame_ini();が自動で呼び出される様にします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#18

投稿記事 by mj(水無月) » 12年前

>softya(ソフト屋)さん、お待たせ致しました

こちらがソースファイルとなります。プログラミングの館でのプログラミングと龍神録での
プログラミングとを何とか組み合わせたようなsoftya(ソフト屋)さんから見たら雑なものと
思われるかもしれませんがご確認の程宜しくお願い致します。

資源管理のほうは後々に画像を設定する際にsoftya(ソフト屋)さんが教えてくださったやり方で
行ってみようと思います。
添付ファイル
program.zip
(28.38 KiB) ダウンロード数: 143 回

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#19

投稿記事 by softya(ソフト屋) » 12年前

そうですね。まず、大きな変更点としてScreenFlip()やProcessMessage()やClearDrawScreen()などが各々2箇所あるのでWinMainの一箇所に統一してください。
つまり、game_main()を解体してWinMainに組み入れてください。そうしないと色々と支障があります。
これは、ゲームプログラミングの館に書いてありますが「4つの書いてはいけない処理」に該当しています。

あとGame_Draw()からgame_main();を呼び出すような機能詐欺はしては行けません。なぜなら他の人にとって意味不明ですし、一年後の自分にも意味不明だと思います。
関数名は機能名であり、関数名に相応しくない機能を搭載しては行けないのです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#20

投稿記事 by mj(水無月) » 12年前

> softya(ソフト屋)さん、ソースの方をご確認くださりありがとうございます。

あちこちにDXライブラリ3大処理があるのはいけないことだということを失念しておりました。
現在WinMainにgame_main()を組み込もうとしているのですがやり方的には下記の
ような方法でif文を設定してif文が成立したときゲームメインのswitch(func_state)が
実行されるようにすればよいでしょうか。

コード:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) //初期化と裏画面化
	{
		return -1;//初期化と裏画面化
	}
	while( ProcessLoop()==0 )//画面更新 & メッセージ処理 & 画面消去
	{
		GetHitKeyStateAll_2();    //キーボードの更新

        SceneMgr_Update();  //更新
	    SceneMgr_Draw();    //描画

		if(メインメニューでゲームスタートが選択されたら)
		{
			switch(func_state)
			{
			  //ゲーム実行処理   
			}
		}
    DxLib_End();//DXライブラリ終了処理
    return 0;
}
また、アップしたソース上ではメインメニューでゲームスタートを選択した際、Game_Draw()から
無理矢理な方法でgame_main();を呼び出してシューティングゲーム部分を実行させています。
しかし、game_main()をWinMain内で処理するとGame_Draw()関数の中身がなくなり関数の
意味がなくなってしまいます。
そうするとメインメニューでゲームスタートを選択した際、どのようにゲーム実行部分に繋がるように
すれば良いのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#21

投稿記事 by softya(ソフト屋) » 12年前

こうするべきでしょう。

コード:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {
	ChangeWindowMode( TRUE ); //ウィンドウモード
	if( DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK ) != 0 ) { //初期化と裏画面化
		return -1;//初期化と裏画面化
	}
	//	全体的な初期化処理
	
	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){//画面更新 & メッセージ処理 & 画面消去
		GetHitKeyStateAll_2();    //キーボードの更新
		
		switch( func_state ) {
			//メニュー処理からゲーム処理まで。
		}
	}
	DxLib_End();//DXライブラリ終了処理
	return 0;
}
また、アップしたソース上ではメインメニューでゲームスタートを選択した際、Game_Draw()から
無理矢理な方法でgame_main();を呼び出してシューティングゲーム部分を実行させています。
しかし、game_main()をWinMain内で処理するとGame_Draw()関数の中身がなくなり関数の
意味がなくなってしまいます。
そうするとメインメニューでゲームスタートを選択した際、どのようにゲーム実行部分に繋がるように
すれば良いのでしょうか。
そう意味でのGame_Draw()関数は不要です。
そういう風になってしまうのはプログラムの流れの設計に問題があるからで、ちゃんとfunc_stateで処理を分ければGame_Draw()も本来の機能で使えるはずです。
XxxMng_???の形式で統一するなら
GameMgr_Update(); //更新
GameMgr_Draw(); //描画
として上手く呼び出してください。

それとゲームプログラミングの館の内容が曖昧みたいなので理解しなおした方が良いかもしれません。
ゲームプログラミング設計 
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)
d.6 管理部の作り方 (似た要素のまとめ方)
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#22

投稿記事 by mj(水無月) » 12年前

>softya(ソフト屋)さん

私自身ゲームプログラミングの館の内容が曖昧になっていたかもしれません。
少し内容を振り返ってみたいと思います。

あと、管理部(Mgr)を作ったほうが良いとのことですがGameMgr_Update();で画面(シーン)の
更新情報を制御するのは分かるのですがGameMgr_Draw(); は何の制御用に作成するの
でしょうか。キャラ画像等の描画処理はゲーム実行処理部のgraph_main();で行うため
GameMgr_Draw();では何を描画させるべきなのかうまくイメージができないのですが?
そもそもDraw()関数はGameMgr_Update();で得られた画面の状態がどのようになっているかの
情報を元にキャラ画像や背景等を描画するようなものと捉えていました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#23

投稿記事 by softya(ソフト屋) » 12年前

>そもそもDraw()関数はGameMgr_Update();で得られた画面の状態がどのようになっているかの
>情報を元にキャラ画像や背景等を描画するようなものと捉えていました。

そうです。描画です。
描画する関数なので描画に専念してください。中でupdateやgame_main()を呼び出すのは描画以外を含むのでルール違反です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#24

投稿記事 by mj(水無月) » 12年前

>softya(ソフト屋)さん

なるほど、それではgame_main();で行われている処理を解体して
GameMgr_Update();(更新)部分とGameMgr_Draw();(描画)部分に
分けた後にswitch( func_state )でSceneMgr_Update()を含めて呼び
出すという流れにすれば良いのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#25

投稿記事 by softya(ソフト屋) » 12年前

この場合のSceneMgrとは何を目的とするモジュール/関数でしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#26

投稿記事 by mj(水無月) » 12年前

>softya(ソフト屋)

シーンの切り替えを管理するものです。SceneMgr()で切り替えたいシーンあるときは
この部分でどのシーンに切り替えるかの命令を発っする司令塔のようなものでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズメニューの作り方について

#27

投稿記事 by softya(ソフト屋) » 12年前

前にもらったソースコードを見る限りは、game_main();はSceneMgr_Update()とSceneMgr_Draw()と似た機能を持つものでしたが、これは2つの同じようなものを持つことになりますので、無駄でありバグの原因となりそうな部分だと思います。game_main();を解体する時点でSceneMgr_Update()とSceneMgr_Draw()は同様に解体して統合されるべきです。
あるいは、game_main();をSceneMgr_Update()とSceneMgr_Draw()に統合するかどちらかを選んでください。
game_main();系とSceneMgr_Update()とSceneMgr_Draw()の系の2つもの管理する仕組みは必要ありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

mj(水無月)
記事: 22
登録日時: 12年前
住所: 東京

Re: ポーズメニューの作り方について

#28

投稿記事 by mj(水無月) » 12年前

>softya(ソフト屋) さん

softya(ソフト屋) さん、ご意見ありがとうございます。全体的に一度それぞれの要素を構成しなおす
必要がありそうですね。これまでのご意見を参考に一度作り直してみたいとおもいます。
一旦このトピックは解決と致しますがソースが完成したら改めてご意見を伺いたいと思います。

お付き合いくださり、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る