简体   繁体   English

sf ::音乐播放但不播放sf ::声音? 为什么?

[英]sf::Music plays but not sf::Sound? Why?

I am learning the SFML library in C++. 我正在学习C ++中的SFML库。 I have been trying to implement an efficient method of organizing audio in my game by making an Audio class that contains two separate std::map for the music (sf::Music) and the sound (sf::Sound). 我一直在尝试通过使Audio类包含两个单独的std :: map(用于音乐(sf :: Music)和声音(sf :: Sound))来实现一种有效的组织游戏音频的方法。 However, when I run the program, only the music is able to play but not the sound effects. 但是,当我运行该程序时,只能播放音乐,而不能播放声音效果。 I believe the sound does load fine since it does not throw the error message. 我相信声音确实加载正常,因为它不会引发错误消息。 Here is my code and info. 这是我的代码和信息。 (Possibly give tips on my code as well since I am new :D ) Thanks in advance (由于我是新手:D,可能还会提供有关我的代码的提示)预先感谢

VS2012, SFML 2.1 VS2012,SFML 2.1

SFML_Snake.h (Game header file) 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 (Game source file) 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 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 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"));
}

在此处输入图片说明

You basically need a sound manager, this is what I use to manager my sounds. 您基本上需要一个声音管理器,这就是我用来管理声音的方法。

Header file 头文件

#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;
};

Source file 源文件

#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();
        }

    }
}

Now you have yourself a SoundManager, you can load sounds like so and play sounds like so. 现在您有了SoundManager,您可以加载类似的声音并播放类似的声音。

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

Hope this helps you out, if you need any more help just let me know. 希望这对您有所帮助,如果您需要更多帮助,请告诉我。

The sf::SoundBuffer effectively holds the audio data you want to playback. sf::SoundBuffer有效地保存您要播放的音频数据。 To do so the data needs to exist as long as you're playing it. 为此,只要您正在播放数据就必须存在。 In your code however, you load the buffers in Audio::loadAudio() but as soon as you leave that function, the buffer will get destroyed and your sf::Sound object don't have any kind of data to playback. 但是,在您的代码中,您将缓冲区加载到Audio::loadAudio()但是一旦离开该函数,缓冲区将被销毁,并且sf::Sound对象没有任何类型的数据可播放。

You rather want to store the sf::SoundBuffer objects instead of the sf::Sound objects. 您宁愿存储sf::SoundBuffer对象,而不是sf::Sound对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM