Accueil ⇒ Informatique ⇒ Bibliothèques ⇒ DirectX ⇒ Leçon 4 : Commandes

Leçon 4 : Commandes

Présentation

La gestion des commandes est un point essentiel dans vos programmes. En effet, sans interaction, l'utilisateur se lassera vite du programme (à moins que votre rève ne soit un magnifique simulateur d'aquarium) : c'est pourquoi maîtriser le clavier et la souris sera vite primordial ! Nous allons vous y aider dans ce cours.

Utiliser les VKC

Plutôt que de devoir apprendre directement Direct Input, ce qui n'est pas chose aisée, jetez plutôt un oeil au Virtual Key Codes. Je les ai utilisés dans mes programmes déjà lors de l'appel à la touche écha. Vous pourrez consulter la liste complète des touches sur le site officiel de Micro$oft. Incluez-les dans votre boucle d'écoute des messages de la manière suivante :

case WM_KEYDOWN:
    switch(wParam) {
        case VK_UP:
            posy -= 2;
            break;
    }

Et ainsi de suite pour toutes les autres touches. Comme ceci, vous pourrez utiliser les commandes clavier sans avoir à passer par un énorme fichier d'en-tête. Attention cependant, de cette manière vous ne pouvez enclencher qu'une seule touche à la fois. Je suis actuellement en train de travailler sur un code qui permette d'utiliser les VKC avec des résultats utiles, même s'ils ne valent pas Direct Input. A vrai dire, je vais aussi vous présenter Direct Input, mais son utilisation est sensiblement différente des VKC. En effet, avec une VK Touche, l'utilisateur appuie une fois sur une touche, ce qui engendre une conséquence une seule fois. Sous Direct Input, l'utilisateur enfonce une touche, ce qui répète une conséquence jusqu'à ce qu'il relâche la touche. Ceci est peu pratique pour un menu sensible. Mais il est possible d'utiliser à la fois les VKC et DINPUT.

Commandes DirectInput

Voyons donc cette partie du SDK :

LPDIRECTINPUT8 DIobjet;
LPDIRECTINPUTDEVICE8 Clavier;
LPDIRECTINPUTDEVICE8 Souris;
DIMOUSESTATE EtatSouris;
 
void DIInit(HWND hWnd)
{
    DIobjet->CreateDevice(GUID_SysKeyboard, &Clavier, NULL);
    Clavier->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
    Clavier->SetDataFormat(&c_dfDIKeyboard);
    Clavier->Acquire();
 
    DIobjet->CreateDevice(GUID_SysMouse, &Souris, NULL);
    Souris->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
    Souris->SetDataFormat(&c_dfDIMouse);
    Souris->Acquire();
}

Ici, nous avons initialisé Direct Input. Tout d'abord, on créé l'objet Direct Input, qui sera l'interface par laquelle nous passerons pour accéder aux périphériques. Ensuite, on déclare deux devices pour le clavier et la souris. Les devices seront l'interface qui nous servira à accéder aux périphériques et à récupérer les données. Après cela, on définit un objet qui nous servira à vérifier l'état de la souris. Ceci fait, tous les ingrédients sont réunis pour commencer. On créé une fonction DIInit, qui recevra le Handle du prog, et qui nous servira à initialiser les devices du clavier et de la souris en mode coopératif. Maintenant que Direct Input est prêt, nous allons créer une fonction Input() qui sera appelée à chaque boucle de message :

void Input()
{ 
    HRESULT hr; 
 
    hr = Clavier->GetDeviceState(sizeof(buffer),(LPVOID)&buffer);
 
    if FAILED(hr) {
        hr = Clavier->Acquire();
        while (hr == DIERR_INPUTLOST)
            hr = Clavier->Acquire();
    }
 
    if (KEYDOWN(buffer, DIK_RIGHT)) {
        if (phase == 2)
            posx += 2;
    }
 
    hr = Souris->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&EtatSouris);
    if (FAILED(hr)) {
        hr = Souris->Acquire();
        while (hr == DIERR_INPUTLOST)
            hr = Souris->Acquire();
    }
 
    if (EtatSouris.rgbButtons[0]&0x80) {
        // Actions si on clique
    }
 
    posx += EtatSouris.lX;
    posy += EtatSouris.lY;
}

Bon, ceci est plus compliqué : on initialise une variable de type HRESULT (c'est à dire qui renvoie FAILED ou OK en général) qui nous servira par la suite. On appelle, pour le clavier, GetDeviceState() afin d'obtenir l'état des touches, et si cette fonction renvoie FAILED on réinitialise le clavier. Vous ne comprenez pas pourquoi ? Essayez votre programme sans et vous verrez : après un appel le clavier ne fonctionne plus. Ensuite on teste la valeure des touches : ici, c'est identique au VK_TOUCHES mais VK est remplacé par DIK. Consultez "dinput.h" pour avoir la liste complète. Ici, si la variable phase est égale à 2, on incrémente la position de J1 de Sensitive (ceci est un extrait simplifié du code source que j'ai écrit pour Axion). Passé ça, on effectue les mêmes opérations pour la souris, mais ici le test est différent. Etat.Souris.lY représente la position en Y dans la structure de souris, mais cette variable est relative. Pour cela, on ne peut pas placer la souris directement aux positions EtatSouris.lY et EtatSouris.lX : on doit passer par une variable ptrY et ptrX avant d'agir sur J1.posx et J1.posy, les positions en x et en y du joueur. Ceci est utile pour les pointeurs de souris en DDRAW. Mais ici, on ne change les positions que si le bouton gauche de la souris est enfoncé car (EtatSouris.rgbButtons[0]&0x80) sert à tester le bouton gauche. A partir de là, il vous suffit d'appeler la fonction Input() à la place de votre boucle d'écoute des messages :

while (TRUE)
{
    if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
        if (!GetMessage(&msg, NULL, 0, 0))
            break;
        DispatchMessage(&msg);
    } else {
        Update();
        Input();
    }
}

Conclusion

Voilà tout. Maintenant, vous savez l'essentiel à savoir pour utiliser le clavier et la souris dans vos programmes. Si vous le voulez, je pourrais écrire un tutorial pour contrôler les périphériques de jeu (joystick) : demandez-le moi si besoin est. Le prochain chapître concernera la musique et les sons dans vos programmes ou d'autres notions importantes dans vos jeux.

Vous pouvez consulter le source d'exemple associé à cet article.