如何循环播放sf::Sound?
How to play a sf::Sound in a loop?
我们(学校)正在使用 SFML 用 C++ 开发游戏。该游戏是一款格斗游戏,例如当玩家被击中时我们需要播放小声音。
我正在尝试循环播放 sf::Sound。我知道我们不应该在循环中调用 sf::Sound 的 play() 方法,但是由于 SFML 应用程序都在 while 循环中调用 运行,我别无选择。或者至少,我不知道还有什么其他方法可以做到这一点。
我尝试使用 ,我阅读了多篇关于它的帖子,但我发现没有任何效果。
这是一个示例代码:
#include <SFML/Audio.hpp>
#include <vector>
#include <iostream>
int main() {
int FPS = 60;
// sf::Music music;
// if(!music.openFromFile("resources/audio/fight_theme.ogg")) {
// std::cout << "Music was not found" << std::endl;
// }
// music.setVolume(10.f);
// music.play();
// Create the main window
sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode();
sf::RenderWindow app(
sf::VideoMode(
desktopMode.width,
desktopMode.height,
desktopMode.bitsPerPixel),
"SkyddaForWhosebug",
sf::Style::Fullscreen
);
app.setFramerateLimit(FPS);
//Main loop
while (app.isOpen()) {
/*In the actual code, we have two player instances.
When the user press S or keyDown button, we call the attack function.
In the function, we deal the damages to the ennemy, then we call playSound
to play the hitting sound
Please note this is a sample code to help understanding the case.
In the actual code, everything is delegated to the Player class, to a SoundLoader (which is basically playSound() here)
The problem is, even with delegation, even if the playSound method is not situated in the main loop,
it is called in the main loop so the location of the code does not make any difference : it won't play since it won't
be called outside of a loop as we do for the background music (see commented code after main() {..., the background music
works fine.*/
if(player.attack(ennemy)) {
playSound();
}
}
return EXIT_SUCCESS;
}
void playSound() {
sf::SoundBuffer buffer;
if(!buffer.loadFromFile(path)) {
std::cout << "Sound was not found at " << path << std::endl;
}
sf::Sound sound(buffer);
sound.play();
}
如果您有其他问题,请不要犹豫。
谢谢!
问题不在于“在循环外被调用”;问题是您的 sf::Sound
对象在 playSound
函数结束时被销毁了!
首先,定义两个全局(或class-)变量:
std::map<std::string, sf::SoundBuffer> buffers;
std::map<std::string, sf::Sound> sounds;
您现在可以定义 playSound
如下:
void playSound(std::string path) {
if (auto it = sounds.find(path); it == sounds.end()) {
bool ok = buffers[path].loadFromFile(path);
// do something if ok is false
sounds[path] = sf::Sound{buffers[path]};
}
sounds[path].play();
}
这将使您的 sf::Sound
对象(和关联的 sf::SoundBuffer
对象)保持活动状态。第一次调用将从磁盘加载文件,后续调用将重新启动现有声音。
请注意,为了便于理解,此代码略微次优:它查找 sounds[path]
两次。作为您的练习,通过在 play
调用中重复使用 it
来摆脱第二次查找。
我们(学校)正在使用 SFML 用 C++ 开发游戏。该游戏是一款格斗游戏,例如当玩家被击中时我们需要播放小声音。
我正在尝试循环播放 sf::Sound。我知道我们不应该在循环中调用 sf::Sound 的 play() 方法,但是由于 SFML 应用程序都在 while 循环中调用 运行,我别无选择。或者至少,我不知道还有什么其他方法可以做到这一点。
我尝试使用
这是一个示例代码:
#include <SFML/Audio.hpp>
#include <vector>
#include <iostream>
int main() {
int FPS = 60;
// sf::Music music;
// if(!music.openFromFile("resources/audio/fight_theme.ogg")) {
// std::cout << "Music was not found" << std::endl;
// }
// music.setVolume(10.f);
// music.play();
// Create the main window
sf::VideoMode desktopMode = sf::VideoMode::getDesktopMode();
sf::RenderWindow app(
sf::VideoMode(
desktopMode.width,
desktopMode.height,
desktopMode.bitsPerPixel),
"SkyddaForWhosebug",
sf::Style::Fullscreen
);
app.setFramerateLimit(FPS);
//Main loop
while (app.isOpen()) {
/*In the actual code, we have two player instances.
When the user press S or keyDown button, we call the attack function.
In the function, we deal the damages to the ennemy, then we call playSound
to play the hitting sound
Please note this is a sample code to help understanding the case.
In the actual code, everything is delegated to the Player class, to a SoundLoader (which is basically playSound() here)
The problem is, even with delegation, even if the playSound method is not situated in the main loop,
it is called in the main loop so the location of the code does not make any difference : it won't play since it won't
be called outside of a loop as we do for the background music (see commented code after main() {..., the background music
works fine.*/
if(player.attack(ennemy)) {
playSound();
}
}
return EXIT_SUCCESS;
}
void playSound() {
sf::SoundBuffer buffer;
if(!buffer.loadFromFile(path)) {
std::cout << "Sound was not found at " << path << std::endl;
}
sf::Sound sound(buffer);
sound.play();
}
如果您有其他问题,请不要犹豫。 谢谢!
问题不在于“在循环外被调用”;问题是您的 sf::Sound
对象在 playSound
函数结束时被销毁了!
首先,定义两个全局(或class-)变量:
std::map<std::string, sf::SoundBuffer> buffers;
std::map<std::string, sf::Sound> sounds;
您现在可以定义 playSound
如下:
void playSound(std::string path) {
if (auto it = sounds.find(path); it == sounds.end()) {
bool ok = buffers[path].loadFromFile(path);
// do something if ok is false
sounds[path] = sf::Sound{buffers[path]};
}
sounds[path].play();
}
这将使您的 sf::Sound
对象(和关联的 sf::SoundBuffer
对象)保持活动状态。第一次调用将从磁盘加载文件,后续调用将重新启动现有声音。
请注意,为了便于理解,此代码略微次优:它查找 sounds[path]
两次。作为您的练习,通过在 play
调用中重复使用 it
来摆脱第二次查找。