我已经使用SFML很长时间了,但是到目前为止,我从未使用过Audio模块。

我想在游戏中添加声音效果,所以我的第一个方法与此类似。

class Deck : public sf::Drawable
{
public:
    ...

private:
    sf::Sound shuffleSound;

    ...

    static sf::SoundBuffer soundBuffer;
};

计划是一次初始化soundBuffer,然后在每个对象的构造函数中执行shuffleSound.setBuffer(soundBuffer);。但是我得到了这个错误:
AL lib: (EE) alc_cleanup: 1 device not closed

Assertion failed: (lockret == althrd_success), function LockLists, file /Users/m/Desktop/tmp/openal/build_deps/openal-soft-openal-soft-1.17.2/Alc/ALc.c, line 776.
(lldb)

搜寻完此错误之后,我在某处看到了一条模糊的消息,内容是关于不将SFML资源放在全局范围内。确定static变量是导致错误的原因,我尝试这样做:
class Deck : public sf::Drawable
{
public:
    ...

private:
    sf::Sound shuffleSound;

    ...

    static std::unique_ptr<sf::SoundBuffer> bufptr;
};

如果对象为空,则通过调用make_unique初始化一次指针,然后在构造函数中执行shuffleSound.setBuffer(*bufptr)

但是,我仍然遇到相同的错误。在程序即将终止之前,不会发生该错误。

任何帮助,将不胜感激。

最佳答案

由于我的声誉太低,我无法添加任何评论,所以我会写下答案。

一开始,我建议您创建一些类来保留所有资源。
检查此:https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources/Include/Book

SFML游戏开发书有源代码-您可以在SFML Github上找到许多有用的 Material 。

因此,在您的情况下,您可以创建该类型的对象:ResourceHolder<sf::SoundBuffer, ID> mSoundHolder;,其中ID是某种enum类型,用于标识每个声音。

然后,要播放声音,只需创建sf::Sound s类型的对象,然后使用s.setBuffer(mSoundHolder.getResource(<YOUR_ID>)s.play()即可。

确保sf::Sound不是本地对象,因为它不会被播放,因为它将被快速自动销毁。然后在类里面创建它,或者如果您想在同一创建中播放更多声音,例如在迭代时添加std::list<sf::Sound> sounds来播放声音。要检查它是否已完成播放,请使用:sound.getStatus() == sf::Sound::Stopped比较,然后从列表中删除声音。

您可以使用sf::Soundsf::SoundBuffer创建std::list对象。然后,您可以简单地在列表对象上使用emplace_back并将sf::SoundBuffer作为参数传递。

希望能帮助到你。

关于c++ - 声明sf::SoundBuffer会导致程序在终止时崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45403807/

10-09 13:35