sf::Music 播放但不播放 sf::Sound?为什么?

sf::Music plays but not sf::Sound? Why?

我正在学习 C++ 中的 SFML 库。我一直在尝试通过制作一个音频 class 来实现一种在我的游戏中组织音频的有效方法,该音频 class 包含两个单独的 std::map 音乐(sf::Music)和声音(sf::Sound ).但是,当我运行程序时,只有音乐能播放,音效不能播放。我相信声音确实可以正常加载,因为它不会抛出错误消息。这是我的代码和信息。 (因为我是新手,可能还会提供有关我的代码的提示:D) 提前致谢

VS2012,SFML 2.1

SFML_Snake.h(游戏头文件)

#pragma once
#ifndef GUARD_SFML_SNAKE
#define GUARD_SFML_SNAKE

#include "SFML/Audio.hpp"
#include "SFML/Graphics.hpp"
#include "Snake.h"
#include "Apple.h"
#include "Audio.h"
#include <iostream>

class SFML_Snake{
public:
    SFML_Snake();
    void run();
private:
    void checkBoundary(Snake);
    void checkApple(Snake&, Apple&, Audio& );
    std::vector<sf::RectangleShape> loadGrid();
private:
    bool processEvents();
    void update(Audio&);
    void render(std::vector<sf::RectangleShape>&);

public:
    sf::RenderWindow window;
    sf::Text textCount;
    Snake snake;
    Apple apple;
};

int main(){
    SFML_Snake start;
    start.run();
}
#endif

SFML_Snake.cpp(游戏源文件)

/*Import statements*/
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include "Snake.h"
#include "variables.h"
#include "Apple.h"
#include "Audio.h"
#include "SFML_Snake.h"
#include <iostream>
#include <vector>
#include <string>
#include <array>
#include <map>
#include <memory>


SFML_Snake::SFML_Snake():
window(sf::VideoMode(windowWidth, windowHeight), "SFML Application" ),
snake(Snake()), apple(Apple(0,0)), textCount(sf::Text())
{
    window.setFramerateLimit(FRAMERATE);
}



void SFML_Snake::checkBoundary(Snake s){
    for (int z = dots; z > 0; z--){
        if ((s.x[0] == s.x[z]) && (s.y[0] == s.y[z]))
            inGame = false;
    }
    if (s.y[0] >= windowHeight)
        inGame = false;
    if (s.y[0] < dotSize)
        inGame = false;
    if (s.x[0] >= windowWidth)
        inGame = false;
    if (s.x[0] < dotSize)
        inGame = false;
}

void SFML_Snake::checkApple(Snake& mA, Apple& mB, Audio& audios){
    if ((mA.x[0] == mB.x()) && (mA.y[0] == mB.y())){
        audios.getSound("eating").play();
        dots += dotInterval;
        points++;
        if(DEBUG)
        std::cout<< points << std::endl;
        textCount.setString(std::string("points: ") + std::to_string(points));
        mB.locateApple();
        for(int i = mA.draw().size() - 1; i >= 0; i--){
            while (((mA.x[0] == mB.x()) && (mA.y[0] == mB.y())) 
                || (0 == mB.x()) 
                || (0 == mB.y()) 
                || (windowWidth - dotSize/2 == mB.x()) 
                || (windowHeight - dotSize/2 == mB.y())) 
            {
                mB.locateApple();
            }
        }
    }
}

bool SFML_Snake::processEvents(){
    sf::Event event;
    while (window.pollEvent(event)){
            if (event.type == sf::Event::Closed)
                window.close();
        }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape)) {
        return true;
    }
    snake.input();
    return false;
}
void SFML_Snake::update(Audio& audios){
        snake.checkReals();
        snake.moveUpdate();
        audios.getSound("moving").play();
        checkApple(snake, apple, audios);
        checkBoundary(snake);
}
void SFML_Snake::render(std::vector<sf::RectangleShape>& grid){

        std::vector<sf::RectangleShape> shapearray = snake.draw();
        for (int i = shapearray.size() - 1; i >= 0; i--){
            window.draw(shapearray[i]);
        }
        window.draw(apple.draw());
        for(int i = grid.size()-1; i>=0; i--){
            window.draw(grid[i]);
        }
        window.draw(textCount);
        window.display();
}
std::vector<sf::RectangleShape> SFML_Snake::loadGrid(){
    std::vector<sf::RectangleShape> grid;
    for(int k= dotSize/2; k<=windowHeight+dotSize/2; k+=dotSize){
            sf::RectangleShape line;
            line.setPosition(0, k-dotSize);
            line.setSize(sf::Vector2f(windowWidth, 1));
            line.setFillColor(sf::Color::Black);
            if(k==dotSize/2 || k == windowHeight + dotSize/2){
                line.setSize(sf::Vector2f(windowWidth, dotSize));
            }
            grid.push_back(line);
        }
    for(int i = dotSize/2; i<=windowWidth+dotSize/2; i+=dotSize){

        sf::RectangleShape line;
        line.setPosition(i-dotSize, 0);
        line.setSize(sf::Vector2f(1, windowHeight));
        line.setFillColor(sf::Color::Black);
        if(i==dotSize/2 || i == windowWidth+dotSize/2){
            line.setSize(sf::Vector2f(dotSize, windowHeight));
        }
        grid.push_back(line);

    }
    return grid;

}

