DirectInput

Après avoir définit un tableau composé des principales commandes des modules,
on commence par créer un objet DirectInput grâce à la fonction DirectInputCreate.
Le premier paramètre est un handle d'instance pour l'application qui est en train de créer l'objet DirectInput.
Le second paramètre est le numéro de version recherché pour DirectInput.
Le troisième est un pointeur sur un pointeur d'objet DirectInput qui sert pour l'énumération et la création d'unités d'entrées.

Pour créer l'unité clavier on se sert de la méthode CreateDevice avec pour premier paramètre un identificateur global de l'unité créée et pour second paramètre un pointeur sur pointeur DirectInputDevice.

Ensuite, on définit le format de données qui est une variable globale prédéfinie (c_dfDIKeyboard). Puis on définit un niveau coopératif sans exclusivité. Et on termine par une acquisition du clavier.

On commence par ajouter le fichier dinput.lib et dxguid.lib dans la liste du projet (voir tutorial 1)

Dans init_Input.h on aura le pointeur LPDIRECTINPUT et le pointeur sur l'unité clavier LPDIRECTINPUTDEVICE.

#include <dinput.h>

static LPDIRECTINPUT obj_DI;

static LPDIRECTINPUTDEVICE obj_clavier;

Dans le fichier decl_init_Input.h on aura

HRESULT init_input(HINSTANCE, HWND, LPDIRECTINPUT*, LPDIRECTINPUTDEVICE*);

Dans init_Input.h :

#include "init_Input.h"

HRESULT init_input(HINSTANCE hinst, LPDIRECTINPUT *lpDI, LPDIRECTINPUTDEVICE *unite) {

ch[' '] = DIK_SPACE;
ch['A'] = DIK_A;
ch['B'] = DIK_B;
ch['C'] = DIK_C;
ch['D'] = DIK_D;
ch['E'] = DIK_E;
ch['F'] = DIK_F;
ch['G'] = DIK_G;
ch['H'] = DIK_H;
ch['I'] = DIK_I;
ch['J'] = DIK_J;
ch['K'] = DIK_K;
ch['L'] = DIK_L;
ch['M'] = DIK_M;
ch['N'] = DIK_N;
ch['O'] = DIK_O;
ch['P'] = DIK_P;
ch['Q'] = DIK_Q;
ch['R'] = DIK_R;
ch['S'] = DIK_S;
ch['T'] = DIK_T;
ch['U'] = DIK_U;
ch['V'] = DIK_V;
ch['W'] = DIK_W;
ch['X'] = DIK_X;
ch['Y'] = DIK_Y;
ch['Z'] = DIK_Z;
ch[37] = DIK_LEFT;
ch[38] = DIK_UP;
ch[39] = DIK_RIGHT;
ch[40] = DIK_DOWN;

if(DirectInputCreate(hinst, DIRECTINPUT_VERSION, lpDI, NULL) != DI_OK)
return E_FAIL;

if((*lpDI)->CreateDevice(GUID_SysKeyboard, unite, NULL) != DI_OK)
return E_FAIL;


(*unite)->SetDataFormat(&c_dfDIKeyboard);

if((*unite)->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE) != DI_OK)
return E_FAIL;

return DI_OK; 

}

On appelle la création dans la fonction main :

ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

if(init_input(hInst, hWnd, &obj_DI, &obj_clavier) == E_FAIL)
return -1;

obj_clavier->Acquire();

et dans la boucle du jeu on a alors

while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else {
Rendu(hCtrl_2, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, &obj_Direct3DDevice, obj_texture, obj_DirectVB, module1, module2, mtm[0], mtm[4], mtm[6], mtm[2], mtm[8], &et_module);
Rendu(hCtrl_1, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, &obj_Direct3DDevice2, obj_texture2, obj_DirectVB2, module2, module1, mtm[3], mtm[5], mtm[7], mtm[1], mtm[9], &et_module2);
mouvement(&obj_clavier);

}
}

La fonction mouvement nous remplace l'ancienne fonction MsgProc. Ici la détection de l'appui d'une touche est beaucoup plus rapide. Les valeurs ds touches sont définies dans le fichier entête DInput.h. On les test par l'intermédiaire d'un masque 0x80 avec un ET LOGIQUE.

