画面の切り替えうまくできない

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

画面の切り替えうまくできない

#1

投稿記事 by よわむし » 5年前

初質問です。DXライブラリまだ独学一日目ですが簡単なゲーム作ろうとしています。
メニュー画面からゲーム画面へうまくいけないです。基本メニュー画面は動作正常。
ゲーム開始選んだらバグる、そしてゲーム説明の画面行ってからゲーム画面行って続こうとしたら何キー押しても無反応。
よろしくお願いいたします。

コード:

 #include "DxLib.h"

////自作関数
int Game();
int Arasuzi();
int ume();
int take();
int matu();

int Key[256];
int gpUpdateKey()
{
	char key[256];
	GetHitKeyStateAll(key);
	for(int i = 0; i < 256; i++)
	{
		if ( key[i] != 0)
		{
			Key[i]++;
		}
		else 
		{
			Key[i] = 0;
		}
	}
	return 0;
}

///色
int White = GetColor(255, 255, 255);
int Red = GetColor(255, 0, 0);

///menu構造体
typedef struct {
	int x, y;
	char name[ 128 ];
}MenuElement_t;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int)
{
	/// ウインドウモード
	ChangeWindowMode(TRUE);
	SetGraphMode(1024, 768,32);
	// DXライブラリの初期化
	DxLib_Init();
	///裏画面設定
	SetDrawScreen(DX_SCREEN_BACK);

	PlayMusic("BGM.mp3", DX_PLAYTYPE_LOOP);

	/////メニュー画面
	////操作説明
	int x = 100, y = 300;

	MenuElement_t MenuElement[3]={
		{80,100,"ゲーム説明"},{100,150,"ゲーム開始"},{100,200,"ゲーム終了"}
	};
	int SelectNum = 0;
	////裏画面を表画面反映&メッセージ処理&画面クリア&キーの状態更新
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
	{
		DrawFormatString(50, 50, White, "【焼肉の神】");
		
		////選択処理
		if (Key[KEY_INPUT_DOWN] == 1)
		{
			SelectNum = (SelectNum + 1) % 3;
		}
		if ( Key[KEY_INPUT_UP] == 1)
		{
			SelectNum = (SelectNum + 2) % 3;
		}
		if (Key[KEY_INPUT_DOWN] == 1 || Key[KEY_INPUT_UP] == 1)
		{
			for (int i = 0; i < 3; i++)
			{
				if (i == SelectNum)
				{
					MenuElement[i].x = 80;
				}
				else
				{
					MenuElement[i].x = 100;
				}
				
			}
		}
		////ゲーム説明
		if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 100)
		{
			ClearDrawScreen();
			while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
			{
				Arasuzi();
			}
			ScreenFlip();
		}
		////ゲーム終了処理
		if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 200)
		{
			break;
		}
		/////ゲーム画面処理
		if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 150)
		{
			SetDrawScreen(DX_SCREEN_BACK);
			ScreenFlip();
			while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
			{
				Game();
			}
			
		}
		
		///描画処理
		for (int i = 0; i < 5; i++)
		{
		
			DrawFormatString(MenuElement[i].x, MenuElement[i].y, GetColor(255, 255, 255), MenuElement[i].name);
		}
		DrawFormatString(x, y, White, "【下キーを押して選択、Enterキー押して動作】");
		
		ScreenFlip();

	}
	// DXライブラリの後始末
	DxLib_End();

	// ソフトの終了
	return 0;
}

int Arasuzi(void)
{
	printfDx("\n");
	printfDx("◎焼肉の神は俺がなる!\n");
	printfDx("あらすじ:\n");
	printfDx("ある日、<焼肉の王>という焼肉屋さんは焼肉の神を求めていた―\n");
	printfDx("「当店三つのコースのメニューそして出されている肉の種類を覚えるお客様は当店の永世VIPになります。\n");
	printfDx(" つまり、いつでも当店のご利用は無料になります。」\n");
	printfDx("\n");
	printfDx("貧乏学生のあなたの戦いは、いざ開幕ーー\n");
	printfDx("\n");
	printfDx("◎操作説明:");
	printfDx("各コースのメニューを覚えてください。\n");
	printfDx("梅コース3品、竹コース4品、松コース5品っていう形で難易度が違います。\n");
	printfDx("一品には二つ種類の肉が出されます。メニューに書いてある方を見分けて答えを入力しましょう。\n");
	printfDx("\n");
	printfDx("頑張って全コース制覇しましょう!\n");
	printfDx("\n");
	printfDx("【ESCキーでそのままゲームはじめます。】\n");

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
	{
		ClearDrawScreen();
		if (Key[KEY_INPUT_RETURN] == 1)
		{
			Game();
		}
		ScreenFlip();

	}

	return 0;

}
int Game(void)
{
	
	ClearDrawScreen();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
	{
		printfDx("コースを選んでください(対応するキーを押してください)\n");
		printfDx("上キー.梅コース 右キー.竹コース SPACEキー.松コース\n");
		if (Key[KEY_INPUT_UP] == 1)
		{
			ume();
			
		}
		if (Key[KEY_INPUT_RIGHT] == 1)
		{
			take();
			
		}
		if (Key[KEY_INPUT_SPACE] == 1)
		{
			matu();
			
		}
		break;
		
		
	}
	ScreenFlip();

	return 0;
}

