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);
希望这对您有所帮助,如果您需要更多帮助,请告诉我。
我正在学习 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);
希望这对您有所帮助,如果您需要更多帮助,请告诉我。