Ecole Polytechnique Fédérale de Lausanne
Section Sciences de la vie
Programmation Orientée Objet
Tutoriel librairie graphique (SFML)

III. Gestion des événements: déplacement des paddles

Jusque là, nous savons ouvrir une fenêtre et y dessiner toutes sortes de choses. Toutefois, il manque un aspect important à nos possibilités: l'interaction avec l'utilisateur.

Cette interaction peut se faire par exemple par le biais :

C'est là qu'intervient la gestion des événements. Reprenons notre squelette d'application SFML et intéressons-nous à la boucle la plus interne :

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Titre");

    while (window.isOpen())
    {
        //Traitement des événements
		sf::Event event;
        while (window.pollEvent(event))
        {
	      //...
		}
		//Fin du traitement des événements
        //...
        window.clear();
        window.display();
    }

    return EXIT_SUCCESS;
}

La boucle while la plus interne va en fait parcourir tous les événements (représentés par la classe sf::Event qui ont été déclenchés depuis le dernier passage dans la boucle de rendu. Ce peut-être une indication de mouvement de souris, d'appui sur une touche ou sur un élément d'interface graphique. A nous ensuite de traiter chaque événement selon son type et ce que nous souhaitons en faire.

Fermeture de fenêtre

La détection et le traitement d'un événement "fermeture de fenêtre" se fait ainsi:

 while (window.pollEvent(event))
{
	if (event.type == sf::Event::Closed)
	{
		//Traitement de l'événement, par exemple fermeture de la fenêtre:
		window.close();
	}    
}

Événements clavier

La détection et le traitement d'un événement "appui sur une touche" se fait ainsi:

 while (window.pollEvent(event))
{
	if (event.type == sf::Event::KeyPressed)
	{
		//Traitement de l'événement
		//La touche pressée est stockée dans event.key.code
	}    
}

La touche pressée est disponible dans event.key.code. Il s'agit d'un attribut de type sf::Keyboard::Key, qui est un enum dont toutes les valeurs sont disponibles dans la documentation.

Voici un exemple d'utilisation:

 while (window.pollEvent(event))
{
	if (event.type == sf::Event::KeyPressed)
	{
		switch(event.key.code)
		{
			case(sf::Keyboard::A):
			//A!
			break;
			case(sf::Keyboard::Left):
			//Flèche gauche!
			break;
			default:
			break;
		}
	}    
}

Pour d'autres types d'événements clavier, voir la documentation.

Évènements souris

Deux types d'événement souris vont nous intéresser: l'appui (ou plutôt le relâchement) d'un bouton(sf::Event::MouseButtonEvent) et le déplacement (sf::Event::MoveEvent).

Voici un exemple d'utilisation combinant les deux:

 while (window.pollEvent(event))
{
	if (event.type == sf::Event::MouseMoved)
	{
		//Nouvelle position stockées dans event.mouseMove.x et event.mouseMove.y
		int x(event.mouseMove.x);
		int y(event.mouseMove.y);
	}
    else if (event.type == sf::Event::MouseButtonReleased)
         {
           //Position au clic stockée dans event.MouseButton.x et event.MouseButton.y
           int x(event.mouseButton.x);
           int y(event.mouseButton.y)

           //Code du bouton stocké dans event.MouseButton.button. Par exemple
           if (event.MouseButton.button==sf::Mouse::Left)
           {
              //Bouton gauche!
           }

         }
}
Les notations utilisées vous sembleront sans doute compliquées à comprendre à ce stade. Pour l'instant il est suffisant de les appliquer telles qu'elles, en sachant juste ce qu'elles signifient et en étant capable d'adapter quelques éléments mineurs (par exemple remplacer sf:::Mouse::Left par sf::Mouse::Right ou sf::Mouse::Middle quand nécessaire).

La touche pressée est disponible dans event.MouseButton.button. Il s'agit d'un attribut de type sf::Mouse::Button, qui est un enum dont toutes les valeurs sont disponibles dans la documentation.

En premier, implémentez la possibilité de fermer la fenêtre en appuyant simplement sur le bouton de fermeture.

Ensuite, nous allons implémenter le mouvement des Paddle, avec le fonctionnement suivant:

La première chose que nous allons faire est de modifier la classe Paddle pour ajouter des méthodes de déplacement, à savoir:

Ensuite, implémentez la gestion des événements en conséquence.

La première méthode sera utilisée pour le déplacement à la souris, la seconde pour le déplacement au clavier (déplacement d'un nombre donné d'unités à chaque appui sur la touche).

Indications :
  1. l'idée est que si un événement de type sf::Event::MouseMoved est détecté par exemple, il faut déplacer horizontalement le Paddle du haut à l'endroit où se trouve la souris (event.mouseMove.x);
  2. de façon similaire, si un événement de type sf::Event::KeyPressed est détecté, si la touche pressée vaut sf::Keyboard::Left il faut déplacer le Paddle du bas d'un delta (par exemple 5) vers la gauche (idem mais vers la droite pour sf::Keyboard::Left);
  3. soit rectangle un sf::RectangleShape. La tournure rectangle.getPosition().x retourne la coordonnées en x de rectangle et rectangle.getPosition().y retourne la coordonnées en y.

Les paddles devraient maintenant pouvoir être déplacés à la souris, respectivement au clavier.

Vous pouvez télécharger une solution de cette étape.

Tutorial SFML
Corentin Perret, Jamila Sam - 2013-2025