Gérer le clavier et la souris avec DirectInput
Un article de Games Creators Network.
Attention
Cet article est en attente du choix d'une licence par son auteur. Elle n'est pas soumise à la licence par défaut du GCN.
Cela signifie entre autre chose que si vous n'êtes pas l'auteur de cet article, vous n'avez probablement pas le droit de le modifier.
Maintenant que vous maîtrisez l'affichage des graphismes de votre jeu, il est temps de pouvoir interagir avec. Dans ce tutoriel nous allons donc apprendre à utiliser le clavier et la souris, qui sont vraiment des choses aisées. Comme l'utilisation des deux périphériques est très proche au niveau de DirectX, la plupart du temps il n'y aura qu'une seule explication du fonctionnement des fonctions propres aux interfaces de DirectInput.
Sommaire |
[modifier] Initialisation de DirectInput
L'initialisation de l'objet DirectInput ne nécessite qu'une ligne de commande:
LPDIRECTINPUT lpdi; DirectInputCreate(hInstance,DIRECTINPUT_VERSION,& lpdi,NULL);
LPDIRECTINPUT : C'est l'objet qui contrôle DirectInput. Il sert à créer les différents périphériques.
DirectInputCreate : C'est la fonction d'initialisation de DirectInput. Le premier paramètre est l'instance de l'application. le deuxième est le version de DirectInput à utiliser (ici la version courante). Le troisième est l'adresse de l'objet DirectInput à initialiser. Le quatrième vaut toujours NULL.
[modifier] Création des périphériques
La création d'un périphérique est un peu plus longue. Il y a très peu de différences entre la souris et le clavier donc chaque fonction ne sera détaillée qu'une fois, et les différences entre le clavier et la souris seront immédiatement énumérées. Voyons les étapes à suivre :
[modifier] Création du périphérique
LPDIRECTINPUTDEVICE lpdiPeriph; lpdi-> CreateDevice(GUID_SysPeriph,& lpdiPeriph,NULL);
LPDIRECTINPUTDEVICE : C'est l'interface de DirectInput pour les périphériques.
CreateDevice : Fonction membre de l'interface IDirectInput. Elle sert à créer un périphérique. Le premier paramètre est le GUID du périphérique. Pour le clavier il faut mettre GUID_SysKeyboardet pour le souris GUID_SysMouse. Le second paramètre est l'adresse du périphérique à créer. Et le troisième paramètre est toujours NULL.
[modifier] Sélection du format de stockage des données
lpdiPeriph-> SetDataFormat(& Format);
SetDataFormat : Fonction membre de l'objet LPDIRECTINPUTDEVICE. Son unique paramètre est le format de données. Il faut remplacer 'Format' par c_dfDIKeyboard pour le clavier et parc_dfDIMouse pour la souris.
[modifier] Initialisation du tampon de données
DIPROPDWORD dipw=
{
// En-tête
{
sizeof(DIPROPDWORD),
sizeof(DIPROPHEADER),
0,
DIPH_DEVICE,
},
// Données
BUFFERSIZE
};
lpdiPeriph-> SetProperty(DIPROP_BUFFERSIZE,& dipw.diph);
DIPROPDWORD : Structure utilisée par DirectInput pour initialiser les propriétés du tampon de données. La seule chose qui est à modifier pour passer de la souris au clavier est la valeur de 'BUFFERSIZE'. Pour le clavier il vaut mieux mettre 32et pour la souris 16. Mais cela est une affaire de préférence. BUFFERSIZE est le nombre d'entrées maximales dans le tampon. Donc plus il est élevé et plus vous pouvez stocker de données avant de les lire.
SetProperty : Fonction membre de l'objet LPDIRECTINPUTDEVICE. Son premier paramètres est à mettre à DIPROP_BUFFERSIZE pour une entrée avec tampon (celle expliquée dans cet article car c'est le seule d'utile). Le second paramètre est l'adresse du membre diph de la structure DIPROPDWORD. Ne me demandez pas pourquoi. C'est comme cela et ça marche parfaitement.
[modifier] Définition du niveau coopératif
lpdiPeriph-> SetCooperativeLevel(MainWindowHandle,COOP_LEVEL);
SetCooperativeLevel : Fonction membre de l'objet LPDIRECTINPUTDEVICE. Elle sert à définir la manière dont le périphérique agit par rapport aux autres applications. Le premier paramètre est le handle de l'application. Le second est une liste d'indicateur. Il faut remplacer 'COOP_LEVEL' par DISCL_NONEXCLUSIVE | DISCL_BACKGROUND pour le clavier (le clavier peut servir dans d'autres programmes) ou par DISCL_EXCLUSIVE | DISCL_FOREGROUNDpour la souris (la souris appartient au programme, elle est 'volée' à Windows).
[modifier] Acquisition du périphérique (la touche finale)
lpdiPeriph-> Acquire();
Acquire : Fonction membre de l'objet LPDIRECTINPUTDEVICE. On ne peut utiliser le périphérique que ci cette commande à réussi.
[modifier] Lecture des périphériques
Maintenant que nous avons crée nos périphériques, il faut être capable de les lires. La chose est très aisée et la différence entre le clavier et la souris est minime ici aussi. Voici comment il faut procéder :
DIDEVICEOBJECTDATA buffer[BUFFERSIZE];
DWORD dwItems=BUFFERSIZE;
// On lit
lpdiPeriph-> GetDeviceData(sizeof(DIDEVICEOBJECTDATA),buffer,& dwItems,0);
// Et on traite
for(DWORD d=0;d< dwItems;d++)
{
switch(buffer[d].dwOfs)
{
// Traitement différent selon que l'on utilise le clavier ou la souris
}
}
DIDEVICEOBJECTDATA : Structure pour le tampon de données. C'est dans un tableau de ce type que l'on récupère les informations sur le périphérique.
GetDeviceData : Fonction membre de l'objet périphérique. Elle sert à lire les données et à les stocker dans le buffer. Le premier paramètre est la taille d'une donnée (un sizeof du type de donnée suffit). Le deuxième paramètre est buffer recevant les données. Le troisième paramètre est l'adresse d'un DWORD contenant le nombre d'éléments à lire et dans lequel sera stocké le nombre d'éléments lus. Enfin, on fixe généralement le dernier paramètre à 0 pour que les données soient effectivement vidées du périphérique.
Pour savoir quelles données ont été lues, il suffit de consulter 2 membres de DIDEVICEOBJECTDATA : dwOfspour savoir quelle touche ou bouton a changé d'état et dwDatapour savoir si on vient de relâcher ou d'enfoncer l'élément.
dwData vaut 0x80 si on vient d'enfoncer l'élément lu et autre chose sinon.
dwOfs vaut l'une des constantes DIK_* pour le clavier et DIMOFS_* pour la souris. La liste complète de ces constantes se trouve dans l'aide de DirectX. A vous d'agir en conséquence pour chaque événement.
Petite précision pour la souris. DIMOFS_X contient la valeur du déplacement horizontal en pixels de la souris et non ses cordonnées. Il est positif si la souris vas vers la droite et négatif vers la gauche. Il en vas de même pour DIMOFS_Y pour le déplacement vertical (Haut=négatif et Bas=Positif).
Pour ce qui est de la gestion, mon approche personnelle est de créer une classe pour le périphérique et de stocker les données qui m'intéressent. de cette façon je peux savoir à tout moment quel est l'état actuel de mon clavier ou de ma souris et je peux interagir dessus directement dans le code.
[modifier] Conclusion
Je pense qu'avec ceci la gestion de la souris et du clavier ne devrait plus vous poser de problèmes. Je joint à ce tutoriel non pas un programme exemple, mais plutôt deux exemple de classe pour le clavier et la souris, ainsi qu'un exemple de fonction d'initialisation de DirectInput. J'espère avoir été assez clair et je me tient à votre disposition pour tout renseignement complémentaire.
Ce document a été publié sur la version 3 du G.C.N. par Kain.
- Auteur Original : Kain
- Date de publication : 9 janvier 2002

