8.1 KiB
8.1 KiB
08. 音频系统
Extra2D 提供了基于 SDL2_mixer 的音频播放系统,支持音效播放。
音频引擎
通过 Application::instance().audio() 访问音频引擎:
auto& audio = Application::instance().audio();
播放音效
基本用法
// 加载音效
auto sound = audio.loadSound("assets/audio/jump.wav");
// 播放音效
sound->play();
// 设置音量 (0.0 - 1.0)
sound->setVolume(0.8f);
音效控制
// 停止播放
sound->stop();
// 暂停
sound->pause();
// 恢复
sound->resume();
// 循环播放
sound->setLooping(true);
// 检查播放状态
bool playing = sound->isPlaying();
bool paused = sound->isPaused();
音调和播放位置
// 设置音调(当前实现不支持)
sound->setPitch(1.0f);
// 获取/设置播放位置(当前实现不支持)
float cursor = sound->getCursor();
sound->setCursor(0.0f);
// 获取音频时长(当前实现不支持)
float duration = sound->getDuration();
全局音量控制
// 设置主音量
audio.setMasterVolume(0.8f);
// 获取主音量
float volume = audio.getMasterVolume();
全局播放控制
// 暂停所有音效
audio.pauseAll();
// 恢复所有音效
audio.resumeAll();
// 停止所有音效
audio.stopAll();
// 卸载指定音效
audio.unloadSound("jump");
// 卸载所有音效
audio.unloadAllSounds();
完整示例
Flappy Bird 音效管理器
参考 examples/flappy_bird/ResLoader.h/cpp:
// ResLoader.h
#pragma once
#include <extra2d/extra2d.h>
#include <map>
namespace flappybird {
enum class MusicType {
Click, // 按键声音
Hit, // 小鸟死亡声音
Fly, // 小鸟飞翔声音
Point, // 得分声音
Swoosh // 转场声音
};
class ResLoader {
public:
static void init();
static void playMusic(MusicType type);
private:
static std::map<MusicType, extra2d::Ptr<extra2d::Sound>> soundMap_;
};
} // namespace flappybird
// ResLoader.cpp
#include "ResLoader.h"
namespace flappybird {
std::map<MusicType, extra2d::Ptr<extra2d::Sound>> ResLoader::soundMap_;
void ResLoader::init() {
auto &resources = extra2d::Application::instance().resources();
// 加载所有音效
soundMap_[MusicType::Click] = resources.loadSound("assets/sound/click.wav");
soundMap_[MusicType::Hit] = resources.loadSound("assets/sound/hit.wav");
soundMap_[MusicType::Fly] = resources.loadSound("assets/sound/fly.wav");
soundMap_[MusicType::Point] = resources.loadSound("assets/sound/point.wav");
soundMap_[MusicType::Swoosh] = resources.loadSound("assets/sound/swoosh.wav");
}
void ResLoader::playMusic(MusicType type) {
auto it = soundMap_.find(type);
if (it != soundMap_.end() && it->second) {
it->second->play();
}
}
} // namespace flappybird
在游戏中使用
// GameScene.cpp - 得分时播放音效
if (pipeX <= birdX) {
score_++;
scoreNumber_->setNumber(score_);
firstPipe->scored = true;
ResLoader::playMusic(MusicType::Point); // 播放得分音效
}
// bird.cpp - 跳跃时播放音效
void Bird::jump() {
velocity_.y = jumpForce_;
ResLoader::playMusic(MusicType::Fly); // 播放飞翔音效
}
// GameOverLayer.cpp - 按钮点击时播放音效
restartBtn_->setOnClick([]() {
ResLoader::playMusic(MusicType::Click); // 播放点击音效
auto &app = extra2d::Application::instance();
app.scenes().replaceScene(extra2d::shared<GameScene>(),
extra2d::TransitionType::Fade, 0.5f);
});
推箱子音效管理器
// audio_manager.h
#pragma once
#include <extra2d/extra2d.h>
namespace pushbox {
class AudioManager {
public:
static AudioManager& instance() {
static AudioManager instance;
return instance;
}
void init();
void setEnabled(bool enabled);
void playMoveSound();
void playBoxMoveSound();
void playWinSound();
private:
AudioManager() = default;
bool enabled_ = true;
extra2d::Ptr<extra2d::Sound> moveSound_;
extra2d::Ptr<extra2d::Sound> boxMoveSound_;
extra2d::Ptr<extra2d::Sound> winSound_;
};
} // namespace pushbox
// audio_manager.cpp
#include "audio_manager.h"
namespace pushbox {
void AudioManager::init() {
auto& audio = extra2d::Application::instance().audio();
// 加载音效
moveSound_ = audio.loadSound("move", "assets/audio/manmove.wav");
boxMoveSound_ = audio.loadSound("boxmove", "assets/audio/boxmove.wav");
winSound_ = audio.loadSound("win", "assets/audio/win.wav");
}
void AudioManager::setEnabled(bool enabled) {
enabled_ = enabled;
if (!enabled) {
extra2d::Application::instance().audio().stopAll();
}
}
void AudioManager::playMoveSound() {
if (enabled_ && moveSound_) {
moveSound_->play();
}
}
void AudioManager::playBoxMoveSound() {
if (enabled_ && boxMoveSound_) {
boxMoveSound_->play();
}
}
void AudioManager::playWinSound() {
if (enabled_ && winSound_) {
winSound_->play();
}
}
} // namespace pushbox
使用音频管理器
// main.cpp
int main(int argc, char** argv) {
// ... 初始化应用 ...
// 初始化音频管理器
pushbox::AudioManager::instance().init();
// ... 运行应用 ...
}
// PlayScene.cpp
void PlayScene::move(int dx, int dy, int direct) {
// ... 移动逻辑 ...
if (isBoxMoved) {
// 播放推箱子音效
pushbox::AudioManager::instance().playBoxMoveSound();
} else {
// 播放移动音效
pushbox::AudioManager::instance().playMoveSound();
}
}
音频开关控制
// 在菜单中切换音效
void StartScene::onUpdate(float dt) {
auto& input = Application::instance().input();
// X键切换音效
if (input.isButtonPressed(GamepadButton::X)) {
g_SoundOpen = !g_SoundOpen;
AudioManager::instance().setEnabled(g_SoundOpen);
updateSoundIcon();
}
}
支持的音频格式
- WAV
- OGG
- MP3(需要 SDL2_mixer 支持)
最佳实践
- 使用单例管理器 - 集中管理音频资源
- 预加载常用音效 - 在初始化时加载
- 提供开关选项 - 让用户控制音效
- 合理设置音量 - 避免音量过大
- 及时卸载不用的音效 - 释放内存资源
API 参考
Sound 类
| 方法 | 说明 |
|---|---|
play() |
播放音效 |
pause() |
暂停播放 |
resume() |
恢复播放 |
stop() |
停止播放 |
isPlaying() |
是否正在播放 |
isPaused() |
是否已暂停 |
setVolume(float) |
设置音量 (0.0-1.0) |
getVolume() |
获取音量 |
setLooping(bool) |
设置循环播放 |
isLooping() |
是否循环播放 |
setPitch(float) |
设置音调(当前不支持) |
getPitch() |
获取音调 |
getDuration() |
获取时长(当前不支持) |
getCursor() |
获取播放位置(当前不支持) |
setCursor(float) |
设置播放位置(当前不支持) |
AudioEngine 类
| 方法 | 说明 |
|---|---|
getInstance() |
获取单例实例 |
initialize() |
初始化音频引擎 |
shutdown() |
关闭音频引擎 |
loadSound(path) |
加载音效(以路径为名称) |
loadSound(name, path) |
加载音效(指定名称) |
getSound(name) |
获取已加载的音效 |
unloadSound(name) |
卸载指定音效 |
unloadAllSounds() |
卸载所有音效 |
setMasterVolume(float) |
设置主音量 |
getMasterVolume() |
获取主音量 |
pauseAll() |
暂停所有音效 |
resumeAll() |
恢复所有音效 |
stopAll() |
停止所有音效 |
总结
至此,你已经学习了 Extra2D 引擎的核心功能:
开始你的游戏开发之旅吧!