SFML community forums

Help => Graphics => Topic started by: justcolorado on January 14, 2012, 03:11:21 am

Title: Redrawing Sprites in a Multi - Threaded Program
Post by: justcolorado on January 14, 2012, 03:11:21 am
I am working on my first game.  I have been stuck for the last few hours and I just cannot figure out how to redraw my sprite in a separate thread.   First I created a struct with a bunch of pointers.  Then I set up a new thread and passed the struct in.  Everything worked great until I tried to redraw the sprite.

Whenever I try to access the sf::RenderWindow.Draw Function, I don't have the right Object type to pass in.  It needs a reference to a Sprite Object, and I only have a pointer.
I tried converting it with a line like the one below but the compiler rejected it with this message: error C2440: 'initializing' : cannot convert from 'sf::Sprite *' to 'sf::Sprite &'
Code: [Select]
Sprite& rPlayer (pSprite);

I tried not using a pointer and just including a Sprite Object in the Struct.  It compiled but when the thread launched, the program froze up for a few seconds, and gave me a bunch of OpenGL error messages in the console window.  I can't figure out what to do with my Pointer so I can pass my sprite in to the sf::RenderWindow.Draw function a separate thread.

Any Help would be greatly appreciated!

My Code looks something like this.

Code: [Select]

struct UserData{
int* pMap;
RenderWindow* pApp;
Sprite* pSprite;
AnimationClass* pAnimator;
};

void ThreadFunction(void* UserData)
{

    for (int i = 0; i < 10; ++i)
{
Data->pAnimator->myAnimation(pSprite);
Data->pApp->Draw(???????What can I pass in here???????);
}
}


int main()
{

    UserData Data = { pMap, pApp, pSprite, pAnimator };
    sf::Thread myThread(&ThreadFunction, &Data);
    myThread.Launch();

    return EXIT_SUCCESS;

}
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: Tex Killer on January 14, 2012, 07:43:40 am
You can pass a pointer like this:
Draw(*pointer)
But I don't think you can access the RenderWindow from multiple threads. Laurent should know better than me, though.
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: Laurent on January 14, 2012, 09:42:43 am
You can't draw from multiple threads. But it seems like a bad solution for what you want to do (animation?).
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: Tank on January 14, 2012, 09:45:21 am
Btw, *foo is called dereferencing (it calls the operator*() function which returns Type&, i.e. a reference).

And yep, the OpenGL context can be active in one thread at a time only. Why did you choose to render from multiple threads?
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: justcolorado on January 14, 2012, 11:34:16 pm
Thanks for your replies.  Now I am not sure how to achieve what I want. When I broke it into two separate threads, the animation sequence I wanted was jerky and would skip frames, because the only thing redrawing the screen was in Main.  

The reason for me wanting to start another thread was:

I want to have my character freeze and do an animation of about 1 second on certain collisions, but I do not want this to stop the enemy from advancing.


So what is the best approach to achieve this?
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: Groogy on January 15, 2012, 12:44:25 am
Your way off if that's what you want to do. This can be done and should be done single-threaded. You don't have to play the entire animation directly in a sequence. You just have to advance the animation frame when enough time have passed. Check out the animation classes in the SFML Wiki (https://github.com/SFML/SFML/wiki).

You are doing a common rookie mistake here when it comes to threads. And I better stop talking here or I can give hour long lectures on how to properly use threads to achieve optimal parallelism (which is their intended usage). And why not to use threads to complete a single task in parallel like you are doing.
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: justcolorado on January 15, 2012, 01:02:41 am
Quote from: "Groogy"
Your way off if that's what you want to do. This can be done and should be done single-threaded. You don't have to play the entire animation directly in a sequence. You just have to advance the animation frame when enough time have passed. Check out the animation classes in the SFML Wiki (https://github.com/SFML/SFML/wiki).

You are doing a common rookie mistake here when it comes to threads. And I better stop talking here or I can give hour long lectures on how to properly use threads to achieve optimal parallelism (which is their intended usage). And why not to use threads to complete a single task in parallel like you are doing.


Thanks.  I will just keep it all in one thread. That should be easy enough to do.  What about playing a separate sound above the background music.  Should this also stay in the main thread?
Title: Redrawing Sprites in a Multi - Threaded Program
Post by: Groogy on January 15, 2012, 01:18:45 am
Quote from: "justcolorado"
What about playing a separate sound above the background music.  Should this also stay in the main thread?


Technically no, they need a seperate thread. But SFML already does that for you in the Audio module if I am not mistaken. There were even some heated discussion of it for some managed language binding where the bindings developer complained that SFML had threads under-the-hood that he couldn't touch. Though even if he experienced "problems" with it I never did while making rbSFML.