void SFML_Snake::run(){
    /*Initialize the objects*/

    std::vector<sf::RectangleShape> grid = loadGrid();
    if(!DEBUG)
        std::cout<<"DEBUG MODE: OFF" <<std::endl;
    Audio& audios = Audio();
    apple.locateApple();

    /*Load the audio*/

    audios.getMusic("backgroundMusic").setVolume(10);
    audios.getMusic("backgroundMusic").setLoop(true);
    audios.getMusic("backgroundMusic").setVolume(25);

    /*Load the font*/
    sf::Font font;
    if (!(font.loadFromFile("arial.ttf")))
        if(DEBUG)
            std::cout << "Error loading fonts" << std::endl;
    /*Create the text*/
    textCount.setFont(font);
    textCount.setString(std::string("points: ") + std::to_string(points));
    textCount.setColor(sf::Color::Red);
    textCount.setCharacterSize(20);
    textCount.setPosition(windowWidth / 2 - (textCount.getString().getSize()*(textCount.getCharacterSize() / 5)), textCount.getCharacterSize() - 10);
    textCount.setStyle(sf::Text::Bold);
    window.draw(textCount);

    /*MAIN GAME LOOP*/
    counterTick = 1;

    audios.getSound("begin").play();
    audios.getMusic("backgroundMusic").play();
    while (inGame && !pause)
    {
        std::string counter = std::to_string(counterTick);
        if(DEBUG)
            std::cout << "Tick: " + counter << std::endl;

        window.clear(sf::Color::White);
        if(processEvents()){
            break;
        }
        update(audios);
        render(grid);
        snake.secInput = false;
        counterTick++;
    }
    audios.getSound("losing").play();
    audios.getMusic("backgroundMusic").stop();
    std::system("PAUSE");//bad practice, debuggin purposes
}

Audio.h

#pragma once
#ifndef GUARD_AUDIO_H
#define GUARD_AUDIO_H
#include "variables.h"
#include "SFML\Graphics.hpp"
#include "SFML\Audio.hpp"
#include <memory>

struct Audio{
    std::map<std::string, sf::Sound> sounds;
    std::map<std::string, std::unique_ptr<sf::Music>> musics;
    //std::map<std::string, sf::Sound> sounds;
    //std::map<std::string, sf::Music> musics;

    Audio();

    void Audio::addSound(sf::Sound&, sf::SoundBuffer& , const std::string&);

    void Audio::addSound(sf::Sound&, const std::string&);

    void Audio::addMusic(const std::string&, std::unique_ptr<sf::Music> );

    sf::Sound &Audio::getSound(std::string);

    sf::Music &Audio::getMusic(std::string);

    void Audio::loadAudio();
};

#endif//GUARD_AUDIO_H

Audio.cpp

