Section Sciences de la vie
Programmation Orientée Objet
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 :
- du clavier
- de la souris
- ou d'interactions avec l'interface graphique (par exemple appuyer sur le bouton de fermeture de la fenêtre). Rappelons-nous que l'on ne peut toujours pas fermer la fenêtre de notre application en cliquant sur le bouton fermer!
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! } } }
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:
- Le paddle du haut est dirigé par le mouvement horizontale de la souris.
- Le paddle du bas est dirigé par les flèches gauche et droite du clavier.
La première chose que nous allons faire est de modifier la classe Paddle pour ajouter des méthodes de déplacement, à savoir:
- Une méthode (publique) void updatePosition(double x) permettant de modifier la position horizontale du paddle, en fournissant une nouvelle position x. Si la position donnée fait sortir le paddle de l'écran, celui-ci ne sera pas déplacé.
- Une méthode (publique) updatePositionDelta(double delta) permettant de modifier la position horizontale du paddle, en fournissant un déplacement (positif ou négatif) par rapport à l'ancienne position.
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).
- 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);
- 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);
- 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.
Corentin Perret, Jamila Sam - 2013-2025