【发布时间】:2014-12-02 19:48:16
【问题描述】:
使用 SFML 2.1
我决定制作一个包含我的音频文件的对象。但是,当我运行测试时,出现以下错误:
错误 C2248:“sf::NonCopyable::NonCopyable”:无法访问在“sf::NonCopyable”类中声明的私有成员
我在 SFML 网站上查找了有关此错误的一些信息,它指出我无法复制继承 sf::NonCopyable 的对象(我认为)。这些对象可能是我即将展示的 sf::Sound 和 sf::Music。真正的问题是:这个副本是在哪里制作的,我该如何修复它?
音频类
struct Audio {
std::map<std::string, sf::Sound> sounds;
std::map<std::string, sf::Music> musics;
Audio() : sounds(),
musics(){}
void addSound(sf::Sound& s, sf::SoundBuffer& sb, std::string key){
s.setBuffer(sb);
sounds.insert(std::pair<std::string, sf::Sound>(key, s));
}
void addSound(sf::Sound& s, std::string key){
sounds.insert(std::pair<std::string, sf::Sound>(key, s));
}
void addMusic(sf::Music& m, std::string key){
musics.insert(std::pair<std::string, sf::Music>(key, m));
}
sf::Sound& getSound(std::string key){
return sounds[key];
}
sf::Music& getMusic(std::string key){
return musics[key];
}
};
加载声音方法
void loadSounds(Audio& audio){
sf::Music backgroundMusic;
sf::Sound eating;
sf::SoundBuffer sb_eating;
sf::Sound moving;
sf::SoundBuffer sb_moving;
sf::Sound losing;
sf::SoundBuffer sb_losing;
sf::Sound begin;
sf::SoundBuffer sb_begin;
if (!backgroundMusic.openFromFile("backgroundmusic.wav"))
std::cerr << "Error opening \"backgroundmusic.wav\"" << std::endl;
if (!sb_eating.loadFromFile("eatingsfx.wav"))
std::cerr << "Error opening \"eatingsfx.wav\"" << std::endl;
if (!sb_moving.loadFromFile("movingsfx.wav"))
std::cerr << "Error opening \"movingsfx.wav\"" << std::endl;
if (!sb_losing.loadFromFile("losingsfx.wav"))
std::cerr << "Error opening \"losingsfx.wav\"" << std::endl;
if (!sb_begin.loadFromFile("beginsfx.wav"))
std::cerr << "Error opening \"beginsfx.wav\"" << std::endl;
eating.setBuffer(sb_eating);
moving.setBuffer(sb_moving);
losing.setBuffer(sb_losing);
begin.setBuffer(sb_begin);
audio.addMusic(backgroundMusic, std::string("backgroundMusic"));
audio.addSound(eating, std::string("eating"));
audio.addSound(moving, std::string("moving"));
audio.addSound(losing, std::string("losing"));
audio.addSound(begin, std::string("begin"));
}
主要方法
int main(){
/*Initialize the objects*/
Snake snake = Snake();
Audio& audios = Audio();
sf::Text textCount;
Apple apple(0, 0);
apple.locateApple();
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML Application" );
/*Load the audio*/
loadSounds(audios);
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")))
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() - 5);
textCount.setStyle(sf::Text::Bold);
window.draw(textCount);
/*Set Framerate fps*/
window.setFramerateLimit(10);
/*MAIN GAME LOOP*/
counterTick = 1;
audios.getSound("begin").play();
audios.getMusic("backgroundMusic").play();
while (inGame)
{
std::string counter = std::to_string(counterTick);
std::cout << "Tick: " + counter << std::endl;
window.clear(sf::Color::Black);
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape)) break;
/*Call Updates*/
snake.input();
snake.checkReals();
snake.moveUpdate();
audios.getSound("moving").play();
/*Call Collisions*/
std::cout << " Outside Collision Loop " << std::endl;
checkApple(snake, apple, audios.getSound("eating"));
checkBoundary(snake);
/*Call Draw*/
std::vector<sf::RectangleShape> shapearray = snake.draw();
for (int i = shapearray.size() - 1; i >= 0; i--){
window.draw(shapearray[i]);
}
window.draw(textCount);
window.draw(apple.draw());
window.display();
counterTick++;
}
audios.getSound("losing").play();
audios.getMusic("backgroundMusic").stop();
std::system("PAUSE");//bad practice, debuggin purposes
return 0;
}
【问题讨论】:
-
std::pair制作一个副本,然后将其插入到地图中创建另一个。也许您想改用std::unique_ptr或std::shared_ptr? -
您使用的是 C++ 11 吗?你也许可以使用新的移动语法——基本上改变你的 addSound、addMusic 等函数来获取 Sound&& 等。
-
@Bash Music 似乎是这里涉及的唯一不可复制的对象(因为它包含
sf::Thread)。您可能必须使用指向sf::Music的指针。由于 SFML 的人没有实现移动构造器,因此它几乎是您唯一的选择。哦,副本是在这一行制作的musics.insert(std::pair<std::string, sf::Music>(key, m));