So I was trying out the SFML tutorial for playing a sound from a local file and came across a weird bug. Whenever I call the playSound function no sound is played and I get an error that I can't find the solution to:
[ALSOFT] (EE) Failed to set real-time priority for thread: Operation not permitted (1)
The strange thing is that if I do the same thing in the main function the sound is played. What is going on here? Here are the only files used in the project, the .wav is just a simple sound file:
main.cpp
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
void playSound() {
sf::SoundBuffer buffer;
if (!buffer.loadFromFile("1-retro-arcade-casino-notification.wav"))
return;
sf::Sound sound;
sound.setBuffer(buffer);
sound.play();
}
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "Notification test");
sf::SoundBuffer buffer;
if (!buffer.loadFromFile("1-retro-arcade-casino-notification.wav"))
return -1;
sf::Sound sound;
sound.setBuffer(buffer);
sound.play();
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::TextEntered) {
char key = static_cast<char>(event.text.unicode);
if (key == 'p') {
playSound();
}
if (key == 'q') {
window.close();
}
}
}
}
return 0;
}
Makefile
all:
g++ -lsfml-audio -lsfml-graphics -lsfml-window -lsfml-system -o main main.cpp
The sound data is not stored directly in sf::Sound but instead in the sf::SoundBuffer. This class encapsulates the audio data, which is basically an array of 16-bit signed integers (called "audio samples").
Sounds (and music) are played in a separate thread. This means that you are free to do anything you want after calling
void play(), except destroying the sound or its data - which you are currently doing.
This is because you have declared your sf::SoundBuffer buffer; inside void playSound(), and subsequently, the sound data gets destroyed as it goes out of scope after returning from void playSound().
To fix your problem, don't declare sf::SoundBuffer in the function. You could just declare it outside the main function, or even pass it as a parameter to playSound().
See the relevant documentation for info.
Related
I have a folder full of images, I need to save these images into the video while doing so I want to show the user the video being played from these images (frames). I can run two separate processes one for the saving and one for the showing but this is not what I am looking for, I want to do both in one step. If you know a solution please let me know.
My code uses C++ with OpenCV but feel free to share with me any code written with any language, or event a concept.
I use gStreamer, ffmpeg as well for the video generation, so I am not looking how to save a video or how to show the video I am looking for a process that can do both in one operation.
here's my quick brew using SFML. You have to link SFML and include the include folder. Simply set directory to your target folder, I use std::filesystem to add all files from that folder to a std::vector<std::string>.
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
#include <iostream>
#include <filesystem>
void add_frame_to_video(std::string path) {
//your encoding stuff ...
}
int main() {
auto dimension = sf::VideoMode(1280u, 720u);
sf::RenderWindow window;
window.create(dimension, "Video Rendering");
sf::Texture frame_texture;
std::vector<std::string> frame_paths;
std::string directory = "resources/";
for (auto i : std::filesystem::directory_iterator(directory)) {
frame_paths.push_back({ i.path().string() });
}
std::size_t frame_ctr = 0u;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
if (frame_ctr >= frame_paths.size()) {
window.close();
return EXIT_FAILURE;
}
const auto& current_frame = frame_paths[frame_ctr];
add_frame_to_video(current_frame);
if (!frame_texture.loadFromFile(current_frame)) {
std::cout << "Error: couldn't load file \"" << current_frame << "\".\n";
window.close();
return EXIT_FAILURE;
}
sf::Sprite frame_sprite;
frame_sprite.setTexture(frame_texture);
++frame_ctr;
window.clear();
window.draw(frame_sprite);
window.display();
}
}
this will create a window that shows each picture per frame using sf::Texture to load and sf::Sprite to display the image. If no more frames are available, the window gets closed and the program terminates. If you want to add time between frames, you can set e.g. window.setFramerateLimit(10); to have 10 frames / second.
I am confused about how to get inputs from Mouse or Keyboard. As an example, I want to draw little dots on my Mouse position when I pressed the button of my Mouse. Which implementation should I follow?
I have used window.pollEvent function to catch the mouse pressed event in the code below.
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(640,480), "Paint");
std::vector<sf::CircleShape> dots;
while (window.isOpen()) {
sf::Event event;
if (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::MouseButtonPressed) {
sf::CircleShape shape(10);
shape.setFillColor(sf::Color::Black);
shape.setPosition(event.mouseButton.x, event.mouseButton.y);
dots.push_back(shape);
}
}
window.clear(sf::Color::White);
for (auto& i : dots) {
window.draw(i);
}
window.display();
}
return 0;
}
or should I do it in the way like this?
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(640,480), "Paint");
std::vector<sf::CircleShape> dots;
while (window.isOpen()) {
sf::Event event;
if (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
sf::CircleShape shape(10);
shape.setFillColor(sf::Color::Black);
shape.setPosition(sf::Mouse::getPosition().x, sf::Mouse::getPosition().y);
dots.push_back(shape);
}
window.clear(sf::Color::White);
for (auto& i : dots) {
window.draw(i);
}
window.display();
}
return 0;
}
If the latter is the appropriate one, then where the if block that checks if the mouse button is pressed should be located, before window.clear() or between window.clear() and window.draw() ?
I could not understand the different between them thoroughly. SFML documentation, for example, shows the latter implemenatation for gunfire action but I could not figure out why. Thanks...
You are essentially asking about the two ways for handling user input:
Events: handling objects that represent an occurrence.
Real-time input: querying the input device about its real-time state.
Your first approach – calling sf::Window::pollEvent() – relies on events. It is an asynchronous mechanism; the button may not be pressed when your code handles the event. Event handling is usually the way to go if all you are interested in is whether the state of the input device has undergone a changeX, e.g., a button has been pressed or released.
Your second approach – calling sf::Mouse::isButtonPressed() – is based on real-time input. It consists of querying the mouse whether a given button is pressed at the moment of calling the function. This approach for handling user input is usually the way to go if you just want to find out the current state of the input device.
XNote, however, that events can be repeated (e.g., if you keep a key pressed for a long time), and therefore they may not necessarily imply a change in the state of the input device. You can disable this with sf::Window::SetKeyRepeatEnabled(), though.
I made this code that shows a timer and pauses when you press spacebar:
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace sf;
using namespace std;
void events();
bool pause, exitPause;
char key;
double timeFrame, timeTot = 0;
Clock timer;
Text text;
Font font;
RenderWindow window(VideoMode(800, 600), "Window", Style::Close);
int main()
{
font.loadFromFile("C:/Windows/Fonts/arial.ttf");
text.setFont(font);
text.setCharacterSize(15);
window.setFramerateLimit(120);
while (window.isOpen())
{
for (Event event; window.pollEvent(event);) {
if (event.type == Event::Closed)
window.close();
if (event.type == Event::TextEntered) {
key = std::tolower(static_cast<char>(event.text.unicode));
if (key == ' ') {
pause = !pause;
if (!pause) {
timer.restart();
}
}
}
}
if (!pause) {
timeFrame = timer.restart().asSeconds();
timeTot += timeFrame;
text.setString(to_string(timeTot));
window.clear();
window.draw(text);
}
window.display();
}
}
If you test, you will see something curious. When pausing by pressing the spacebar, window.display alternates between the last and the current displayed number.
But if I put window.clear and window.draw together with window.display, the problem does not happen.
if (!pause) {
timeFrame = timer.restart().asSeconds();
timeTot += timeFrame;
text.setString(to_string(timeTot));
}
window.clear();
window.draw(text);
window.display();
I thought windows.display, alone, would only show the last buffer.
What is the problem?
The moment you pause you stop updating the draw buffers. SFML is always double-buffered, and in each iteration you always need to parse input, update whatever needs updating, redraw the "hidden" frame, and then flip the buffers. This is basically a "Game Loop" pattern.
In your code you always parse input, update the timer and pause state based on that, and you always flip the buffers (with window.display()). You only redraw the "hidden" frame buffer if the state is not paused, however.
So, you are seeing the expected output, and you found the correct solution.
As an aside, there are indeed several style issues in your code, including uninitialized variables, which is always dangerous in C++.
So I've been looking around in my code for hours now and finally I think I found the issue with the code. An SFML method doesn't work or I am using it wrong.
I am trying to load a PNG file from my disk into the program so I can render it on screen.
But the picture is never even loaded into the program to begin with it seems. As when I check the debugger I see no actual info about the file I am trying to load in.
I'll show the entire Engine.cpp file first, and then explain step by step what happens.
My Engine.cpp looks like this:
#include "Engine.h"
#include <SFML\Graphics.hpp>
Engine::Engine()
{
}
Engine::~Engine()
{
}
bool Engine::Init()
{
LoadImages();
window = new sf::RenderWindow(sf::VideoMode(800,600,32), "RPG");
if(!window)
return false;
return true;
}
void Engine::LoadImages()
{
sf::Image sprite;
sprite.loadFromFile("C:/Users/Vipar/Pictures/sprite1.png");
imageManager.AddImage(sprite);
testTile = new Tile(imageManager.GetImage(0));
}
void Engine::RenderFrame()
{
window->clear();
testTile->Draw(0,0,window);
window->display();
}
void Engine::ProcessInput()
{
sf::Event evt;
//Loop through all window events
while(window->pollEvent(evt))
{
if(evt.type == sf::Event::Closed)
window->close();
}
}
void Engine::Update()
{
}
void Engine::MainLoop()
{
sf::Image sprite;
sprite.loadFromFile("C:/Users/Vipar/Pictures/sprite1.png");
imageManager.AddImage(sprite);
testTile = new Tile(imageManager.GetImage(0));
//Loop until our window is closed
while(window->isOpen())
{
ProcessInput();
Update();
RenderFrame();
testTile->Draw(0,0,window);
}
}
void Engine::Go()
{
if(!Init())
throw "Could not initialize Engine";
MainLoop();
}
I call this method:
void Engine::LoadImages()
{
sf::Image sprite;
sprite.loadFromFile("C:/Users/Vipar/Pictures/sprite1.png");
imageManager.AddImage(sprite);
testTile = new Tile(imageManager.GetImage(0));
}
It adds the Image to my ImageManager for later use if need be. This is done for a bit of efficiency. Then I apply the Image to my custom class called Tile. It looks like this:
#include "Tile.h"
#include <SFML\Graphics.hpp>
#include <iostream>
Tile::Tile(sf::Image& image)
{
sf::Texture tex;
tex.loadFromImage(image);
baseSprite.setTexture(tex,true);
}
Tile::~Tile()
{
}
void Tile::Draw(int x, int y, sf::RenderWindow* rw)
{
baseSprite.setPosition(x,y);
rw->draw(baseSprite);
}
void Tile::Destroy()
{
delete &baseSprite;
}
Then I draw the Tile on screen to test it out.
Why does this png file not even load into my program to begin with? If you need additional code, please let me know. I am a bit green on this SFML framework and C++ but I am good at Java and C#.
I only work with SFML.net (maybe you should use it?), and I don't like how you're doing things, but...
Throw some debug messages to make sure that all your appropriate
functions/code is getting run.
Clear with a different color and make sure it works.
Your naming is confusing and misleading.
Make sure you've checked the tutorial to see how they draw.
As the title says, I have successfully compiled, linked and ran a program made in sfml-1.6 on Linux Mint 14. I used g++ for compiling. However as soon as I moved the source files to Windows and tried to compile to the Windows equivalent of the sfml libraries, it crashes. The program compiles and links just fine but it crashes BEFORE it reaches main. I have made sure I dont have any global objects/variables in my own .h files. But I cannot do it for the sfml library. I suspected that it might be because the library was broken so I ported the code for sfml 2.0., and the problem persists. Any clues on what I am doing wrong? I have also made sure I dont use any platform specific headers.
Here is my main.cpp
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "World.h"
#include <sstream>
#include <vector>
#include <zip.h>
enum states
{
MENU,
GAME,
PAUSE,
EXIT,
DIE
};
player plr;
sf::Clock timer;
void getKeys(const sf::Input& input);
std::string floatToString(float flt);
int main(int argc, char** argv)
{
sf::RenderWindow window(sf::VideoMode(1024, 768), "sfTest");
window.SetFramerateLimit(60);
sf::Music startSong;
sf::Music endSong;
sf::Music s1, s2, s3;
sf::String musicBy;
musicBy.SetText("Music by Kevin McLeod: www.incompetech.com");
if(!s1.OpenFromFile("Batty McFaddin.ogg"))
return -1;
if(!s2.OpenFromFile("Merry Go.ogg"))
return -1;
if(!s3.OpenFromFile("One-eyed Maestro.ogg"))
return -1;
if(!endSong.OpenFromFile("One-eyed Maestro.ogg"))
return -10;
if(!startSong.OpenFromFile("Comedic Juggernaut.ogg"))
return -15;
endSong.SetVolume(50);
std::vector<sf::Music*> playList;
std::vector<sf::Music*>::iterator mIt;
s1.SetVolume(25);
s2.SetVolume(25);
s3.SetVolume(25);
playList.push_back(&s2);
playList.push_back(&s3);
playList.push_back(&s1);
startSong.SetLoop(true);
startSong.SetVolume(50);
const sf::Input& input = window.GetInput();
plr.setSpeed(.5);
plr.setMaxSpeed(15.0);
plr.setJumpForce(.4f);
plr.setJumpSpeed(16.f);
int state = MENU;
sf::String str;
str.SetText("Welcome to fatrunning!");
sf::String str2;
str2.SetText("Developed by Echoes Entertainment");
str2.Move(0, 100);
sf::String cont;
cont.SetText("Please press enter to play...");
cont.Move(0, 30);
sf::String spd;
sf::String menuHelp;
menuHelp.SetText("Stand on the block equivalent to the level (0-15) and press TAB");
menuHelp.Move(0, 30);
float endTime = 60*5;
float curTime = 0;
sf::Sprite menu;
sf::Image mim;
mim.LoadFromFile("MenuBackground.png");
menu.SetImage(mim);
sf::String scr;
sf::String thanks("Thanks for playing! Your score was: ");
//sf::String tarantulas(" Tarantual tarantulas Everybody loves tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas They're so soft and they're so furry And they're so cute if your vision's blurry all of mine got free but dont you worry though they're crawling up your wall in a big hurry Tarantual tarantulas Everybody loves tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas Don't look now but i have a feeling there's one above you on your ceiling but when they crawl they never fall unless the person under them is nervous at all Tarantual tarantulas Everybody loves tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas \t \t can you feel that itch on the top of your head it could be one of them crawling instead but it wont bite unless it senses fear so just stay calm til' it's gone in a year \t\t Tarantual tarantulas Everybody loves tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas Tarantual tarantulas Everybody loves tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas if there's just fuzz where your hamster was it's propably because of tarantulas Tarantulas tarantulas it's propably because of tarantulas");
//.tarantulas.Move(3000, 0);
thanks.Move(0, 30);
scr.Move(500, 30);
World world;
world.addLevel("lvl1", "lvl1.txt");
world.addLevel("lvl2", "lvl2.txt");
world.addLevel("lvl3", "lvl3.txt");
world.addLevel("lvl4", "lvl4.txt");
world.addLevel("lvl5", "lvl5.txt");
world.addLevel("lvl6", "lvl6.txt");
world.addLevel("lvl7", "lvl7.txt");
world.addLevel("lvl8", "lvl8.txt");
world.addLevel("lvl9", "lvl9.txt");
world.addLevel("lvl10", "lvl10.txt");
world.addLevel("lvl11", "lvl11.txt");
world.addLevel("lvl12", "lvl12.txt");
world.addLevel("lvl13", "lvl13.txt");
world.addLevel("lvl14", "lvl14.txt");
world.addLevel("lvl15", "lvl15.txt");
world.setMenuLevel("menu.txt");
world.regPlr(plr);
bool once = false;
bool unodos = false;
float finalScore = 0;
while (state != DIE)
{
sf::Event e;
while (window.GetEvent(e))
{
if ( e.Type == sf::Event::Closed )
{
window.Close();
state = EXIT;
}
if( e.Type == sf::Event::KeyPressed )
{
if(e.Key.Code == sf::Key::Return)
{
if(!unodos)
{
state = GAME;
unodos = true;
}
}
}
}
getKeys(input);
window.Clear();
switch(state)
{
case MENU:
if(startSong.GetStatus() == sf::Sound::Stopped)
startSong.Play();
window.Draw(menu);
window.Draw(str);
window.Draw(str2);
window.Draw(cont);
break;
case GAME:
if(startSong.GetStatus() == sf::Sound::Playing)
{
mIt = playList.begin();
(*mIt)->Play();
startSong.Stop();
}
if((*mIt)->GetStatus() == sf::Sound::Stopped)
{
mIt++;
if(mIt == playList.end())
mIt = playList.begin();
(*mIt)->Play();
}
timer.Reset();
spd.SetText(floatToString(endTime-plr.time));
world.drawWorld(window);
world.update(input);
plr.update();
window.Draw(plr.getSprite());
window.Draw(spd);
plr.time+=timer.GetElapsedTime();
if(plr.time >= endTime || world.quit)
{
state = EXIT;
plr.time = endTime;
}
if(world.atMenu)
state = PAUSE;
break;
case PAUSE:
if(startSong.GetStatus() == sf::Sound::Playing)
startSong.Stop();
spd.SetText(floatToString(endTime-plr.time));
plr.update();
world.drawWorld(window);
world.update(input);
window.Draw(plr.getSprite());
window.Draw(spd);
window.Draw(menuHelp);
if(!world.atMenu)
state = GAME;
if(world.quit)
state = EXIT;
break;
case EXIT:
if(!once)
{
endSong.Play();
(*mIt)->Stop();
world.addLevel("end", "end.txt");
world.setLevel("end");
once = true;
finalScore = plr.score;
finalScore += (endTime-plr.time);
}
//tarantulas.Move(-3.5, 0);
plr.update();
world.drawWorld(window);
window.Draw(plr.getSprite());
scr.SetText(floatToString(finalScore));
//window.Draw(tarantulas);
window.Draw(musicBy);
window.Draw(thanks);
window.Draw(scr);
if(world.curLvl->atEnd)
state = DIE;
break;
case DIE:
window.Close();
break;
default:
break;
}
window.Display();
}
return 0;
}
std::string floatToString(float flt)
{
std::stringstream ss;
ss << flt;
return ss.str();
}
void getKeys(const sf::Input& input)
{
if(input.IsKeyDown(sf::Key::D))
{
plr.isAcc = true;
plr.right();
}
else if(input.IsKeyDown(sf::Key::A))
{
plr.isAcc = true;
plr.left();
}
if(input.IsKeyDown(sf::Key::Space))
{
plr.isJump = false;
plr.jump();
}
if(!input.IsKeyDown(sf::Key::D) && !input.IsKeyDown(sf::Key::A))
{
plr.isAcc = false;
}
if(!input.IsKeyDown(sf::Key::Space))
plr.isJump = true;
}
That is the whole main.cpp, if you need to look at the other sources, ask me. But the program crashes BEFORE it reaches main. It doesn't even reach the enum define.
This could be due to any undefined or unspecified behavior in
the constructors of objects with static lifetime. One of the
most frequence causes, however, is order of initialization
issues. Do some of your objects with static lifetime use other
objects with static lifetime in their constructor? For example,
does the constructor for player use a static object defined in
World? Or even something from SFML? (A quick glance shows some
objects with static lifetime in the library. You shouldn't use
any of these in any of your constructors of objects with static
lifetime.)
Run the program in the debugger (windbg.exe), that should show you where the exception occurs, with helpful progress text in the output window about what's been loaded so far, any 'swallowed' exceptions, and you can take it from there.
It's possible the crash is due to some incompatibility between how the EXE was compiled and how the library was compiled... check your code-generation flags, character sets, etc.