ページ 11

BGMを流したいのですが・・・。

Posted: 2015年4月01日(水) 17:35
by DAIKI
現在ゲーム制作を行っている初心者のものです。
プログラミングでBGMを流そうと思い、LoadSoundMem関数とPlaySoundMem関数、StopSoundMem関数を用いて作成したのですが、

・最初の段階でBGMがノイズのような状態になってしまう
・BGMの切り替えができない
・2点目の問題により2曲目が再生できない

上記のような状態となってしまっています。
おそらくノイズのような状態はCountがループしていることによりBGMの再生が最初からという状態が高速に行われてしまっているのかなと思うのですが、改善することが出来ずに困っています。

どのような処理を加えることで上記の問題を解決することが出来るか、BGMをうまく再生することが出来るか改善点を教えていただけると嬉しいです。
よろしくお願いいたします。

使用環境はVisual Studio for Desktop 2013,Visual C++2010です。


main.cpp

コード:

#include<Dxlib.h>
#include"control.h"


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	/*ウインドウモード設定、Dxライブラリ初期化設定、描画先を裏画面に設定*/
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

	int t1;

	SetOutApplicationLogValidFlag(FALSE);						/*実行後にログを吐き出さない関数*/

	OpBGM();
	GameBGM();

	Option();													/*初期化関数*/


	/*裏画面を表画面に反映、メッセージ処理、画面をクリア*/
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0){

		t1 = GetNowCount();

		Step1();

		Step2();

		while (GetNowCount() - t1 < 17);						/*どんなモニタを使用していても60msec待機する*/
	}

	DxLib_End();												/*Dxライブラリ終了処理*/

	return(0);
}

control.cpp

コード:

#include<DxLib.h>
#include"control.h"

#define MAX 50


int Count = 0;																							/*カウントを格納する変数*/
int Time = 0;																							/*時間を格納する変数*/

int WHITE;																								/*WHITEを指定する*/

int Check_Color[MAX] = { 0, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 0, 1, 2, 1, 0, 1, 0, 2, 1};					/*だるまの順番*/
int Color[3];																							/*だるまの色指定*/

int p[4] = { KEY_INPUT_LEFT, KEY_INPUT_DOWN, KEY_INPUT_RIGHT, KEY_INPUT_RETURN };						/*キー指定*/
int Check_Push[4];																						/*押されたキーを格納*/
int Old_Push[4] = { 0, 0, 0, 0 };																		/*過去に押されたキーを格納*/

int Font_30;																							/*文字のフォントを設定*/
int Font_100;
int Font_130;
int Font_300;
int Font_600;

int Handle1;																							/*BGMを格納*/
int Handle2;

char key[256];																							/*キーを格納する変数*/
char Allow[3][3] = { "←", "↓", "→" };																/*矢印を格納する変数*/


/*初期設定*/
void Option(){
	
	WHITE = GetColor(255, 255, 255);																	/*WHITEの色を設定*/
	Color[0] = GetColor(255, 0, 0);																		/*Color[0]に赤を設定*/
	Color[1] = GetColor(0, 255, 0);																		/*Color[1]に緑を設定*/
	Color[2] = GetColor(0, 0, 255);																		/*Color[2]に青を設定*/

	Font_30 = CreateFontToHandle(NULL, 30, 3);															/*文字のフォントの大きさや太さを設定*/
	Font_100 = CreateFontToHandle(NULL, 100, 5);
	Font_130 = CreateFontToHandle(NULL, 130, 5);
	Font_300 = CreateFontToHandle(NULL, 300, 5);
	Font_600 = CreateFontToHandle(NULL, 600, 5);

	Handle1 = LoadSoundMem("BGM/Op.Mp3");
	Handle2 = LoadSoundMem("BGM/Main.Mp3");
}


/*スキップを表示*/
void Skip(){
	DrawStringToHandle(480, 450, "SKIP:Enter", WHITE, Font_30);
}


/*リトライを表示*/
void Retry(){
	DrawStringToHandle(470, 450, "RETRY:Enter", WHITE, Font_30);
}


/*オープニングのBGM*/
void OpBGM(){
	if (Count==0)
		PlaySoundMem(Handle1, DX_PLAYTYPE_BACK);

	if (Count == 330)
		StopSoundMem(Handle1);
}


/*ゲーム中のBGM*/
void GameBGM(){
	if (Count == 1020)
		PlaySoundMem(Handle2, DX_PLAYTYPE_BACK);
}


