|
|
|
|
Les boutons du menuPour le moment, notre menu n'est muni que d'une image de fond. L'objectif de cette deuxième partie est de créer une classe Bouton permettant de dessiner un bouton. Lorsque la souris survolera le bouton, celui-ci sera dessiné en surbrillance. Et lorsqu'on cliquera dessus, il sera enfoncé. Pour l'occasion, j'ai dessiné 3 images de bouton que voici : ![]() bouton_pas_survole.bmp ![]() bouton_survole.bmp ![]() bouton_enfonce.bmp Pour donner l'illusion d'un bouton enfoncé, j'ai simplement mis l'ombre en haut à gauche au lieu d'en bas à droite. Si vous voulez utiliser le même bouton que moi, enregistrez les 3 images du bouton au format BMP.
Sommaire du chapitre :
![]() Installation de SDL_ttfTéléchargement de SDL_ttfPour pouvoir écrire du texte sur nos boutons, nous aurons besoin de la bibliothèque SDL_ttf. Pour la télécharger, rendez-vous sur le site de SDL_ttf et téléchargez le fichier SDL_ttf-devel-2.0.10-VC.zip. Installation de SDL_ttfLe *.zip est constitué de deux dossiers : include et lib. Dans le dossier include vous trouverez le fichier SDL_ttf.h. Copiez ce fichier dans le dossier CodeBlocks\MinGW\include\SDL\ avec tous les fichiers de la SDL déjà présents. Il s'agit du fichier qui contient la déclaration des fonctions que votre compilateur pourra utiliser. Pour les utiliser, vous devrez inclure l'entête #include <SDL/SDL_ttf.h>. Pour fonctionner, ces fonctions doivent être accompagnées de leur description. La description des fonctions est déjà compilée dans un fichier SDL_ttf.lib. Ce fichier se situe dans le dossier lib. Votre compilateur en aura besoin pour créer l'exécutable. Copiez ce fichier dans le dossier CodeBlocks\MinGW\lib\. Ne soyez pas étonné de mettre le premier *.lib à côté de plein de fichiers *.a et *.o. Pour que votre compilateur prenne en compte ce *.lib, vous devez l'ajouter à l'éditeur des liens. Pour cela, allez dans le menu Project -> Build Options... puis dans l'onglet Linker settings. Assurez-vous d'être dans le linker du mode "Debug" en cliquant sur "Debug" en haut à gauche. Dans Other linker options, ajoutez la ligne -lSDL_ttf. La bibliothèque SDL_ttf est maintenant installée. Dans le dossier lib de la bibliothèque que vous venez de télécharger, vous avez dû remarquer qu'il y avait trois *.dll. Copiez les à côté de l'exécutable de votre jeu, il en aura besoin pour s'exécuter. Ces trois DLL devront être fournies avec votre jeu. Je vous le rappellerai lorsque nous créerons le setup du jeu. Test de l'installationAfin de s'assurer que la bibliothèque est bien installée, voici un bout de code à insérer dans la méthode Menu::dessinerBoutons() pour tester.
Pour fonctionner, ce code a besoin du fichier Cartonsix NC.ttf (cliquez ici pour le télécharger). Vous devrez le placer à côté de votre exécutable. Il s'agit de la police utilisée pour afficher le message de validation suivant. Vous devrez également inclure l'entête #include <SDL/SDL_ttf.h>. ![]() Un message apparait à l'écran, signifiant que la bibliothèque est bien installée. Attention : Ce code n'est pas du tout optimisé. On s'en contentera pour valider l'installation de la bibliothèque SDL_ttf. Je n'expliquerais pas le fonctionnement de ce bout de code. Si votre code ne compile pas, revoyez l'installation de la bibliothèque. Assurez-vous de ne pas avoir oublié l'entête #include <SDL/SDL_ttf.h>. Si votre code compile mais n'affiche pas le message, cela vient probablement du fait que vous avez oublié de placer le fichier Cartonsix NC.ttf à côté de votre exécutable. La classe BoutonMaintenant que le bibliothèque SDL_ttf est installée, nous allons pouvoir passer aux choses sérieuses. Vous pouvez supprimer le code de test. Création de la classe BoutonNous allons créer une classe Bouton dans des fichiers bouton.h et bouton.cpp.
Le constructeurPour le constructeur, il va falloir faire des choix. Il y a un compromis à faire entre la paramétrabilité et la simplicité d'utilisation des boutons. Dans une première version, j'avais le constructeur suivant :
Ainsi, je pouvais choisir la police, la taille et la couleur de chacun des boutons. Finalement, je me suis rendu compte que je faisais toujours des boutons identiques ; seul le texte et la position du bouton étaient différent. Je vous propose donc ce constructeur avec le strict nécessaire :
Les paramètres texte désigne le texte affiché sur le bouton tandis que x et y sont destinés à positionner le centre du bouton par rapport à la fenêtre. ![]() Le centre du bouton sera choisis comme référence pour positionner le bouton sur la fenêtre Enregistrement des paramètresLes paramètres x et y seront mémorisés dans des attributs déclarés au sein de la classe Bouton comme ceci :
Pour le texte, on créera directement la texture du texte à l'aide d'une méthode creerTextureTexte() que nous allons créer.
Celle-ci aura pour but de créer la texture du texte et de retourner le numéro de la texture. Ce numéro sera inscrit dans un attribut textureTexte. Le destructeur se chargera de libérer la texture.
Création de la texture du textePour créer l'image du texte, nous allons utiliser TTF_RenderText_Blended(). Cette fonction de la bibliothèque SDL_ttf permet de créer une image du texte avec la police passée en premier paramètre et la couleur passée en troisième paramètre. Pour charger la police, nous utiliserons la fonction TTF_OpenFont() qui prend en paramètre le nom du fichier TTF et la taille en pixel de la police. Vous trouverez de nombreuses polices à télécharger sur dafont.com. J'ai choisi d'utiliser Cartonsix NC.ttf. La fonction TTF_RenderText_Blended() retourne un pointeur sur une SDL_Surface de 32 bits : 24 bits pour la couleur, 8 pour la transparence. Les pixels situés autour des lettres sont transparents. Pour le reste, je me suis fortement inspiré de la méthode ConteneurTextures::chargerTexture().
J'ai dû créer de nouveaux attributs :
Chargement des textures du boutonSouvenez-vous, le bouton possède trois images de fond différentes. Pour faire simple, nous réutiliserons notre classe ConteneurTextures. Nous chargerons les trois images du bouton dans le constructeur et nous les libèrerons dans le destructeur. Si plusieurs boutons sont instanciés, le ConteneurTextures n'en chargera qu'un exemplaire, il est prévu pour.
Dessin du boutonNous allons maintenant dessiner le bouton. La méthode dessiner()Nous allons créer une méthode dessiner() qui aura pour effet de dessiner le bouton. En fonction de l'état du bouton, l'une des trois images est dessinée en fond. Dans la classe Bouton, j'ai déclaré une énumération permettant de définir l'état du bouton.
La méthode dessiner() commencera par lire l'état du bouton puis dessinera l'image de fond en conséquence avant d'affichera le texte du bouton.
Pour le moment, on bouchonnera la méthode lectureEtatBouton() en retournant PAS_SURVOLE. Plus tard, nous déterminerons l'état du bouton en fonction de la position de la souris. Dessin du fond du boutonLa méthode dessinerFond() prend en paramètre l'une des trois images à dessiner. On sélectionne cette image, on récupère ses dimensions, puis on la dessine à l'écran.
Attention : L'origine du repère d'OpenGL est en bas à gauche. On doit donc soustraire la position verticale du bouton à la hauteur de la fenêtre. Dessin du texte sur le boutonLe dessin du texte sur le bouton est semblable au dessin du fond du bouton.
Test du boutonInitialisation de SDL_ttfPour fonctionner, notre bouton a besoin que SDL_ttf soit initialisé. Ajoutez TTF_Init() à la fonction Jeu::initSDL(). De même, appelez TTF_Quit() à la fin de la méthode Jeu::executer().
Affichage de quelques boutonsDans la méthode Menu::dessinerBoutons() instanciez et dessinez quelques boutons :
Vous devriez obtenir ceci : ![]() Affichage de quelques boutons Le MIP mapping mis en place dans la gestion des textures a pour effet de lisser les bords du bouton. Gestion de l'état du boutonLe but de la méthode lectureEtatBouton() consiste a déterminer l'état du bouton en fonction de la position de la souris et du bouton gauche de la souris. Je vais vous laisser coder cette méthode, elle n'est pas très difficile. Quelques indices : - La souris est sur le bouton si sa position en X est entre la gauche et la droite du bouton et que sa position en Y est entre le haut et le bas du bouton. - Le bouton est enfoncé si la souris est sur le bouton (indice précédent) et que le bouton gauche de la souris est enfoncé. Voici comment récupérer les données utiles :
Pour les dimensions du bouton, j'ai pris arbitrairement l'une des trois images en supposant qu'elles font la même taille. Lorsque votre méthode sera terminée, vos boutons agiront immédiatement avec la souris. En effet, le retour de la méthode est déjà pris en compte par la méthode dessiner(). La gestion du cliquePour le moment, notre bouton réagit bien à la souris. Mais lorsqu'on clique dessus, rien ne se passe. Ce qui serait bien, ce serait qu'un évènement soit généré lorsqu'on clique sur le bouton. Ainsi, on pourrait le récupérer dans la boucle d'exécution du jeu, comme un évènement SDL. Et bien figurez-vous que les développeurs de la SDL ont tout prévu : il est possible de générer ses propres évènements. Générer son propre type d'évènementUn type d'évènement n'est rien d'autre qu'un nombre. Pour le moment nous avons rencontré les types d'évènements suivants : SDL_QUIT, SDL_MOUSEMOTION et SDL_KEYDOWN. Derrière chacune de ces macros se cache un nombre. Heureusement pour nous, il ne sont pas tous pris : de SDL_USEREVENT à (SDL_MAXEVENTS-1) il n'y a aucune macro SDL de prédéfinie et nous allons pouvoir en utiliser une. Nous allons définir BOUTON_CLIQUE avec le premiers type d'évènement libre. Cette macro sera définie dans boutons.h
Génération et interception de l'évènementPour générer un évènement de type BOUTON_CLIQUE, vous devez déclarer une structure de type SDL_Event, initialiser son champs type et envoyer l'évènement dans la file d'attente des évènements avec la fonction SDL_PushEvent().
En aval, dans la boucle de gestion des évènements de la méthode Jeu::executer(), vous intercepterez l'évènement comme ceci :
Parmi les instructions à exécuter, vous pouvez, par exemple, instancier la scène et l'exécuter
Vous pouvez également choisir de quitter l'application en affectant la valeur FALSE à la variable continuer. Détection d'un clique sur le boutonUn bouton est cliqué lorsqu'il passe de l'état ENFONCE à l'état SURVOLE sans état intermédiaire. Pour détecter ce passage, je me suis mis dans la méthode Bouton::dessiner() entre la lecture de l'état du bouton et la mémorisation de celui-ci.
Mon évènement semble ne jamais être généré. Pourquoi ? Si vous avez associé le clique du bouton à une suite instructions, vous avez probablement dû vous rendre compte que ces instructions ne s'exécutaient pas. J'obtiens le même résultat. Après quelques secondes de réflexion je me suis souvenu que les boutons étaient recréé à chaque fois dans Menu::dessinerBoutons(). L'état précédent du bouton est alors toujours à la valeur à laquelle il est initialisé à la construction. L'état précédent n'est donc jamais ENFONCE ; par conséquent, le bouton ne sera donc jamais détecté comme cliqué. D'ailleurs, cet attribut n'est même pas initialisé, je vous invite à le faire avec la valeur PAS_SURVOLE. Création de la liste des boutonsPour que le clique puisse être détecté, les boutons doivent être existant continuellement. Nous allons donc créer un std::set de Bouton dans la classe Menu. Nous aurons besoin d'une méthode pour les ajouter.
La méthode ajouterBouton() n'est pas très compliqué à créer, elle ne fait qu'instancier dynamiquement un Bouton pour l'ajouter à la liste des boutons.
Les boutons devront être libérés dans le destructeur du menu.
La méthode Menu::dessinerBoutons() devient alors :
L'ajout d'un bouton au menu se fait maintenant à l'aide d'un simple appel à la méthode Menu::ajouterBouton(), comme ceci :
Avec ce code, vous devez obtenir à l'écran deux boutons cliquables. Il reste encore un soucis : tous les boutons sont associés au même case :
Différenciation des boutonsLa différenciation des boutons ressemble à celle des touches du clavier : après avoir détecté le type d'évènement, vous alliez récupérer le "code" de la touche. Et bien pour les boutons, nous allons faire la même chose avec le champ SDL_Event.user.code de type int. Pour chaque bouton, nous initialiserons ce champs à un nombre différent. Lors de la lecture de l'évènement de type BOUTON_CLIQUE, nous irons relire ce champs pour déterminer le bouton qui a été cliqué. Pour cela, nous allons ajouter un attribut code dans la classe Bouton et l'initialiser avec un paramètre passé au constructeur.
Cela implique de modifier le prototype de la méthode Menu::ajouterBouton().
L'ajout d'un bouton se fait maintenant comme ceci :
Génération de l'évènement propre au boutonLors de la génération de l'évènement, on indique le code du bouton.
Lecture du bouton cliquéEn fonction de la valeur du champ evenement.user.code, on aiguille l'exécution du jeu.
Mise au pointDéverrouiller la sourisSi vous cliquez sur "Jouer", cela a pour effet de lancer la scène. A la fin de l'exécution de la scène, le menu reprend la main mais la souris reste invisible et verrouillée dans la fenêtre. Dans le constructeur, nous maintenons verrouillé la souris dans la fenêtre grâce aux instructions suivantes :
Après réflexion, je pense que ce n'est pas à la construction de la scène qu'il faut verrouiller la souris mais plutôt au tout début de l'exécution de la scène. Dans la scène, nous allons donc créer une méthode verrouillerSouris() dans laquelle nous exécuterons ces trois instructions. Cette méthode sera appelée au tout début de l'exécution de la scène. De même, nous ferons une méthode deverrouillerSouris() qui aura l'effet inverse et sera exécutée à la fin de l'exécution de la scène.
Ainsi, votre souris est déverrouillée lorsque le menu réapparait. Notre menu est maintenant constitué de boutons et la création de menu devient très simplifiée. Je tiens à remercier perreet pour avoir contribué au développement de ce menu. État actuel du projet : Jeu_09.zip. ![]() Rédigé par David
Consulté 6938 fois |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hébergeur du site : 1and1.fr Site de création de Jeux Vidéo Apprenez à créer vos propres Jeux Video |
1393682 pages ont été consultées sur le site ! Dont 1360 pages pendant les 24 dernières heures. Page générée en 0.429 secondes Nos partenaires - Otium Production : Aide aux débutants à créer leurs jeux - Les bibliothèques de développement de jeux vidéo |