At the moment I'm experimenting with sf::Thread but I get some problems with global sf::Text variables and I'm not sure if SFML is messing something up or my lack of knowledge.
I choose to use the member function version for thread creation and setup three files as an example.
What I basicly want to do is display how each thread is running.
So the code seems in my opinion okay and using a sf::Mutex for the mUPS doesn't change anything.
The problem now is, that only some random numbers get displayed on the window altough the std::cout looks okay.
When further tempering with the text output I noticed that:
1) When setting the text outside of the Draw() function it doesn't get displayed at all (I set it at the intitializastion).
2) Using the mFPS which is declared outside of the Draw function and assign some numbers all the '0' don't get displayed.
3) When using a sf::Text local to the thread it gets displayed without problems.
4) It seems everything works fine with a non-member function without argument.
What I ask myself now, can't I use external sf::Text? If not how would I share text between threads? Or better how would a use threads to draw stuff?
main.cpp
#include "Task.hpp"
int main(int argc, char **argv)
{
Task test;
test.Run();
return EXIT_SUCCESS;
}
Task.hpp
#ifndef TASK_HPP
#define TASK_HPP
#include <SFML/Graphics.hpp>
class Task
{
public:
Task();
~Task();
void Draw();
void Update();
void Run();
private:
sf::Text mFPS;
sf::Text mUPS;
bool mRun;
sf::Mutex mLocker;
sf::Font mFont;
};
#endif // TASK_HPP
Task.cpp
#include "Task.hpp"
#include <SFML/System.hpp>
#include <sstream>
#include <iostream>
Task::Task() : mFPS(sf::String("FPS: 30")),
mUPS(sf::String("UPS: 30")),
mRun(false),
mLocker(),
mFont()
{
mFont.LoadFromFile("FreeMono.ttf");
mFPS.SetFont(mFont);
mFPS.SetPosition(sf::Vector2f(10.f, 10.f));
mFPS.SetColor(sf::Color::White);
mUPS.SetFont(mFont);
mUPS.SetPosition(sf::Vector2f(10.f, 50.f));
mUPS.SetColor(sf::Color::White);
}
Task::~Task() { }
void Task::Draw()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
window.SetFramerateLimit(30);
sf::Clock clock;
float currentFPS = 30;
while(mRun)
{
// Process events
sf::Event event;
while (window.PollEvent(event))
{
// Close window : exit
if (event.Type == sf::Event::Closed)
{
mRun = false;
window.Close();
}
}
std::stringstream ss;
currentFPS = 1.f/clock.GetElapsedTime().AsSeconds();
ss << "FPS: " << currentFPS;
std::cout << ss.str() << std::endl;
mFPS.SetString(sf::String(ss.str()));
window.Clear();
window.Draw(mFPS);
window.Draw(mUPS);
window.Display();
// Reset
clock.Restart();
}
}
void Task::Update()
{
sf::Clock clock;
float currentUPS = 30;
while(mRun)
{
currentUPS = 1.f/clock.GetElapsedTime().AsSeconds();
std::ostringstream oss;
oss << "UPS: " << (unsigned int)(currentUPS);
{
sf::Lock::Lock(mLocker);
mUPS.SetString(sf::String(oss.str()));
}
// Reset
clock.Restart();
}
}
void Task::Run()
{
mRun = true;
sf::Thread thread1(&Task::Draw, this);
thread1.Launch();
sf::Thread thread2(&Task::Update, this);
thread2.Launch();
thread2.Wait();
thread1.Wait();
}
Thanks for any help!
eXpl0it3r
Okay I shortened the code, also I think the code from the first post as some side-effects on multiple levels, e.g. I got a crash in WglContext.hpp even though I used an additional font and linked staticlly.
But let's first concentrait on the fact that the text stuff gets kinda messed up.
New Code:
#include <SFML/Graphics.hpp>
#include <sstream>
class Task
{
public:
Task() : mCounter(sf::String("FPS: 30"))
{
mCounter.SetPosition(sf::Vector2f(10.f, 10.f));
mCounter.SetColor(sf::Color::White);
}
void Draw()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
float counter = 30;
while(window.IsOpen())
{
sf::Event event;
while(window.PollEvent(event))
if(event.Type == sf::Event::Closed)
window.Close();
counter++;
mCounter.SetString("FPS: " + GetString(counter));
window.Clear();
window.Draw(mCounter);
window.Display();
}
}
void Run()
{
sf::Thread thread1(&Task::Draw, this);
thread1.Launch();
thread1.Wait();
}
private:
sf::Text mCounter;
sf::String GetString(float aFloat)
{
std::stringstream ss;
ss << aFloat;
return sf::String(ss.str());
}
};
int main()
{
Task test;
test.Run();
return 0;
}
I still call the Run() function which creates now only one thread.
The sf::Text mCounter gets declared and initialized inside the main thread. Additionally I introduced a GetString() function which converts a float to a sf::String.
I now get displayed the numbers, but when ever there should be a 0 it just doesn't get displayed. Also the 'FPS:' doesn't get shown.
(https://legacy.sfmluploads.org/cache/pics/207_counter.png)
Does sf::Text also need a valid OpenGL context? I've just seen that on Linux you can't create a sf::Texture before initializing the RenderWindow.