SDL2 游戏开发日记(四)
加入音乐和音效
使用SDL_Mixer库,支持的音频格式有wav,mp3,ogg,flac,midi等。
使用单例模式对SDL_Mixer作个简单的封装。实现加载,播放
声音播放类
#pragma once
#include <map>
#include <SDL_mixer.h>
#include <string>
using namespace std;
typedef map<string, Mix_Music*> MusicsMap;
typedef map<string, Mix_Chunk*> SoundsMap;
#define theSounds GameSound::Instance()
class GameSound{
private:
//已加载过的声音列表
MusicsMap mMusics;
//已加载过的音效列表
SoundsMap mSounds;
GameSound(const GameSound &){}
void operator=(const GameSound &){}
GameSound(){
}
public:
static GameSound &Instance(){
static GameSound instance;
return instance;
}
~GameSound(){
}
//释放所有声音。在Mix_Quit前调用
void ReleaseAllSounds(){
if (Mix_PlayingMusic()){
Mix_HaltMusic();
}
Mix_HaltChannel(-1);
MusicsMap::iterator iter = mMusics.begin();
while (iter != mMusics.end()){
Mix_FreeMusic(iter->second);
iter++;
}
mMusics.clear();
SoundsMap::iterator soundsIter = mSounds.begin();
while (soundsIter != mSounds.begin()){
Mix_FreeChunk(soundsIter->second);
soundsIter++;
}
mSounds.clear();
}
//加载音乐
Mix_Music* LoadMusic(string fileName);
//加载音效
Mix_Chunk* LoadSound(string fileName);
//播放音效
bool PlaySoundEffect(string fileName,int loops);
//播放音乐
//通过文件名查找是否已经加载。
//fileName 文件名
//loops,循环次数,-1为一直循环播放
bool PlayMusic(string fileName,int loops);
//暂停
void PauseMusic(){
if (Mix_PlayingMusic()){
Mix_PauseMusic();
}
}
//继续播放
void ResumeMusic(){
if (Mix_PausedMusic()){
Mix_ResumeMusic();
}
}
//停止播放
void StopMusic(){
if (Mix_PlayingMusic()){
Mix_HaltMusic();
}
}
//把声音从已加载过的列表中删除
void DeleteMusic(string fileName){
MusicsMap::iterator iter = mMusics.find(fileName);
if (iter != mMusics.end()){
Mix_FreeMusic(iter->second);
mMusics.erase(iter);
}
}
void DeleteSound(string fileName){
SoundsMap::iterator iter = mSounds.find(fileName);
if (iter != mSounds.end()){
Mix_FreeChunk(iter->second);
mSounds.erase(iter);
}
}
};
//GameSound.cpp
#include "stdafx.h"
#include "SDLGame.h"
#include "GameSound.h"
Mix_Music* GameSound::LoadMusic(string fileName){
Mix_Music *music = NULL;
MusicsMap::iterator iter = mMusics.find(fileName);
if (iter != mMusics.end()){
music = iter->second;
return music;
}
else{
music = Mix_LoadMUS((theGame.GetResourcePath() + fileName).c_str());
if (music != NULL){
mMusics.insert(std::make_pair(fileName, music));
}
else{
return NULL;
}
}
return music;
}
//
Mix_Chunk* GameSound::LoadSound(string fileName){
Mix_Chunk *chunk = NULL;
SoundsMap::iterator iter = mSounds.find(fileName);
if (iter != mSounds.end()){
chunk = iter->second;
return chunk;
}
chunk = Mix_LoadWAV((theGame.GetResourcePath() + fileName).c_str());
if (chunk != NULL){
mSounds.insert(std::make_pair(fileName, chunk));
}
else{
return NULL;
}
return chunk;
}
bool GameSound::PlaySoundEffect(string fileName, int loops){
Mix_Chunk *chunk = LoadSound(fileName);
if (chunk == NULL)
return false;
Mix_PlayChannel(-1, chunk, loops);
return true;
}
bool GameSound::PlayMusic(string fileName,int loops){
Mix_Music *music = LoadMusic(fileName);
if (music == NULL)
return false;
if (Mix_PlayingMusic()){
Mix_HaltMusic();
}
Mix_PlayMusic(music, loops);
return true;
}
测试播放
//加载音乐
theSounds.LoadMusic("background.mp3");
theSounds.LoadSound("delete.wav");
theSounds.PlayMusic("background.mp3", -1);