Crearea propriului controler de mișcare
Mutarea obiectelor și a zborului este, desigur, bună, dar dacă aveți nevoie de altceva? Să vedem cum să creăm un controler de mișcare pentru un obiect mai interesant - rezervorul spațial Mark VII cu un radar Doppler în banda X. Rezervorul se poate mișca în jurul planetei la viteze diferite și poate porni mișcarea. Turnul său se învârte rapid și pistolul se ridică. Se pare că am uitat să menționez radarul, care se rotește fericit pe turn? În Fig. 6.11 Rezervorul Mark VII este descris în timpul misiunii de luptă.
Fig. 6.11. Spațiu maritim VII cu radar Doppler X-band
Hmm. ai observat că rezervorul nu are roți? Pot oferi două explicații:
Acesta este un rezervor zburător.
Eram prea leneș să mă încurc cu roțile.
În Fig. Figura 6.12 prezintă o diagramă a părților mobile ale rezervorului (împreună cu roțile). Ilustrația este afișată în fila color.
Fig. 6.12. Componentele rezervorului
Anexa Tank C3dTank clasa este derivată din C3dFrame. Secvența în care rezervorul este construit după cum urmează: în primul rând, vom atașa carcasa la rama exterioară și apoi atașați la corpul turnului și în ultimă instanță și atașați arma la turnul radar. Radarul este condus într-o rotație constantă. Arma se poate ridica și cade, rotindu-se în jurul axei sale orizontale. Turnul se poate roti în jurul axei verticale a corpului.
Înainte de a se ocupa de controler, să examinăm fragmentul de cod în care este creat rezervorul, astfel încât să fie mai ușor pentru noi să îl gestionăm:
Singurul lucru care ar părea ciudat aici este că am folosit un cadru separat pentru radar. A trebuit să fac acest lucru din cauza faptului că, în versiunea originală a rezervorului, axa y a radarului a fost schimbată în raport cu locul unde am vrut să poziționez radarul. Prin urmare, am stabilit originea cadrului în punctul turnului în care este amplasată axa și am mutat obiectul radar în interiorul cadrului astfel încât acesta să fie deasupra axei de rotație (Figura 6.13).
Fig. 6.13. Plasarea radarului în interiorul cadrului
Toate obiectele care alcătuiesc rezervorul nostru au fost create în Studio 3D și convertite în format .XX folosind utilitarul conv3ds. care este inclus în SDK-ul DirectX 2. Acestea au fost incluse în fișierul de aplicație RC2 ca resurse:
XOF tag. care apare în fișierul de resurse, îl puteți înlocui, de fapt, cu orice alt șir. Am ales XOF numai pentru că o astfel de extensie este utilizată în fișierele cu descrierea figurii. Singurul loc unde apare șirul XOF este funcția C3dShape :: Load. unde această linie este folosită pentru a distinge fișierele XOF de alte tipuri de resurse.
Clasa cisternă include trei funcții, care se află în fișierul 3dTank.cpp și sunt concepute pentru a regla colțurile turelei și a pistolului, precum și pentru fotografiere:
După cum puteți vedea, pentru a determina poziția turelei și a tunului, vom calcula vectorul de direcție. Apoi am stabilit direcția obiectului în raport cu părintele său; Apropo, așa funcționează implicit funcția SetDirection. Dar am vrut să-mi fac codul atât de simplu și evident, astfel încât pentru fiecare apel să trec un argument suplimentar - cadrul de referință.
Rezervorul este gata. Rămâne de învățat cum să o gestionăm.
Controlerul rezervorului
Majoritatea codului de controler se află în clasele C3dWnd și C3dController. Pentru a crea un controler propriu, trebuie doar să introduceți o clasă nouă, derivată din C3dController. Înlocuiți funcția OnUpdate din acesta și instalați un nou controler în aplicația dvs. Cu toate acestea, înainte de a scrie funcția OnUpdate. Ar trebui să distribuiți parametrii joystick-ului în funcție de funcțiile care trebuie efectuate. Configurația pe care am oprit este prezentată în Tabelul 6.3.
Tabelul 6.3. Controlul rezervorului
Am decis să folosesc parametrii x și r pentru rotiri, astfel încât, chiar și cu cel mai simplu joystick cu două axe, să puteți controla rezervorul. Am ales pentru această aplicație joystick-ul SideWinder Pro - dă o senzație mai realistă decât SpaceBall. În plus, butonul de selecție a vederilor, situat pe mânerul joystick-ului, este foarte bun pentru a roti turnul.
După ce ați decis cu conducerea, puteți scrie un program. Codul tuturor controlerului este compus din două funcții:
Constructorul inițializează numai date locale; toată lucrarea reală se face în funcția OnUpdate. Parametrul y specifică viteza curentă. Poziția curentă și direcția rezervorului sunt stocate în obiectele C3dVector. Parametrii x și r determină matricea de rotație, care specifică noua orientare a vectorului de direcție. Vectorul de direcție este înmulțit cu viteza - vectorul de deplasare obținut este adăugat la vectorul poziției anterioare a rezervorului. Apoi mutăm rezervorul într-o nouă poziție și stabilim o nouă direcție pentru rezervor.
Butonul de selectare a vederii determină direcția turnului. Verificăm starea butoanelor 3 și 4, iar dacă sunt apăsate, unghiul de creștere a armei se modifică cu o mică valoare. Dacă țineți unul dintre aceste butoane apăsate, butoiul pistolului se va ridica încet sau va cădea.
Rămâne doar să țineți cont de butonul de fotografiere. Verificarea variabilei locale m_bWasFire previne fotografiile repetate la apăsarea butonului - nu sunt permise arme automate în SUA.
Asamblarea finală a aplicației
Codul pentru aplicația Moving a fost folosit ca bază pentru aplicația Tank. Am șters comenzile de meniu inutile și am înlocuit forma curentă cu obiectul C3dTank. În plus, am inclus o imagine de fundal în aspect. Mai jos este fragmentul de cod în care este configurată fereastra principală a aplicației:
Funcția NewScene creează un aspect și specifică condițiile inițiale:
Dacă rezervorul se lasă în spatele marginii ferestrei și se pierde, puteți rula comanda Fișier&mnsp;| | Nou. Pentru a apela funcția NewScene și a începe din nou. Rămâne să spun despre ultima schimbare pe care am făcut - când controlorul cere un indicator la cadrul cu care ar trebui să funcționeze, funcția OnGetCtrlFrame returnează un indicator la rezervor:
Notă - deși funcția ar trebui să returneze un indicator la C3dFrame. trece de fapt un pointer la obiectul C3dTank. Utilizăm această circumstanță în funcția OnUpdate. al cărui cod a fost dat mai sus. Dacă anterior v-ar fi crezut că conversia unui pointer la C3dFrame de pe C3dTank indicatorul pare îndoielnică, dar acum este ușor să ne asigurăm că am avut tot dreptul să facă acest lucru.