/*オープニング設定*/
void Opening(){
	if (Count < 270){
		if (Count >= 0){
			if (Count < 10)
				DrawStringToHandle(680 - 60 * Count, 50, "あなたの", WHITE, Font_100);
			else
				DrawStringToHandle(80, 50, "あなたの", WHITE, Font_100);
		}
		if (Count >= 90){
			if (Count < 100)
				DrawStringToHandle(180 - 600 + 60 * (Count - 90), 150, "瞬発力は", WHITE, Font_100);
			else
				DrawStringToHandle(180, 150, "瞬発力を", WHITE, Font_100);
		}
		if (Count >= 180){
			if (Count < 190){
				DrawStringToHandle(630 - 60 * (Count - 180), 250, "測って", WHITE, Font_100);
				DrawStringToHandle(320 - 600 + 60 * (Count - 180), 250, "みる?", WHITE, Font_100);
			}
			else{
				DrawStringToHandle(30, 250, "測って", WHITE, Font_100);
				DrawStringToHandle(320, 250, "みる?", WHITE, Font_100);
			}
		}
	}

	if (Count >= 270 && Count < 330)
		DrawStringToHandle(60, 190, "ルール説明", WHITE, Font_100);
	if (Check_Push[3] == 1)																					/*ENTERキーが押された瞬間*/
		Count = 330;																						/*オープニングが終了する時間Count=300へ飛ばす*/

	PlaySoundMem(Handle1, DX_PLAYTYPE_BACK);

	Skip();																									/*Skipを表示する*/
}


/*キーの入力状態を判断(左キー…p[0],下キー…p[1],右キー…p[2],Enterキー…p[3])*/
void KeyCheck(){
	for (int i = 0; i < 4; i++){
		if (key[p[i]] == 1 && Old_Push[i] == 0)															/*過去の入力状態が0で、今の瞬間に1になったら*/
			Check_Push[i] = 1;																				/*押された状態を表す関数に1を加える*/
		else
			Check_Push[i] = 0;																				/*キーが押されていなくても、今の瞬間でなければ何もしない*/
	}

	for (int i = 0; i < 4; i++)
		Old_Push[i] = key[p[i]];																			/*現在のキー入力状態を、過去の入力状態に保存*/
	
}


/*説明画面(0…左キー、1…下キー、2…右キー)*/
void Demo(){
	static int x0[6] = { 0, 1, 2, 1, 0, 2 };																/*Xはデモで押されるキーの順番*/
	static int x1[2] = { 0, 2 };

	for (int i=0 ; i < 3; i++){
		key[p[i]] = 0;
	}

	for (int i = 0; i < 6; i++){																			/*正解例を表示*/
		if (Count>500 + i * 60 && Count <= 560 + i * 60)
			key[p[x0[i]]] = 1;
	}

	for (int i = 0; i < 2; i++){																			/*間違い入力例を表示*/
		if (Count>920 + i * 60 && Count <= 980 + i * 60)
			key[p[x1[i]]] = 1;
	}
}


/*説明画面2*/
void Demo2(){
	if (Count <= 1040){																						/*カウントダウン前の説明画面*/
		DrawStringToHandle(20, 20, "ルール説明", WHITE, Font_30);

		if (Check_Push[3] == 1)																				/*ENTERが押されたら「Are You Ready?」まで画面を移動*/
			Count = 1040;																					/*画面移動のためのCount*/

		Skip();																								/*Skip表示*/
	}

	if (Count == 1140){																						/*画面にだるまが表示される前にだるまの色を初期化*/
		for (int i = 0; i < MAX; i++){
			Check_Color[i] = GetRand(2);																	/*0~2までの乱数を入力(0…赤、1…緑、2…青)*/

			if (i > 1){
				if (Check_Color[i] == Check_Color[i - 1] && Check_Color[i - 1] == Check_Color[i - 2])		/*3つ連続で同じ色なら乱数を入れ直す*/
					i--;																					/*iを戻す*/
			}
		}
	}
}



/*カウントダウン*/
void Countdown(){
	DrawStringToHandle(380 - (Count - 380), 180, "同じ色の十字キーを素早く押せ!", WHITE, Font_30);

	/*カウントダウン*/
	if (Count > 1040 && Count <= 1140){
		DrawStringToHandle(150, 120, "Are You", WHITE, Font_100);
		DrawStringToHandle(180, 280, "Ready?", WHITE, Font_100);
	}
	if (Count > 1140 && Count <= 1230)
		DrawStringToHandle(320-70, 40, "3", WHITE, Font_300);
	if (Count > 1230 && Count <= 1320)
		DrawStringToHandle(320-70, 40, "2", WHITE, Font_300);
	if (Count > 1320 && Count <= 1410)
		DrawStringToHandle(320-70, 40, "1", WHITE, Font_300);
}


/*だるまの表示*/
void Daruma_Display(int Now){
	int n;

	n = Now;

	for (int i = 0; i < 15; i++){
		DrawBox(320 - 30, 300 - (i + 1) * 20, 320 + 30, 300 - i * 20, Color[Check_Color[n]],TRUE);
		DrawBox(320 - 30, 300 - (i + 1) * 20, 320 + 30, 300 - i * 20, WHITE, FALSE);

		n++;

		if (n >= MAX)																						/*15個表示する前に最大まで表示したらブレイク*/
			break;
	}
}


