[C/C++] Récupérer le clavier et la fenêtre avec SDL

Après avoir créé une fenêtre simple la deuxième chose essentielle avant de vouloir programmer une application, un jeu, ou un prototype, est d’ajouter au minimum la possibilité de quitter le programme à l’aide d’une touche ou de la croix en haut de la fenêtre. Comme pour l’autre tutoriel sur la simple fenêtre, on va se concentrer uniquement sur le minimum à savoir pour créer une application minimale. Je ne vais parler ici que du clavier et d’un événement de la fenêtre et le programme doit pouvoir tourner en continue sans attendre d’action de l’utilisateurice. Je ne parlerai pas de la souris ou d’un joystick, ni même de fonctions bloquantes.

La boucle d’exécution

Avant de récupérer les événements, mettons en place une boucle d’exécution. Cette boucle sert à assurer que le programme écoute les événements, affiche quelque chose à l’écran, renouvelle l’image sur l’écran, et tout ce qu’on peut attendre de lui, en continue. Sans boucle, le programme ferait ce qu’on attend, et arriverait à la fin et s’arrêterait. Cette boucle doit bien entendu pouvoir s’arrêter pour permettre de quitter lorsqu’on le désir. Pour cela, on va simplement ajouter une variable booléenne et rendre actif la boucle uniquement si ça valeur est fausse.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main ( void ) {
  bool bQuit = false;
 
  Init ();
 
  SDL_FillRect (_sdlSurface, NULL, SDL_MapRGB (_sdlSurface->format, 0, 0, 0));
  SDL_UpdateWindowSurface (_sdlWindow);
 
  while (!bQuit) { // App loop
    ...
  }
 
  CleanUp ();
 
  return 0;
}

Les événements non-bloquants

Les événements sont les signaux émit par le clavier, la souris, un joystick, ou encore une action sur la fenêtre. Chaque événement déclenché est stocké dans une fil d’attente et le premier de la fil est lu par une fonction qui peut être bloquante ou non-bloquante. On dit que la fonction est bloquante quand elle fige le programme en attente d’un événement de l’utilisateurice. Il existe une fonction permettant de n’attendre qu’un certain temps, mais la très grande majorité du temps, le plus utile est d’éviter de bloquer le programme.

La première chose à faire est de déclarer les événements de SDL, puis on va écouter les événements un par un. Malgré le fais que la fonction d’écoute utilisée ici n’est pas bloquante, un seul événement sera écouté à chaque fois qu’on appelle la fonction. Ce qui signifie que si cette fonction est appelé dans une condition SI, alors d’autres événements déclenchés par l’utilisateurice ne seront pas traité. Il faut donc mettre la fonction d’écoute dans une boucle pour parcourir la totalité de sa liste d’attente.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    // Event management
    SDL_Event oEvent;
    while ( SDL_PollEvent (&oEvent) == 1 ) {
      switch(oEvent.type) {
        case SDL_WINDOWEVENT: // Window event
          if (oEvent.window.event == SDL_WINDOWEVENT_CLOSE) {
            bQuit = true;
          }
          break;
        case SDL_KEYUP: // Keyboard event
          if (oEvent.key.keysym.sym == SDLK_ESCAPE) {
            bQuit = true;
          }
          break;
        default:
          break;
      }
    }

Maintenant, que cela est fait, il reste à activer notre variable booléenne lorsque soit on appuie sur la touche Echap du clavier, soit on clique sur la croix en haut de la fenêtre. SDL fournit des noms d’événements pour indiquer quel événement on veut associer à une action.

Conclusion

Voilà, dorénavant notre programme tout simple peut s’arrêter uniquement quand on le veut. D’autres événements vont pouvoir être appelés dans notre application, selon ce qu’on veut obtenir, en suivant la même logique. Pour la souris et le joystick, il y a une légère différence, mais ça fera l’objet d’un autre petit tutoriel. Voici le code final dans la fonction main de notre simple fenêtre.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main ( void ) {
  bool bQuit = false;
 
  Init ();
 
  SDL_FillRect (_sdlSurface, NULL, SDL_MapRGB (_sdlSurface->format, 0, 0, 0));
  SDL_UpdateWindowSurface (_sdlWindow);
 
  while (!bQuit) { // App loop
    // Event management
    SDL_Event oEvent;
    while ( SDL_PollEvent (&oEvent) == 1 ) {
      switch(oEvent.type) {
        case SDL_WINDOWEVENT: // Window event
          if (oEvent.window.event == SDL_WINDOWEVENT_CLOSE) {
            bQuit = true;
          }
          break;
        case SDL_KEYUP: // Keyboard event
          if (oEvent.key.keysym.sym == SDLK_ESCAPE) {
            bQuit = true;
          }
          break;
        default:
          break;
      }
    }
  }
 
  CleanUp ();
 
  return 0;
}

Si vous avez aimé cet article, vous pouvez me faire un don en Ethereum 🙂
Ethereum : 0xab7dD988aD7348C75db90343591596974A435803

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *