{"id":606,"date":"2014-02-24T17:48:25","date_gmt":"2014-02-24T15:48:25","guid":{"rendered":"http:\/\/pila.fr\/wordpress\/?p=606"},"modified":"2015-06-30T15:46:59","modified_gmt":"2015-06-30T13:46:59","slug":"simple-xbox-360-controller-une-classe-permettant-lutilisation-des-manettes-xbox-360-sous-windows-avec-qt","status":"publish","type":"post","link":"https:\/\/pila.fr\/wordpress\/archives\/606","title":{"rendered":"Simple Xbox 360 Controller : une classe permettant l&rsquo;utilisation des manettes Xbox 360 sous Windows avec Qt"},"content":{"rendered":"<p style=\"text-align: justify;\">Pour utiliser les manettes de xbox 360 sous Windows, Microsoft a mis au point la librairie Xinput. Si plusieurs d\u00e9veloppeurs ont d\u00e9j\u00e0 mis a disposition des classes C++ pour faciliter l&rsquo;acc\u00e8s \u00e0 Xinput, aucune n&rsquo;a \u00e9t\u00e9 \u00e9crite pour tirer partie du m\u00e9canisme des slot \/ signal de Qt. La classe SimpleXbox360Controller a pour objectif de pallier ce manque.<\/p>\n<div id=\"attachment_607\" style=\"width: 500px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/pila.fr\/wordpress\/wp-content\/uploads\/SimpleXbox360Controller.jpg\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-607\" class=\" wp-image-607 \" src=\"http:\/\/pila.fr\/wordpress\/wp-content\/uploads\/SimpleXbox360Controller.jpg\" alt=\"Le logiciel de test Simple Xbox 360 Controller Tester\" width=\"500\" height=\"382\" srcset=\"https:\/\/pila.fr\/wordpress\/wp-content\/uploads\/SimpleXbox360Controller.jpg 684w, https:\/\/pila.fr\/wordpress\/wp-content\/uploads\/SimpleXbox360Controller-300x228.jpg 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><p id=\"caption-attachment-607\" class=\"wp-caption-text\">Le logiciel de d\u00e9mo :\u00a0 Simple Xbox 360 Controller Tester<\/p><\/div>\n<p>Le programme d&rsquo;exemple Xbox 360 Controller Tester permet de tester rapidement le fonctionnement d&rsquo;une manette. L&rsquo;ex\u00e9cutable est disponible ici : <a href=\"http:\/\/pila.fr\/wordpress\/wp-content\/uploads\/SimpleXbox360ControllerTester.zip\">SimpleXbox360ControllerTester<\/a><\/p>\n<p>L&rsquo;ensemble du code de la classe, celui du programme d&rsquo;exemple, et la documentation en anglais du code est disponible sur <a title=\"Simple Xbox 360 Controller sur GitLab\" href=\"https:\/\/gitlab.com\/Pilatomic\/simple-xbox-360-controller\/tree\/master\" target=\"_blank\">GitLab<\/a>.<\/p>\n<p>Pour mes amis francophones, vous trouverez ci-dessous une version fran\u00e7aise de la doc :<br \/>\n<!--more--><\/p>\n<h1 style=\"text-align: justify;\">Important<\/h1>\n<p>&nbsp;<\/p>\n<p>Il faut imp\u00e9rativement ajouter la ligne suivante dans votre fichier .pro, sans quoi le compilateur ne trouvera pas le fichier XInput.lib :<\/p>\n<p>win32:LIBS += $${<em>PRO_FILE_PWD<\/em>}\/SimpleXbox360Controller\/XInput.lib<\/p>\n<p>&nbsp;<\/p>\n<h1>Principe<\/h1>\n<p>&nbsp;<\/p>\n<p>La classe SimpleXbox360Controller permet de r\u00e9cup\u00e9rer l&rsquo;\u00e9tat d&rsquo;une manette de xbox 360 connect\u00e9e \u00e0 l&rsquo;ordinateur. (pour g\u00e9rer 4 manettes, utiliser 4 instances de la classe). Cette classe a \u00e9t\u00e9 \u00e9crite pour offrir un maximum de flexibilit\u00e9, il y a par cons\u00e9quente plusieurs fa\u00e7on de l&rsquo;utiliser. La r\u00e9cup\u00e9ration des infos de la manette peut se faire soit de fa\u00e7on automatique (la classe dispose de son propre<span style=\"color: #888888;\"><em> QTimer<\/em><\/span>) soit manuellement, \u00e0 chaque appel de la fonction <em>update()<\/em>. De m\u00eame, la classe \u00e9met des signaux \u00e0 chaque changement d&rsquo;\u00e9tat de la manette, mais il est \u00e9galement possible de Statlire manuellement le dernier \u00e9tat re\u00e7u.<\/p>\n<p>Mais commen\u00e7ons par le d\u00e9but :<\/p>\n<p>&nbsp;<\/p>\n<h1>Le constructeur<\/h1>\n<p>&nbsp;<\/p>\n<p>Celui ci prend jusqu&rsquo;\u00e0 5 param\u00e8tres :<\/p>\n<ol>\n<li>Le num\u00e9ro de la manette associ\u00e9e (de 0 \u00e0 3, correspond au manettes des joueurs 1 \u00e0 4).<\/li>\n<li>Le rayon du point mort du stick analogique gauche (de 0 \u00e0 32767). Il est conseill\u00e9 d&rsquo;omettre ce param\u00e8tre, la valeur par d\u00e9faut \u00e9tant alors utilis\u00e9e.<\/li>\n<li>Le rayon du point mort du stick analogique droit (de 0 \u00e0 32767). Il est conseill\u00e9 d&rsquo;omettre ce param\u00e8tre, la valeur par d\u00e9faut \u00e9tant alors utilis\u00e9e.<\/li>\n<li>Le seuil de d\u00e9tection des g\u00e2chettes (de 0 \u00e0 255). Il est conseill\u00e9 d&rsquo;omettre ce param\u00e8tre, la valeur par d\u00e9faut \u00e9tant alors utilis\u00e9e.<\/li>\n<li>Le <em>QObject<\/em> parent. Permet \u00e0 Qt d&rsquo;am\u00e9liorer la gestion m\u00e9moire. Pas vraiment n\u00e9cessaire si l&rsquo;on pense \u00e0 mettre les <em>delete<\/em>.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h1>La classe Input<\/h1>\n<p>&nbsp;<\/p>\n<p>Cette classe repr\u00e9sente l&rsquo;\u00e9tat de la manette. Elle appartient \u00e0 la classe SimpleXbox360Controller ( pour en d\u00e9clarer une nouvelle instance, il faut donc \u00e9crire <em>SimpleXbox360Controller::InputState monInputState<\/em>) Chaque stick analogique est repr\u00e9sent\u00e9 par 2 variables de type float dont la valeur varie de -1 (haut\/gauche) \u00e0 1 (bas\/droite), 0 correspondant \u00e0 la position au repos.<\/p>\n<p>Chaque g\u00e2chette est repr\u00e9sent\u00e9e par une variable <em>float<\/em> de valeur comprise entre 0 (g\u00e2chette au repos) \u00e0 1 (appuy\u00e9e au maximum)<\/p>\n<p>Ces valeurs sont obtenues apr\u00e8s calcul des seuils et des des points morts, donc vous n&rsquo;avez pas d&rsquo;effectuer ces calculs.<\/p>\n<p>Le type et l&rsquo;\u00e9tat de la batterie sont repr\u00e9sent\u00e9s par des variables de type <em>quint8<\/em> (entiers non sign\u00e9s sur 8 bits). Ces variables doivent \u00eatre interpr\u00e9t\u00e9es par comparaison avec les d\u00e9finitions <em>BATTERY_TYPE_<\/em> et <em>BATTERY_LEVEL_<\/em> du fichier <em>XInput.h<\/em><\/p>\n<p>L&rsquo;\u00e9tat des boutons est repr\u00e9sent\u00e9 par une variable de type quint16. L&rsquo;\u00e9tat de chaque bouton peut \u00eatre \u00e9valu\u00e9 par appel de la m\u00e9thode<em> InputState::isButtonPressed()<\/em> . Par exemple, pour v\u00e9rifier si le bouton A est appuy\u00e9 : <em>myInputState.isButtonPressed(XINPUT_GAMEPAD_A)<\/em> retourne <em>true<\/em> si A est appuy\u00e9, et <em>false<\/em> sinon.<\/p>\n<p>&nbsp;<\/p>\n<h1>Signaux<\/h1>\n<p>&nbsp;<\/p>\n<ul>\n<li>controllerNewState(SimpleXbox360Controller::InputState) : est \u00e9mis si l&rsquo;\u00e9tat de la manette a chang\u00e9 depuis l&rsquo;appel pr\u00e9c\u00e9dent de la m\u00e9thode <em>update()<\/em><\/li>\n<li>controllerNewBatteryState(quint8 newBatteryType, quint8 newBatteryLevel) : est \u00e9mis si l&rsquo;\u00e9tat de la batterie de la manette a chang\u00e9 depuis\u00a0l&rsquo;appel pr\u00e9c\u00e9dent de la m\u00e9thode <em>update().\u00a0<\/em>Comment pr\u00e9c\u00e9demment, les param\u00e8tres doivent \u00eatre interpr\u00e9t\u00e9es par comparaison avec les d\u00e9finitions <em>BATTERY_TYPE_<\/em> et <em>BATTERY_LEVEL_<\/em> du fichier <em>XInput.h<\/em><\/li>\n<li>void controllerConnected(unsigned int controllerNum) : est \u00e9mis si la manette a \u00e9t\u00e9 connect\u00e9e depuis\u00a0l&rsquo;appel pr\u00e9c\u00e9dent de la fonction <em>update()<\/em><\/li>\n<li>void controllerDisconnected(unsigned int controllerNum) : est \u00e9mis si la manette a \u00e9t\u00e9 d\u00e9connect\u00e9e\u00a0l&rsquo;appel pr\u00e9c\u00e9dent de la fonction <em>update()<\/em><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1>Slots<\/h1>\n<p>&nbsp;<\/p>\n<ul>\n<li>update() : permet de rafraichir les infos de la manette, et provoque alors l&rsquo;\u00e9mission des signaux ad\u00e9quats. Si l&rsquo;on ne souhaite pas utiliser les signaux, il est possible de r\u00e9cup\u00e9rer les derni\u00e8res infos re\u00e7us avec la m\u00e9thode <em>getCurrentState()<\/em><\/li>\n<li>startAutoPolling(unsigned int interval) : d\u00e9marre un <em>QTimer<\/em> qui sera charg\u00e9 d&rsquo;appeler la fonction<em> update()<\/em> toute les <em>interval<\/em> milliseconds.<\/li>\n<li>stopAutoPolling() : arr\u00eate le <em>QTimer<\/em>.<\/li>\n<li>void setVibration(float leftVibration, float rightVibration) : r\u00e8gle la valeur des vibrations pour les moteurs gauche et droits. Les valeurs doivent \u00eatre comprises entre 0 et 1. Les deux moteurs produisent des vibrations diff\u00e9rentes, donc n&rsquo;h\u00e9sitez pas \u00e0 essayer l&rsquo;un ou l&rsquo;autre, voire mixer les deux pour obtenir le ressenti recherch\u00e9.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1>R\u00e9glage manuel des points morts<\/h1>\n<p>&nbsp;<\/p>\n<p>Ces fonctions sont l\u00e0 au cas o\u00f9 vous en auriez besoin dans un cas particulier. En temps normal elle ne sont pas n\u00e9cessaires. Elles peuvent s&rsquo;av\u00e9rer utile, par exemple, pour celui qui souhaite jou\u00e9 avec une manette dont les ressorts des sticks analogiques sont particuli\u00e8rement us\u00e9s, et pour laquelle les valeurs par d\u00e9faut des points morts ne conviennent pas. Pour les g\u00e2chettes, normalement le probl\u00e8me de vieillissement des ressorts ne se pose pas, donc il est possible de r\u00e9duire la valeur (la valeur par d\u00e9faut est de 30) pour profiter d&rsquo;une plus grande course des g\u00e2chettes :<\/p>\n<ul>\n<li>setLeftStickDeadZone(unsigned int newDeadZone) : r\u00e8gle le rayon du point mort du stick analogique gauche (de 0 \u00e0 32767). Il est conseill\u00e9 d&rsquo;omettre ce param\u00e8tre, la valeur par d\u00e9faut \u00e9tant alors utilis\u00e9e.<\/li>\n<li>setRightStickDeadZone(unsigned int newDeadZone) : r\u00e8gle le rayon du point mort du stick analogique droit (de 0 \u00e0 32767). Il est conseill\u00e9 d&rsquo;omettre ce param\u00e8tre, la valeur par d\u00e9faut \u00e9tant alors utilis\u00e9e.<\/li>\n<li>setTriggerThreshold(unsigned int newThreshold) : r\u00e8gle le seuil de d\u00e9clenchement des g\u00e2chettes ( de 0 \u00e0 255).<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1>Autre m\u00e9thodes<\/h1>\n<p>&nbsp;<\/p>\n<ul>\n<li>bool isStateChanged(void) : retourne <em>true<\/em> si l&rsquo;\u00e9tat de la manette a chang\u00e9 depuis l&rsquo;appel pr\u00e9c\u00e9dent de la fonction<em> update().<\/em><\/li>\n<li>bool isConnected(void) : retourne <em>true<\/em> si la manette est connect\u00e9e.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1>Conclusion<\/h1>\n<p>&nbsp;<\/p>\n<p>Ayant utilis\u00e9 cette classe sur 2 projets depuis sont \u00e9criture, dont logiciel de d\u00e9mo Simple Xbox 360 Controller Tester, qui fonctionne parfaitement, elle me semble adapt\u00e9e, et les quelques bugs r\u00e9siduels ont \u00e9t\u00e9 d\u00e9couverts et corrig\u00e9s, donc vous devriez pouvoir l&rsquo;utiliser sans probl\u00e8me !<\/p>\n<p>N&rsquo;h\u00e9sitez pas \u00e0 me faire par de vos commentaires, id\u00e9es, am\u00e9liorations, o\u00f9 m\u00eame projets utilisant cette classe. Je pr\u00e9cise que l&rsquo;ensemble est sous license GPL.<\/p>\n<p>Enjoy \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pour utiliser les manettes de xbox 360 sous Windows, Microsoft a mis au point la librairie Xinput. Si plusieurs d\u00e9veloppeurs ont d\u00e9j\u00e0 mis a disposition des classes C++ pour faciliter l&rsquo;acc\u00e8s \u00e0 Xinput, aucune n&rsquo;a \u00e9t\u00e9 \u00e9crite pour tirer partie du m\u00e9canisme des slot \/ signal de Qt. La classe SimpleXbox360Controller a pour objectif de &hellip; <\/p>\n<p><a class=\"more-link btn\" href=\"https:\/\/pila.fr\/wordpress\/archives\/606\">Lire la suite<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[24,12,77,76,11,46],"class_list":["post-606","post","type-post","status-publish","format-standard","hentry","category-prog","tag-bibliotheque","tag-c","tag-classe","tag-manette","tag-qt","tag-xbox360","item-wrap"],"_links":{"self":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/606","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=606"}],"version-history":[{"count":21,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/606\/revisions"}],"predecessor-version":[{"id":961,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/606\/revisions\/961"}],"wp:attachment":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}