/*矢印と円の表示*/
void Circle_Display(){
	for (int i = 0; i < 3; i++){																			/*矢印の円を表示*/
		if (key[p[i]] == 1){																				/*入力されている矢印は大きな円*/
			DrawCircle(170 + i * 150, 400, 70, Color[i]);
			DrawFormatStringToHandle(105 + i * 150, 340, WHITE, Font_130, Allow[i]);
		}
		else{																								/*違う場合は小さな円*/
			DrawCircle(170 + i * 150, 400, 50, Color[i]);
			DrawFormatStringToHandle(120 + i * 150, 350, WHITE, Font_100, Allow[i]);
		}
	}
}


/*ゲームの処理*/
void Game(){
	static int Pass = 0, Correct = 0, Fault = 0, Fault_Count = 0;											/*Correct…正解数(最大MAX),Fault=×が表示される時間*/

	Daruma_Display(Correct);																				/*nから上までだるまを表示*/

	if (Fault == 0 && Time == 0){																			/*Fault>0は入力不可…×表示状態の事。Timeはクリアしたときの時間を格納する変数*/
		if (Check_Push[Check_Color[Correct]] == 1)															/*現在一番下にあるだるまに対応したキーが正しく入力されたら*/
			Correct++;																						/*次のダルマへ*/
		else{
			for (int i = 0; i < 3; i++){																	/*他の何かのキーが入力されていたら*/
				if (Check_Push[i] == 1){
					Fault = 60;
					Fault_Count++;
				}
			}
		}
		if (Correct == MAX)																					/*正解数とMAXが同じになったら*/
			Time = Count;																					/*クリアーした時間を格納する*/
	}

	Circle_Display();																						/*矢印、円を表示*/

	if (Fault>0 && Time == 0){																				/*Faultの時は×を表示*/
		DrawStringToHandle(320 - 300, 240 - 300, "×", Color[0], Font_600);
		Fault--;
	}
	if (Time > 0){																							/*クリアした場合*/
		DrawStringToHandle(200, 50, "Clear!", WHITE, Font_100);
		DrawFormatStringToHandle(250, 200, WHITE, Font_30, "TIME %.3f", (double)(Time - 1410)*17.0f / 1000.0f);
		DrawFormatStringToHandle(240, 250, WHITE, Font_30, "ミス回数 %d回", Fault_Count);
	
		Retry();

		if (Check_Push[3] == 1){																			/*ENTERが押されたら初期化してリスタート*/
			Fault_Count = 0;
			Time = 0;
			Count = 1040;
			Correct = 0;
		}
	}
	if (Count > 1410 && Count <= 1500)																		/*ゲームが始まって90カウントは表示*/
		DrawStringToHandle(170, 190, "START!", WHITE, Font_100);
}


void Step1(){
	GetHitKeyStateAll(key);

	if (Count >= 330 && Count <= 1410)
		Demo();																								/*デモの間push*/

	KeyCheck();																								/*キーが押されたかどうか判定*/
}


void Step2(){
	if (Count >= 0 && Count < 330)																			/*オープニング*/
		Opening();

	else if (Count >= 330 && Count <= 1410){																/*説明画面*/
		if (Count <= 1040 || Count > 1140)
			Game();
		Demo2();

		Countdown();
	}

	else{																									/*ゲーム画面*/
		Game();
	}

	Count++;																								/*Countを加算*/
}

control.h

コード:

#ifndef DEF_PLAYER_H

#define DEF_PLAYER_H


void Option();

void Skip();

void Retry();

void OpBGM();

void GameBGM();

void Opening();

void KeyCheck();

void Demo();

void Demo2();

void Countdown();

void Daruma_Display();

void Circle_Display();

void Game();

void Step1();

void Step2();


#endif

Re: BGMを流したいのですが・・・。

Posted: 2015年4月01日(水) 17:39
by みけCAT
・OpBGM()とGameBGM()をメインループの中で呼ぶようにする
・Opening()の中でPlaySoundMem(Handle1, DX_PLAYTYPE_BACK)を呼ばないようにする

テストしていませんが、これでどうですか?

Re: BGMを流したいのですが・・・。

Posted: 2015年4月01日(水) 18:14
by DAIKI
みけCATさん、返信ありがとうございます。

2つめのOpening関数内でOpBGMは改善途中で残してしまっていたものでした。すみません・・・。

1つめのメインループ内でOpBGM関数とGameBGM関数を呼び出すという事はmain.cppのwhileループの中に呼び出すという事でしょうか?


基本的な部分ですみません・・・。

Re: BGMを流したいのですが・・・。

Posted: 2015年4月01日(水) 18:24
by みけCAT
DAIKI さんが書きました:1つめのメインループ内でOpBGM関数とGameBGM関数を呼び出すという事はmain.cppのwhileループの中に呼び出すという事でしょうか?
はい。「ループの中に」ではなく、「ループの中で」ですね。
もしくは、Step1()またはStep2()に入れてもいいかもしれません。

Re: BGMを流したいのですが・・・。

Posted: 2015年4月01日(水) 18:32
by DAIKI
みけCATさん、ありがとうございました。

whileループの中で呼び出したらうまくBGMが流れました。
ありがとうございました!