細かいところを追加していくパート2

これは完全に寄り道
タイトルとかプレイ画面とか寂しいのでBGMつけてみよう。のコーナー
まずは、フリーのBGMを探してください。Siv3Dでは.mp3や.wavなどが再生でる。
僕はここのものを使いますイワシロ音楽素材
困った時の、niconicoコモンズ、ここは授業中にも紹介したよね
音声データを用意したら、fontやtextureと同様にAsset化してしまおう。
とりあえず、3種類用意しよう。

  1. タイトル画面用(普通の音楽データ)
  2. プレイ画面用(普通の音楽データ)
  3. クリア時のジングル(おめでとう音:短めのファンファーレ的な奴)
Main.cpp
	AudioAsset::Register(U"STAGE_SND", U"タイトル用.mp3");
	AudioAsset::Register(U"TITLE_SND", U"プレイ画面用.mp3");
	AudioAsset::Register(U"CLEAR_SND", U"クリアジングル.mp3");

データ多くなってきたのでちょっと読み込みに時間がかかるようになってきたね。

次は、さっそく鳴らしていく。
まずはタイトル画面から。
こんな感じで音楽ファイルを制御できる。簡単だよね。
あとは同じようにほかの鳴らしたいところで鳴らしてやればいいさー

gameSequence.cpp
void UpdateTitle(GAME_STATE& _state)
{
	if (!AudioAsset(U"TITLE_SND").isPlaying()) {//すでになっている状態でなければ
		AudioAsset(U"TITLE_SND").setVolume(0.5); //ボリューム調整(任意)
		AudioAsset(U"TITLE_SND").setLoop(true);  //ずっとタイトル画面流していたい人用ループ設定オン  
		AudioAsset(U"TITLE_SND").play(); //音楽スタート
	}
	if (KeySpace.down())
	{
		_state = GAME_STATE::PLAY;
		AudioAsset(U"TITLE_SND").stop();//シーン切り替える前にタイトル音楽をストップ
	}
Fig. 1: soundを追加した版(音量注意)

クリアしたときになんかすぐ場面切り替わるやつ

次にプレイしていて気持ち悪いのは、クリアするとすぐにクリアシーンに移行し、クリックすると次に進むっていう仕様
これはとてもよくない。。。
ゲームをプレイするうえで、入力デバイスがあっちゃこっちゃいくのはとてもまずい状況である。
キーボードを使っていたと思うと、急にコントローラーを持て!コントローラーを使っていたら、急にマウスをクリックしろ!
これはもはや嫌がらせである。。。
今回は、スタートもキーボードにしちゃったので操作はなるべくキーボードだけで完結させてあげたい
さてどうしようか?
これにはタイマーを使ってみよう。タイマーはScene::DeltaTime()を使うと、フレーム間の経過時間をdouble(秒)でとってこれる。
したがって、5秒待ちたければ、カウントダウンタイマー double CDTimer = 5.0;で初期化しておいて、
毎フレーム CDTimer = CDTimer - Scene::DeltaTime();していって、<0になった所がタイマー切れ(Time is Up)のところだよね!

このタイマーは、Mainでは使わないので(gameSequence.cpp内で見えていれば十分)gameSequence.cpp内で宣言する
ついでにタイマーがオンかオフかのフラグとしてbool isTimerOnも作っとく

gameSequence.cpp
double CDTimer = 6.0;
bool TimerOn = false;

こっからの設計はこんな感じ

  1. ステージクリア?
    1. ステージBGMをストップ & タイマースタート
    2. クリアジングルを鳴らす(5秒程度のもの)
      1. 3秒間完成状態の画面を見せる
    3. 3秒たったら、クリアメッセージの画面へ移行
      1. ここでも3秒間Try Next Stage的なメッセージを見せる
      2. 3秒たったら、ステージを進めて、プレイ画面へ
  1. if(checkClear())
    1. STAGE_SND .stop() isTimerOn = true
    2. CLEAR_SND .play()(5秒程度のもの)
      1. 3秒は 何もしない
    3. CDTimer < 3 ⇒ state = CLEAR
      1. CDTimer > 0 なら Try Next Stage的なメッセージを見せる
      2. CDTimer < 0 ⇒ ステージを進めて、state = PLAY, isTimerOn = false , CDTimer = 6

こんぐらい書くとできるかな?
ついでに、クリアしたときにジングルが鳴るが、その間にプレイヤーが動いてクリア状態を崩してしまうことがある。
それってちょいめんどくさいことが起こるので、クリアしたら入力を受け付けない=クリアしてない時だけ入力を受け付ける
って処理に変更しておく!

これらのテクニックを合わせると、何秒後に画面遷移、とか、イベント事が起こったら何秒間停止とかの処理ができる。(超うれしい!)

void UpdatePlay(GAME_STATE& _state)
{
	if (!AudioAsset(U"STAGE_SND").isPlaying())
	{
	ステージBGMをスタートさせる処理省略
	}
	if (CheckClear(maps[crrStageNumber]))
	{
		ステージBGMストップ
		if (!AudioAsset(U"CLEAR_SND").isPlaying())
		{
			クリアジングルのボリュームセット
             クリアジングルをプレイ
			isTimerOnフラグをOnに
		}
		if (CDTimerが3秒切ってたら) {
			_stateをCLEARに変更
		}
	}
    else
        {   //クリア状態じゃなかったら新しい入力をとってくる
	    direction nextDir = GetDirection();
	    MoveObject(nextDir, maps[crrStageNumber]);
        }
	if (タイマーオンですか?)
		CDTimerをScene::DeltaTime()だけ減らしてやる
 
        シフトキーの奴とか省略
}
 
省略
 
void UpdateClear(GAME_STATE& _state)
{
	if (タイマーオンですか?)
		CDTimerをScene::DeltaTime()だけへらしてやる
 
	if(タイマーが0切ったら){
		//ここは今までのステージを進める処理
                ステージ増やして;
		if (ステージがMAX_STAGE_NUMになってたら)
			crrStageNumberをエラーにならんようにMAX_STAGE_NUM - 1に更新する(変な処理だけど、後で治そう)
		 _stateをGAME_STATE::PLAYに変更(タイマー0=3秒間 次のステージへ!の画面を見せ終わった)
		//タイマーのリセット処理
                TimerOnをOFFに;
		CDTimerを6に初期化;
	}
}

実行例

Fig. 2: カウントダウンタイマーで入力制御と画面制御

こまかいところうんぬん その3 へ