Attention: cette page se réfère à une ancienne version de SFML. Cliquez ici pour passer à la dernière version.

Gérer le temps

Introduction

Le temps n'est habituellement pas un gros sujet en soi, mais dans une application temps réel, il est important de le gérer correctement, comme nous allons le voir dans ce nouveau tutoriel.

Mesurer le temps

Dans la SFML, vous mesurez le temps avec la classe sf::Clock. Elle définit deux fonctions : Reset(), pour remettre à zéro l'horloge, et GetElapsedTime(), pour récupérer le temps écoulé depuis le dernier appel à Reset(). Le temps est défini en secondes, comme toutes les durées que vous trouverez dans la SFML.
Comme vous le voyez, cette classe est loin d'être compliquée.

sf::Clock Clock;

while (App.IsOpened())
{
    // Traitement des évènements

    // Récupération du temps écoulé depuis le dernier tour de boucle
    float Time = Clock.GetElapsedTime();
    Clock.Reset();

    // Affichage de la fenêtre
}

Récupérer le temps écoulé peut être très utile si vous avez à incrémenter une variable à chaque tour de boucle (une position, une orientation, ...). Si vous ne tenez pas compte du facteur temps, votre simulation ne produira pas les mêmes résultats selon que l'application tourne à 60 images par seconde ou à 1000 images par second. Par exemple, ce bout de code va produire un mouvement dépendant du taux de rafraîchissement :

const float Speed = 50.f;
float Left = 0.f;
float Top  = 0.f;

while (App.IsOpened())
{
    if (App.GetInput().IsKeyDown(sf::Key::Left))  Left -= Speed;
    if (App.GetInput().IsKeyDown(sf::Key::Right)) Left += Speed;
    if (App.GetInput().IsKeyDown(sf::Key::Up))    Top  -= Speed;
    if (App.GetInput().IsKeyDown(sf::Key::Down))  Top  += Speed;
}

Alors que celui-ci va assurer une vitesse constante quelque soit le matériel :

sf::Clock Clock;

const float Speed = 50.f;
float Left = 0.f;
float Top  = 0.f;

while (App.IsOpened())
{
    float ElapsedTime = Clock.GetElapsedTime();
    Clock.Reset();

    if (App.GetInput().IsKeyDown(sf::Key::Left))  Left -= Speed * ElapsedTime;
    if (App.GetInput().IsKeyDown(sf::Key::Right)) Left += Speed * ElapsedTime;
    if (App.GetInput().IsKeyDown(sf::Key::Up))    Top  -= Speed * ElapsedTime;
    if (App.GetInput().IsKeyDown(sf::Key::Down))  Top  += Speed * ElapsedTime;
}

La plupart du temps, vous aurez à mesurer le temps écoulé depuis le dernier rafraîchissement. La classe sf::Window fournit une fonction utile pour récupérer ce temps sans avoir à gérer une horloge : GetFrameTime(). Ainsi nous pourrions ré-écrire notre code de la manière suivante :

const float Speed = 50.f;
float Left = 0.f;
float Top  = 0.f;

while (App.IsOpened())
{
    if (App.GetInput().IsKeyDown(sf::Key::Left))  Left -= Speed * App.GetFrameTime();
    if (App.GetInput().IsKeyDown(sf::Key::Right)) Left += Speed * App.GetFrameTime();
    if (App.GetInput().IsKeyDown(sf::Key::Up))    Top  -= Speed * App.GetFrameTime();
    if (App.GetInput().IsKeyDown(sf::Key::Down))  Top  += Speed * App.GetFrameTime();
}

Mesurer le taux de rafraîchissement (framerate)

Le framerate étant l'inverse de la durée d'un rafraîchissement, vous pouvez facilement le déduire du temps écoulé entre deux rafraîchissements :

sf::Clock Clock;

while (App.IsOpened())
{
    float Framerate = 1.f / Clock.GetElapsedTime();
    Clock.Reset();
}

// Ou bien :

while (App.IsOpened())
{
    float Framerate = 1.f / App.GetFrameTime();
}

Si votre framerate se retrouve bloqué autour de 60 images par seconde ne vous inquiétez pas : cela signifie simplement que la synchronisation verticale (v-sync) est activée. Basiquement, lorsque la synchronisation verticale est activée, l'affichage sera synchronisé avec le taux de rafraîchissement du moniteur. Cela signifie que vous ne pourrez jamais afficher plus d'images que l'écran ne le peut. Et c'est une bonne chose, étant donné que cela va empêcher votre application de tourner à des vitesses incroyables comme 2000 images par seconde, et produire des artefacts visuels ou des comportements inatendus.

Cependant, vous voudriez parfois effectuer des tests pour faire des optimisations, et vous voudriez un taux de rafraîchissement maximum. SFML vous autorise à désactiver la synchronisation verticale si vous le voulez, avec la fonction UseVerticalSync :

App.UseVerticalSync(false);

Notez que la synchronisation verticale est désactivée par défaut.

Vous pouvez également fixer le taux de rafraîchissement à une fréquence donnée :

App.SetFramerateLimit(60); // Limite à 60 images par seconde
App.SetFramerateLimit(0);  // Limite désactivée

Conclusion

La gestion du temps n'a plus de secret pour vous, et vous êtes prêt à écrire des applications temps réel robustes. Dans le prochain tutoriel, nous allons jouer un peu avec OpenGL, pour finalement avoir quelque chose à afficher dans notre fenêtre.
Cependant, si vous n'êtes pas intéressé par l'utilisation d'OpenGL avec la SFML, vous pouvez immédiatement sauter à la section suivante concernant le module graphique.