int ume(void)
{

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
	{
		ClearDrawScreen();
		printfDx("梅コースのメニューは以下となります。\n");
		printfDx("カルビ、ハラミ、ロース。\n");

		ScreenFlip();

		////一品目
		////画像表示
		ClearDrawScreen();
		printfDx("\n");
		printfDx("カルビはどちらですか?(右ならAを入力、左ならBを入力)\n");

		int Harami;
		Harami = LoadGraph("ハラミ.png");
		DrawGraph(50, 100, Harami, TRUE);
		int Karubi;
		Karubi = LoadGraph("カルビ.png");
		DrawGraph(450, 100, Karubi, TRUE);


		if (Key[KEY_INPUT_A] == 1)
		{
			printfDx("正解です!\n");


			////二品目
			printf("\n");
			printf("ハラミはどちらですか?(右ならAを入力、左ならSを入力)\n");

			int Harami;
			Harami = LoadGraph("ハラミ.png");
			DrawGraph(50, 100, Harami, TRUE);
			int rose;
			rose = LoadGraph("ロース.png");
			DrawGraph(450, 100, rose, TRUE);

			if (Key[KEY_INPUT_A] == 1)
			{
				printf("正解です!\n");


				////三品目
				printf("\n");
				printf("ロースはどちらですか?(右ならAを入力、左ならSを入力)\n");

				int Karubi;
				Karubi = LoadGraph("カルビ.png");
				DrawGraph(50, 100, Karubi, TRUE);
				int rose;
				rose = LoadGraph("ロース.png");
				DrawGraph(450, 100, rose, TRUE);

				if (Key[KEY_INPUT_A] == 1)
				{
					DrawFormatString(100, 100, Red, "正解です!\n");
					DrawFormatString(100, 200, Red, "梅コースクリアです!\n");

					DrawFormatString(100, 400, Red, "Enterキーでゲーム終了です");
					if (Key[KEY_INPUT_RETURN] == 1)
					{
						break;
					}
				}
				else
				{
					DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
					return 0;
				}

			}
			else
			{
				DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
				return 0;
			}


		}
		else
		{
			DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
			return 0;
		}

		ScreenFlip();
	}
	return 0;
}  

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 画面の切り替えうまくできない

#2

投稿記事 by みけCAT » 5年前

まだ詳しく見ていないですが、DXライブラリ3大処理があちこちにあってよくないコードですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 画面の切り替えうまくできない

#3

投稿記事 by みけCAT » 5年前

基本的な考え方としては、
「今のフレームの状態と入力に基づき、描画を行い、次のフレームの状態を作る」です。
どの画面を表示するのかというのも「状態」ですし、
どのメニューが選択されているかというも「状態」です。
以下のコードのように、変数で状態を管理し、状態に応じて処理を分けると良いでしょう。

他のポイントとしては、(通常行われるように)毎フレーム画面を初期化する場合、
printfDxの出力はフレームをまたいで残るので状態が変わる直前に行い、
DrawFormatStringやDrawGraphの出力はそのフレームだけに反映されるので毎フレーム行います。
なお、画像は毎フレーム読み込むのではなく、ゲーム開始時に1回だけ読み込んでおくのがいいでしょう。

さらに、メニューを描画するループの回数が多すぎて範囲外へのアクセスが起こっていたので、修正しました。
また、自分の判断で適当にclsDx(printfDxの出力を消す)の呼び出しを入れました。
「ESCキーでそのままゲームはじめます」と出ているのにEnterキーを押さないと始まらない仕様、
および普通に考えると左が正しいのにA(右)を押さないと正解扱いにならない仕様は、一応残しました。

