第09回 音声の管理と再生
2 / 4 状態遷移とBGMの切り替え
このステップの目的
ゲーム画面の遷移に合わせてBGMを切り替え、古い曲を停止して新しい曲をループ再生する仕組みを実装します。
BGMの二重再生を防ぐ制御
BGMは通常、画面の雰囲気に合わせて1曲だけがループ再生されます。
前のBGMを止めずに次の曲を再生すると、2曲が同時に鳴ります。不快な音割れや不協和音の原因になります。
SoundManager::PlayBgm()では、現在の曲を必ず止めてから新しい曲を再生します。
SoundManager.cppcpp
void SoundManager::PlayBgm(Id id)
{
// BGMは同時に1曲だけ再生する
StopBgm();
currentBgm = handles[ToIndex(id)];
PlaySoundMem(currentBgm, DX_PLAYTYPE_LOOP);
}
void SoundManager::StopBgm()
{
if (currentBgm == -1)
return;
StopSoundMem(currentBgm);
currentBgm = -1;
}未再生や停止中は-1で表します。この仕組みによって、いつPlayBgm()を呼んでも曲は重複しません。
ChangeState() によるBGM切り替えの一元化
第07回で画面遷移をGame::ChangeState()へまとめたため、BGMの切り替えもこの関数に書けます。
Game.cppcpp
void Game::ChangeState(State nextState)
{
state = nextState;
// Stateに入ったときのBGMをここで切り替える
switch (state)
{
case State::Title:
sounds.PlayBgm(SoundId::TitleBgm);
break;
case State::Playing:
sounds.PlayBgm(SoundId::PlayingBgm);
break;
case State::GameClear:
sounds.StopBgm();
sounds.PlaySe(SoundId::Clear);
break;
case State::GameOver:
sounds.StopBgm();
sounds.PlaySe(SoundId::GameOver);
break;
}
}クリアやゲームオーバーへ移るときは、sounds.StopBgm()でプレイ中のBGMを止めます。その後、結果画面用のファンファーレや効果音を1回再生します。
画面遷移とBGMの制御を連動させるため、リトライしてもタイトルBGMが鳴り続けるような切り替え漏れは起きません。
チェックリスト
-
SoundManager::PlayBgm()が既存の曲を停止してから新しい曲を再生している - BGMの切り替え処理が
Game::ChangeState()に集約されている - クリア画面およびゲームオーバー画面でプレイ中BGMが停止することを確認できる
- タイトルへ戻った際、タイトルBGMが最初から正しく再生されることを確認できる