void mouvement(LPDIRECTINPUTDEVICE *clav) {

BYTE buffer[256];
ZeroMemory( buffer, sizeof(buffer) );

(*clav)->GetDeviceState(sizeof(buffer), buffer);

if(buffer[ch[direc.j1.haut]] & 0x80) {

if(DSbuffer[3]&& et_module.haut!=1) {
DSbuffer[3]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[3]->Play(0,0,0); // Joue le son
}
if(DSbuffer[4]&& et_module.haut!=1) 
DSbuffer[4]->Stop();

et_module.haut=1;et_module.bas=0;
}

else {

if(DSbuffer[4]&& et_module.haut!=2) {
DSbuffer[4]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[4]->Play(0,0,0); // Joue le son
}
if(DSbuffer[3]&& et_module.haut!=2)
DSbuffer[3]->Stop();

et_module.haut=2;et_module.bas=0;
}

if(buffer[ch[direc.j1.feu]] & 0x80) {
if(DSbuffer[0] && et_module.feu!=1 && et_module.feu!=2) {
DSbuffer[0]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[0]->Play(0,0,0); // Joue le son
et_module.feu=1;

}
}

if(buffer[ch[direc.j2.feu]] & 0x80) {
if(DSbuffer[0] && et_module2.feu!=1 && et_module2.feu!=2) {
DSbuffer[0]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[0]->Play(0,0,0); // Joue le son
et_module2.feu=1;

}

}

if(buffer[ch[direc.j2.haut]] & 0x80) {
if(DSbuffer[3]&& et_module2.haut!=1) {
DSbuffer[3]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[3]->Play(0,0,0); // Joue le son

}

if(DSbuffer[4]&& et_module2.haut!=1)
DSbuffer[4]->Stop();
et_module2.haut=1;et_module2.bas=0;
}
else {
if(DSbuffer[4]&& et_module2.haut!=2) {
DSbuffer[4]->SetCurrentPosition(0); // Met le fichier wav au début
DSbuffer[4]->Play(0,0,0); // Joue le son
}
if(DSbuffer[3]&& et_module2.haut!=2)
DSbuffer[3]->Stop();
et_module2.haut=2;et_module2.bas=0;
}


if(buffer[ch[direc.j1.gauche]] & 0x80)
{et_module.gauche=1;et_module.droite=0;return;}
else
if(buffer[ch[direc.j1.droite]] & 0x80) 
{et_module.droite=1;et_module.gauche=0;return;}
else 
{
if(et_module.droite == 1)
{et_module.gauche=0;et_module.droite=2;return;}
if(et_module.gauche == 1)
{et_module.gauche=2;et_module.droite=0;return;}
}


if(buffer[ch[direc.j2.gauche]] & 0x80)
{et_module2.gauche=1;et_module2.droite=0;return;}
else
if(buffer[ch[direc.j2.droite]] & 0x80) 
{et_module2.droite=1;et_module2.gauche=0;return;}
else 
{
if(et_module2.droite == 1)
{et_module2.gauche=0;et_module2.droite=2;return;}
if(et_module2.gauche == 1)
{et_module2.gauche=2;et_module2.droite=0;return;}
}
}

La fonction MsgProc devient simplement :

LRESULT CALLBACK MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{

switch( msg )
{

case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0;

case WM_KEYUP :

switch(wParam) {

case VK_ESCAPE:
DestroyWindow(hWnd);
break;

}
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}

Pour éviter un trop grand nombre de missiles dans le jeux, on fixe une période pour autoriser le lancement d'un nouveau missile. C'est la variable k_spac_miss. dans le fichier principal .h on a alors :

typedef struct {
D3DMATRIX view_matr;
D3DVECTOR position_cam; 
D3DMATRIX monde;
float rot_cam, coef_rotation_module, coef_vitesse_module, coef_cam, module_rot;
D3DVECTOR coord_0;
Missile missile;
float rayon, tcr;
unsigned char collision, stopecl;
float vies;
unsigned int k_spac_miss;

//collision avec l extrémité du labyrinthe
coord_2D rl;
unsigned int nbr_texture;

} _module_;

On a alors dans la fonction Rendu :

if ((etm->feu==1) && (fin < 50))
{missile_init(rp, etm);
etm->feu=2;}

Missile cell = rp->missile;

affich_missile(D3DD, mtm_missile, rp, cell);

rp->k_spac_miss++;

if(rp->k_spac_miss > 10)
{rp->k_spac_miss = 0; etm->feu = 0;}

Téléchargez la source, cliquez ci-dessous :