コード:

#include "DxLib.h"

////自作関数
int Menu();
int StartGame();
int Game();
int StartArasuzi();
int Arasuzi();
int ume();
int take();
int matu();

int Key[256];
int gpUpdateKey()
{
	char key[256];
	GetHitKeyStateAll(key);
	for(int i = 0; i < 256; i++)
	{
		if ( key[i] != 0)
		{
			Key[i]++;
		}
		else 
		{
			Key[i] = 0;
		}
	}
	return 0;
}

///色
int White = GetColor(255, 255, 255);
int Red = GetColor(255, 0, 0);

///menu構造体
typedef struct {
	int x, y;
	char name[ 128 ];
}MenuElement_t;

///現在の画面
enum CurrentStatusEnum {
	MENU,
	ARASUZI,
	GAME,
	END
} currentStatus = MENU;

/////メニュー画面
////操作説明
int x = 100, y = 300;

MenuElement_t MenuElement[3]={
	{80,100,"ゲーム説明"},{100,150,"ゲーム開始"},{100,200,"ゲーム終了"}
};
int SelectNum = 0;

///ゲーム画面の状態
enum GameSelectStatusEnum {
	SELECT,
	UME,
	TAKE,
	MATU
} gameSelectStatus = SELECT;

int gameStatus;

///画像
int Harami;
int Karubi;
int rose;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int)
{
	/// ウインドウモード
	ChangeWindowMode(TRUE);
	SetGraphMode(1024, 768,32);
	// DXライブラリの初期化
	DxLib_Init();
	///裏画面設定
	SetDrawScreen(DX_SCREEN_BACK);

	///画像の読み込み
	Harami = LoadGraph("ハラミ.png");
	Karubi = LoadGraph("カルビ.png");
	rose = LoadGraph("ロース.png");

	PlayMusic("BGM.mp3", DX_PLAYTYPE_LOOP);

	////裏画面を表画面反映&メッセージ処理&画面クリア&キーの状態更新
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0)
	{
		switch (currentStatus) {
			case MENU:
				Menu();
				break;
			case ARASUZI:
				Arasuzi();
				break;
			case GAME:
				Game();
				break;
			case END:
				break;
		}
		if (currentStatus == END) break;
	}
	// DXライブラリの後始末
	DxLib_End();

	// ソフトの終了
	return 0;
}

int Menu(void)
{
	DrawFormatString(50, 50, White, "【焼肉の神】");
	
	////選択処理
	if (Key[KEY_INPUT_DOWN] == 1)
	{
		SelectNum = (SelectNum + 1) % 3;
	}
	if ( Key[KEY_INPUT_UP] == 1)
	{
		SelectNum = (SelectNum + 2) % 3;
	}
	if (Key[KEY_INPUT_DOWN] == 1 || Key[KEY_INPUT_UP] == 1)
	{
		for (int i = 0; i < 3; i++)
		{
			if (i == SelectNum)
			{
				MenuElement[i].x = 80;
			}
			else
			{
				MenuElement[i].x = 100;
			}
			
		}
	}
	////ゲーム説明
	if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 100)
	{
		StartArasuzi();
	}
	////ゲーム終了処理
	if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 200)
	{
		currentStatus = END;
	}
	/////ゲーム画面処理
	if (Key[KEY_INPUT_RETURN] == 1 && MenuElement[SelectNum].y == 150)
	{
		StartGame();
	}
	
	///描画処理
	for (int i = 0; i < 3; i++)
	{
	
		DrawFormatString(MenuElement[i].x, MenuElement[i].y, GetColor(255, 255, 255), MenuElement[i].name);
	}
	DrawFormatString(x, y, White, "【下キーを押して選択、Enterキー押して動作】");

	return 0;
}

int StartArasuzi(void)
{
	clsDx();

	printfDx("\n");
	printfDx("◎焼肉の神は俺がなる!\n");
	printfDx("あらすじ:\n");
	printfDx("ある日、<焼肉の王>という焼肉屋さんは焼肉の神を求めていた―\n");
	printfDx("「当店三つのコースのメニューそして出されている肉の種類を覚えるお客様は当店の永世VIPになります。\n");
	printfDx(" つまり、いつでも当店のご利用は無料になります。」\n");
	printfDx("\n");
	printfDx("貧乏学生のあなたの戦いは、いざ開幕ーー\n");
	printfDx("\n");
	printfDx("◎操作説明:");
	printfDx("各コースのメニューを覚えてください。\n");
	printfDx("梅コース3品、竹コース4品、松コース5品っていう形で難易度が違います。\n");
	printfDx("一品には二つ種類の肉が出されます。メニューに書いてある方を見分けて答えを入力しましょう。\n");
	printfDx("\n");
	printfDx("頑張って全コース制覇しましょう!\n");
	printfDx("\n");
	printfDx("【ESCキーでそのままゲームはじめます。】\n");

	currentStatus = ARASUZI;
	return 0;
}

