Lekcija 6: DirectInput i mrvica STL-a
Bilo koji računalni program ne služi nikakvoj svrsi ako nema neki način komunikacije sa vanjskim svijetom. DirectInput je prozor u svijet za sve DirectX aplikacije, on omogučava interakciju sa tipkovnicom, mišem, joystickom i drugim ulazno-izlaznim uređajima. Pošto je DirectInput tema sama za sebe, ja ću objasniti samo osnovne stvari potrebne za jednostavniju interakciju između DirectX aplikacije, tipkovnice i miša.
Osim toga, objasniti ću kako koristiti klasu vector koja je dio STL-a (Standard Template Library) koja će služiti kao dinamički spremnik objekata u sceni.
Ja osobno volim razdijeliti programe na funkcionalne dijelove, te što je više dijelova grupirati u klase. Tako sam napravio i sa DirectInput dijelom programa kojeg čini jedna statička klasa koja sadrži sve varijable koje su potrebne unutar programa. Način na koji povezujete pojedine dijelove programa je vaš osobni odabir, i to može biti preko bazne klase, globalnih varijabli, povezivanje klasa nekom trećom klasom ili neki drugi način koji je mješavina prva tri. U ovom programu svaka klasa koja zahtjeva interakciju sadrži CScene pointer preko kojeg pristupa drugim podacima.
Što se samog programa tiće, zamjenjeno je par stvari u sceni. Prva promjena je ubacivanje još jednog parametra u Inicijaliziraj metodu, koja predstavlja instancu trenutnog prozora, i potrebna je za inicijalizaciju DirectInputa.
|
bool CScene::Inicijaliziraj(HWND hWnd,HINSTANCE hInstance) |
Unutar metode poziva se InitialiseInput metoda koja je dio staticke klase CDInput koja predstavlja sučelje prema DirectInput dijelu aplikacije.
|
CDInput::InitialiseInput(hWnd,hInstance) |
Iduča linija povezuje scenu i CDInput klasu:
|
CDInput::scene=this; |
Osim inicijalizacije DirectInputa scena je prilagođena za dinamičko kreiranje objekata. Objekti koji se stvaraju jednostavno se stavljaju na vrh vektora plohe unutar CScene klase. Pojedini objekt kreira se pomoću new operatora, te se nakon stavljanja u vector ta ista varijabla može koristiti za kreiranje novog objekta. Klasa vector ima mnoštvo metoda, i one su dostupne u literaturi (helpu) koja dolazi sa MS Visual Studiom. Nama najbitnije su puchback i size metode. Pushback metoda stavlja element na vrh stoga, a size metoda vraća trenutnu veličinu vektora. Vector se deklarira tako za određeni tip podataka, i ako taj podatak nije isti najbolje ga je "boxati" u void pokazivać, te ga kasnije "unboxati", tj korisiti cast operator koji će taj pointer pretvoriti u nama odgovarajući tip.
Deklaracija vektora:
|
vector<CPloha *> plohe//vektor koji ce sadrzavati plohe |
Kreiranje plohe i stavljanje na vrh vektora:
|
CPloha *Ploha=newCPloha(D3DDevice,10,10,D3DCOLOR_XRGB(255,255,255)) plohe.push_back(Ploha) |
Gornja ploha je kreirana pri inicijalizaciji objekata i predstavlja kursor.
Šetanje kroz vektor:
|
for(int br=0;br<plohe.size();br++) { plohe[br]->Render(); } |
Uz ovakav način manipulacije objektima mnogo je jednostavnije kreirati dinamičku scenu gdje broj objekata nije stalan kroz cijelo izvođenje programa.
Osnovnu funkcionalnost od strane DirectInputa pruža klasa IDirectInput8 pomoću koje se zatim mogu kreirati uređaji (devices) koji predstavljaju miša, tipkovnicu, ili neki drugi uređaj. IDirectInput8 interface se dobiva create funkcijom:
|
DirectInput8Create(hInst, DIRECTINPUT_VERSION,IID_IDirectInput8, (void**)&m_pDirectInput, NULL) |
Ova funkcionalnost može se postići na više načina, pogledajte Action Mapping u DirectInput referenci. U CDInput klasi kreiraju se dva uređaja, jedan za tipkovnicu, a drugi za miša. Uređaji se kreiraju pomoću CreateDevice metode IDirectInput8 interfacea. Za svaki uređaj potrebno je podesiti format njegovih podataka, način na koji se DirectInput odnosi prema drugim programima koji se trenutno vrte (cooperative level), te je potrebno preuzeti uređaj Aquire metodom.
|
m_pDirectInput->CreateDevice(GUID_SysKeyboard, &m_pKeyboard, NULL);
m_pKeyboard->SetDataFormat(&c_dfDIKeyboard);
m_pKeyboard->SetCooperativeLevel(hWnd, DISCL_BACKGROUND|DISCL_NONEXCLUSIVE );
if(m_pKeyboard) { m_pKeyboard->Acquire(); } |
Kod nas je cooperative level podešen na pozadinski, uz neekskluzivni mod. Ako je mod pozadinski, program će primati podatke sa tipkovnice ili miša iako on nije trenutno aktivni prozor, a neekskluzivni mod dozvoljava i drugim programima da koriste uređaj.
Ista stvar se radi i za miša:
|
m_pDirectInput->CreateDevice(GUID_SysMouse, &m_pMouse, NULL);
m_pMouse->SetDataFormat(&c_dfDIMouse);
m_pMouse->SetCooperativeLevel(hWnd, DISCL_BACKGROUND|DISCL_NONEXCLUSIVE);
if(m_pMouse) { m_pMouse->Acquire(); } |
Sve ovo potrebno je obaviti pri inicijalizaciji DirectInputa, te su svi ovi pozivi smješteni u InitialiseInput metodu.
Druge dvije bitne metode su ProcessKeyboard i ProcessMouse koje se moraju pozivati u GameLoop-u, tj. glavnoj petlji. Ove funkcije ispituju stanje uređaja i osvježavaju sadržaje varijabli preko kojih program prima podatke iz vanjskog svijeta.
Provjera miša obavlja se pozivom GetDeviceState metode sa idučim parametrima :
|
DIMOUSESTATE MouseState; m_pMouse->GetDeviceState(sizeof(MouseState),(LPVOID)&MouseState); |
DIMOUSESTATE je struktura u koju će biti zapisano stanje miša, koje ćemo dalje u programu ispitivati.
typedef struct DIMOUSESTATE {
LONG lX;
LONG lY;
LONG lZ;
BYTE rgbButtons[4];
} DIMOUSESTATE, *LPDIMOUSESTATE;
lZ obično predstavlja kotačić na mišu. Izveo sam osvježavanje stanja, te poprilično detaljno sučelje koje uključuje provjeru pritisaka tipki miša.
Provjeravanje tipkovnice se vrši sa istom metodom, ali sa drugim parametrima:
|
char KeyboardState[256];
if(FAILED(m_pKeyboard->GetDeviceState(sizeof(KeyboardState), (LPVOID)&KeyboardState))) { return; } |
Pozivanje Process metoda vrši se iz CScene klase unutar glavne petlje, prije renderiranja objekata.
U Render funkciji kreirao sam dodatne plohe ako je pritisnuta tipka na mišu.
|
if(CDInput::MouseLeft) { CPloha *Ploha=new CPloha(D3DDevice,10.,10.,D3DCOLOR_XRGB(rand()*255/RAND_MAX, rand()*255/RAND_MAX, rand()*255/RAND_MAX)); plohe.push_back(Ploha); Ploha->MoveTo(CDInput::MouseX,CDInput::MouseY,1.0); } |
Još jedna bitna stvar u kojoj se ova lekcija razlikuje od prijašnje je mogučnost promjene položaja, rotacije i skale unutar samog CPloha objekta, ovo čini manipulaciju objektima mnogo jednostavnijom i općenitijom.
Izgled šeste aplikacije:

Made by: Mll