Reputation: 1172
I am learning the SFML library in C++. 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). 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
VS2012, SFML 2.1
SFML_Snake.h (Game header file)
#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)
/*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"));
}
Upvotes: 1
Views: 2327
Reputation: 5897
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.
SoundLoader sl;
sl.LoadSounds();
sl.Play(SoundNames::sound1);
Hope this helps you out, if you need any more help just let me know.
Upvotes: 2
Reputation: 2613
The sf::SoundBuffer
effectively holds the audio data you want to playback. 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.
You rather want to store the sf::SoundBuffer
objects instead of the sf::Sound
objects.
Upvotes: 0