int Arasuzi(void)
{
	if (Key[KEY_INPUT_RETURN] == 1)
	{
		StartGame();
	}

	return 0;

}

int StartGame(void)
{
	clsDx();

	printfDx("コースを選んでください(対応するキーを押してください)\n");
	printfDx("上キー.梅コース 右キー.竹コース SPACEキー.松コース\n");

	currentStatus = GAME;
	gameSelectStatus = SELECT;
	gameStatus = 0;
	return 0;
}

int Game(void)
{
	switch (gameSelectStatus) {
		case SELECT:
			if (Key[KEY_INPUT_UP] == 1)
			{
				gameSelectStatus = UME;
				
			}
			if (Key[KEY_INPUT_RIGHT] == 1)
			{
				gameSelectStatus = TAKE;
				
			}
			if (Key[KEY_INPUT_SPACE] == 1)
			{
				gameSelectStatus = MATU;
				
			}
			break;
		case UME:
			ume();
			break;
		case TAKE:
			take();
			break;
		case MATU:
			matu();
			break;
	}

	return 0;
}

int ume(void)
{

	switch (gameStatus) {
		case 0:
			clsDx();
			printfDx("梅コースのメニューは以下となります。\n");
			printfDx("カルビ、ハラミ、ロース。\n");

			////一品目
			////画像表示
			ClearDrawScreen();
			printfDx("\n");
			printfDx("カルビはどちらですか?(右ならAを入力、左ならBを入力)\n");

			gameStatus = 1;
			break;
		case 1:
			DrawGraph(50, 100, Harami, TRUE);
			DrawGraph(450, 100, Karubi, TRUE);

			if (Key[KEY_INPUT_A] == 1)
			{
				printfDx("正解です!\n");


				////二品目
				printfDx("\n");
				printfDx("ハラミはどちらですか?(右ならAを入力、左ならSを入力)\n");

				gameStatus = 2;
			}
			if (Key[KEY_INPUT_S] == 1)
			{
				gameStatus = 7;
			}
			break;
		case 2:
			DrawGraph(50, 100, Harami, TRUE);
			DrawGraph(450, 100, rose, TRUE);

			if (Key[KEY_INPUT_A] == 1)
			{
				printfDx("正解です!\n");


				////三品目
				printfDx("\n");
				printfDx("ロースはどちらですか?(右ならAを入力、左ならSを入力)\n");

				gameStatus = 3;
			}
			if (Key[KEY_INPUT_S] == 1)
			{
				gameStatus = 6;
			}
			break;
		case 3:
			DrawGraph(50, 100, Karubi, TRUE);
			DrawGraph(450, 100, rose, TRUE);

			if (Key[KEY_INPUT_A] == 1)
			{
				DrawFormatString(100, 100, Red, "正解です!\n");
				DrawFormatString(100, 200, Red, "梅コースクリアです!\n");

				DrawFormatString(100, 400, Red, "Enterキーでゲーム終了です");

				gameStatus = 4;
			}
			if (Key[KEY_INPUT_S] == 1)
			{
				gameStatus = 5;
			}
			break;
		case 4:
			if (Key[KEY_INPUT_RETURN] == 1)
			{
				clsDx();
				currentStatus = MENU;
			}
			break;
		case 5:
			///三品目で間違えた状態
			DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
			break;
		case 6:
			///二品目で間違えた状態
			DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
			break;
		case 7:
			///一品目で間違えた状態
			DrawFormatString(100, 100, Red, "間違えました。また次回です。\n");
			break;
	}
	return 0;
}

int matu(void)
{
	return 0;
}

int take(void)
{
	return 0;
}
添付ファイル
yakiniku.zip
仮素材
(39.12 KiB) ダウンロード数: 145 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

よわむし

Re: 画面の切り替えうまくできない

#4

投稿記事 by よわむし » 5年前

なるほど、、、分かりました!ありがとうございます。

返信

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