Bonjour,
Mon jeu possede plusieurs ecrans differents deja en place, et j'aimerais faire un bel effet de transition avec Fade in & fade out.
L'appel de la transition se fait en dehors du thread de rendu graphique.
Voici la classe:
#ifndef FADE_H_INCLUDED
#define FADE_H_INCLUDED
/// Used for screen fading.
#include <SFML/Graphics.hpp>
class Fade
{
public:
Fade() : m_fadein(false), m_fadeout(false), m_started(false), m_rect(sf::RectangleShape()), m_alpha(0), m_goal(0) { };
~Fade() { }
/// Called by the secondary thread
void FadeOut() {
/// Setting the flag to true, so the rendering thread knows that he has to fade out the screen
/// Regular screen to full black screen.
m_fadeout = true; m_alpha = 0; m_goal = 255;
m_rect.setFillColor(sf::Color(0,0,0,0));
}
/// Called by the secondary thread
void FadeIn() {
/// Setting the flag to true, so the rendering thread knows that he has to fade in the screen
m_fadein = true; m_alpha = 255; m_goal = 0;
//m_rect.setFillColor(sf::Color(0,0,0,255));
}
/// Simply returns the shape for displaying
inline sf::RectangleShape& getShape() { return m_rect; }
/// Used by the main loop, if this returns true, the thread will draw it
inline bool doFade() {
if(m_fadein && (m_alpha > m_goal)) // black > screen
{
m_alpha--;
m_rect.setFillColor(sf::Color(0,0,0,m_alpha));
return true;
}
else if(m_fadeout && (m_alpha < m_goal)) // screen > black
{
m_alpha++;
m_rect.setFillColor(sf::Color(0,0,0,m_alpha));
return true;
}
else { return false; }
}
/// Used by the secondary thread, if this is true, it means the main thread is fading. Some sort of mutex :P
inline bool Fading() const { return (m_started); }
/// Used by the main thread to know if he has to perform a fade
inline bool requestFade() const { return (m_fadein | m_fadeout); }
/// Both used by the main thread to change the flags, so the secondary thread will know that he is fading. (cf: Fading())
void startFading() { m_started = true; }
void doneFading() { m_started = false; m_fadein = false; m_fadeout = false; }
inline static const unsigned int fadingTime() { return fading_time; }
private:
/// Flag: Fade in action
bool m_fadein;
/// Flag: Fade out action
bool m_fadeout;
/// Flag: if theres a fade processing
bool m_started;
/// SFML's shape
sf::RectangleShape m_rect;
/// Current alpha.
unsigned int m_alpha;
/// Alpha to reach
unsigned int m_goal;
static const unsigned int fading_time = 10; // in ms
};
#endif // FADE_H_INCLUDED
Quand je veux faire un fade, de mon thread secondaire, je fais ceci:
m_gameui.getRenderer().getFader().FadeOut(); // Appel a fade out : ecran > ecran noir
nextScreen(); // Simple routine qui permet a l'ecran de se mettre a jour sous l'ecran noir
while(m_gameui.getRenderer().getFader().Fading()) {} // On attend pendant que le fade se termine (donc ecran noir
m_gameui.getRenderer().getFader().FadeIn(); // Et hop on retourne au nouvel ecran
Et mon thread principal:
short LoginScreen::Run()
{
m_desktop.GetEngine().LoadThemeFromFile("Data/css/login.css");
/// Add the UI to the window
m_desktop.Add(getScreen());
/// Rendering loop
while(m_game.getRenderer().getApp().isOpen() && m_game.isRunning())
{
/// Clearing the window
m_game.getRenderer().getApp().clear();
sf::Event event;
while(m_game.getRenderer().getApp().pollEvent(event))
{
/// Event handling
/// SFGUI
m_desktop.HandleEvent(event);
/// SFML
if(event.type == sf::Event::Closed)
{
/// This will automatically terminate the networker thread & nicely exit the game
m_game.crash();
}
}
m_game.getRenderer().getApp().resetGLStates();
/// Drawings (SFGUI)
/// UI
if(changeScreen())
{
oldScreen()->Show(false);
m_desktop.Remove(oldScreen());
getScreen()->Show(true);
m_desktop.Add(getScreen());
}
/// Fading out (screen to black)
if(m_game.getRenderer().getFader().requestFade())
{
m_game.getRenderer().getFader().startFading();
}
if(m_game.getRenderer().getFader().Fading())
{
if(m_game.getRenderer().getFader().doFade())
{
m_game.getRenderer().getApp().draw(m_game.getRenderer().getFader().getShape());
}
else
{
m_game.getRenderer().getFader().doneFading();
}
}
/// Displayings
m_desktop.Update(0.f);
m_game.getRenderer().display(m_game.getRenderer().getApp());
m_game.getRenderer().getApp().display();
}
return -1;
}
Le probleme ?
L'ecran devient tout noir d'un coup, et j'ai acces a l'ecran caché derriere ce noir.
Comment faire pour avoir une belle transition ?
Merci d'avance,
nico