SFML community forums
Help => System => Topic started by: Kalith on June 27, 2010, 07:15:39 pm
-
Hello !
Sorry to bother you every time... But I've been using sf::Thread to create a loading screen and I can't seem to create resources properly. Using the code from the tutorials :
#include <SFML/Graphics.hpp>
sf::Image* pImage = NULL;
void CreateImage(void*)
{
pImage = new sf::Image();
pImage->LoadFromFile("sprite.png");
}
int main()
{
// Create the main rendering window
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Graphics");
// Load the sprite image from a file, withing another thread
sf::Thread Thread(&CreateImage);
Thread.Launch();
// Make sure the Image has been created
Thread.Wait();
// Create the sprite
sf::Sprite Sprite(*pImage);
// Change its properties
Sprite.SetColor(sf::Color(0, 255, 255, 128));
Sprite.SetPosition(200.f, 100.f);
Sprite.SetScale(2.f, 2.f);
// Start game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
}
// Clear screen
App.Clear();
// Display sprite in our window
App.Draw(Sprite);
// Display window contents on screen
App.Display();
}
delete pImage;
return EXIT_SUCCESS;
}
This code displays a plain white (well, blue) sprite on the screen.
If you call CreateImage(NULL) directly without using the thread, it works perfectly and the content of the image is displayed.
I've tried with boost::thread and get the same problem, so I guess it's not sf::Thread related?
As always, using SFML 2.0 (15/06/2010) on Windows XP with MinGW.
Am I doing something wrong ?
-
Okay nevermind.
When using the OpenGL context in another thread, you have to disable the contex from the main thread, then enable it in the new thread.
When you're done using it, disactivate it in the new thread and activate it again in the main thread :
#include <SFML/Graphics.hpp>
sf::Image* pImage = NULL;
sf::RenderWindow* pWindow = NULL;
void CreateImage(void*)
{
pWindow->SetActive(true);
pImage = new sf::Image();
pImage->LoadFromFile("sprite.png");
pWindow->SetActive(false);
}
int main()
{
// Create the main rendering window
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Graphics");
pWindow = &App;
// Load the sprite image from a file, withing another thread
sf::Thread Thread(&CreateImage);
pWindow->SetActive(false);
Thread.Launch();
// Make sure the Image has been created
Thread.Wait();
pWindow->SetActive(true);
// Create the sprite
sf::Sprite Sprite(*pImage);
// Change its properties
Sprite.SetColor(sf::Color(0, 255, 255, 128));
Sprite.SetPosition(200.f, 100.f);
Sprite.SetScale(2.f, 2.f);
// Start game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
}
// Clear screen
App.Clear();
// Display sprite in our window
App.Draw(Sprite);
// Display window contents on screen
App.Display();
}
delete pImage;
return EXIT_SUCCESS;
}
It's explained in Window::SetActive() (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Window.htm#b4e6bf9911297d74af92d7251c3dc536).
Maybe you could add an entry in the thread tutorial ? Just a simple warning that links to the docs for example.
-
You can use another context so that your main thread can continue to do whatever it was doing:
void CreateImage(void*)
{
sf::Context context;
pImage = new sf::Image();
pImage->LoadFromFile("sprite.png");
}
-
Just found out, yes :)
Thank you, it works perfectly!