#include "Audio.h"
#include <iostream>
    Audio::Audio(){
        loadAudio();
    }
    void Audio::addSound(sf::Sound& s, sf::SoundBuffer& sb, const std::string &key){
        s.setBuffer(sb);
        sounds.insert(std::pair<std::string, sf::Sound>(key, std::move(s)));
    }
    void Audio::addSound(sf::Sound& s, const std::string &key){
        sounds.insert(std::pair<std::string, sf::Sound>(key, s));
    }
    void Audio::addMusic(const std::string &key, std::unique_ptr<sf::Music> value){
        musics.insert(std::pair<std::string, std::unique_ptr<sf::Music> >(key, std::move(value)));
    }
    sf::Sound &Audio::getSound(std::string key){
        return sounds.at(key);
    }
    sf::Music &Audio::getMusic(std::string key){
        return *musics.at(key);
    }
    void Audio::loadAudio(){

    //sf::Music backgroundMusic;
    sf::Sound s_eating;
    sf::SoundBuffer sb_eating;
    sf::Sound s_moving;
    sf::SoundBuffer sb_moving;
    sf::Sound s_losing;
    sf::SoundBuffer sb_losing;
    sf::Sound s_begin;
    sf::SoundBuffer sb_begin;

    auto backgroundMusic = std::unique_ptr<sf::Music>(new sf::Music());

    if (!backgroundMusic->openFromFile("backgroundmusic.wav"))
        if(DEBUG)
            std::cerr << "Error opening \"backgroundmusic.wav\"" << std::endl;
    if (!sb_eating.loadFromFile("eatingsfx.wav"))
        if(DEBUG)
            std::cerr << "Error opening \"eatingsfx.wav\"" << std::endl;
    if (!sb_moving.loadFromFile("movingsfx.wav"))
        if(DEBUG)
            std::cerr << "Error opening \"movingsfx.wav\"" << std::endl;
    if (!sb_losing.loadFromFile("losingsfx.wav"))
        if(DEBUG)
            std::cerr << "Error opening \"losingsfx.wav\"" << std::endl;
    if (!sb_begin.loadFromFile("beginsfx.wav"))
        if(DEBUG)
            std::cerr << "Error opening \"beginsfx.wav\"" << std::endl;

    //s_eating.setBuffer(sb_eating);
    //s_moving.setBuffer(sb_moving);
    //s_losing.setBuffer(sb_losing);
    //s_begin.setBuffer(sb_begin);
    addMusic(std::string("backgroundMusic"), std::move(backgroundMusic));
    addSound(s_eating, sb_eating, std::string("eating"));
    addSound(s_moving, sb_moving, std::string("moving"));
    addSound(s_losing, sb_losing, std::string("losing"));
    addSound(s_begin, sb_begin, std::string("begin"));
}

sf::SoundBuffer有效地保存了您要播放的音频数据。为此,只要您正在播放数据,数据就必须存在。然而,在您的代码中,您在 Audio::loadAudio() 中加载了缓冲区,但是一旦您离开该函数,缓冲区就会被销毁并且您的 sf::Sound 对象没有任何类型的数据可以播放。

您想存储 sf::SoundBuffer 个对象而不是 sf::Sound 个对象。

你基本上需要一个声音管理器,这就是我用来管理声音的工具。

头文件

#pragma once

#include "SFML/Audio.hpp"
#include "Enums.h"
#include <map>
#include <vector>
#include <iostream>

class SoundLoader
{
public:
    //SoundNames is an enum
    SoundLoader();
    ~SoundLoader();

    void LoadSounds();
    void PlaySound(SoundNames soundName);

    std::map<SoundNames, sf::SoundBuffer> Sounds;
    std::vector<sf::Sound> playingSounds;
};

源文件

#include "SoundLoader.h"

SoundLoader::SoundLoader()
{

}

SoundLoader::~SoundLoader()
{

}

void SoundLoader::LoadSounds()
{
    Sounds[SoundNames::sound1].loadFromFile("Assets/Sounds/sound1.wav");
}

void SoundLoader::PlaySound(SoundNames soundName)
{
    if (playingSounds.size() == 0)
    {
        playingSounds.push_back(sf::Sound());
        playingSounds.at(0).setBuffer(Sounds[soundName]);
        playingSounds.at(0).play();
    }
    else
    {
        int location = -1;
        for (int i = 0; i < playingSounds.size(); i++)
        {
            if (playingSounds.at(i).getStatus() != sf::Sound::Playing && location == -1)
            {
                location = i;
            }
        }

        if (location != -1)
        {
            playingSounds.at(location).setBuffer(Sounds[soundName]);
            playingSounds.at(location).play();
        }
        else
        {
            playingSounds.push_back(sf::Sound());
            playingSounds.at(playingSounds.size()-1).setBuffer(Sounds[soundName]);
            playingSounds.at(playingSounds.size() - 1).play();
        }

    }
}

现在您有了一个 SoundManager,您可以像这样加载声音并像这样播放声音。

SoundLoader sl;
sl.LoadSounds();
sl.Play(SoundNames::sound1);

希望这对您有所帮助,如果您需要更多帮助,请告诉我。