Appearance
第09回 音声の管理と再生
1 / 4 SoundManagerで音声を所有する
このステップの目的
音声ハンドルを画像と同じようにManagerへ集約し、ゲーム中のクラスから直接扱わない
音声IDを定義する
ゲーム内では、音声ファイル名ではなくSoundManager::Idを使います。 タイトルBGM、プレイ中BGM、射撃や命中のSEを意味で区別します。
SoundManager.hcpp
enum class Id
{
TitleBgm,
PlayingBgm,
Shot,
Hit,
Damage,
Clear,
GameOver,
Count
};画像と同じように、IDとファイルパスの対応表を用意します。
SoundManager.cppcpp
using SoundId = SoundManager::Id;
struct SoundEntry
{
SoundId id;
const wchar_t* path;
};
constexpr std::array<SoundEntry, static_cast<std::size_t>(SoundId::Count)> SoundTable =
{
SoundEntry { SoundId::TitleBgm, L"Assets/Sounds/TitleBgm.wav" },
SoundEntry { SoundId::PlayingBgm, L"Assets/Sounds/PlayingBgm.wav" },
SoundEntry { SoundId::Shot, L"Assets/Sounds/Shot.wav" },
SoundEntry { SoundId::Hit, L"Assets/Sounds/Hit.wav" },
SoundEntry { SoundId::Damage, L"Assets/Sounds/Damage.wav" },
SoundEntry { SoundId::Clear, L"Assets/Sounds/Clear.wav" },
SoundEntry { SoundId::GameOver, L"Assets/Sounds/GameOver.wav" }
};ImageManagerとの対応
音声Managerも、対応表を走査して読み込み、デストラクタまたは解放関数でハンドルを解放します。 LoadSoundMem()やDeleteSoundMem()をGameやEntityから直接呼びません。
読み込み処理は対応表を順に走査し、失敗した時点で対象パスを返します。
SoundManager.cppcpp
std::size_t ToIndex(SoundId id)
{
return static_cast<std::size_t>(id);
}
for (const SoundEntry& entry : SoundTable)
{
const std::size_t index = ToIndex(entry.id);
handles[index] = LoadSoundMem(entry.path);
if (handles[index] == -1)
{
Release();
return { false, entry.path };
}
}音声が必須素材であることも画像と同じです。 読み込みに失敗したらゲームを開始せず、対象パスを確認できるようにします。
チェックリスト
- 音声の種類を
Idで表している - 音声ハンドルを
SoundManagerが所有している - 音声の直接読み込みをGameやEntityへ置いていない