I.A.J.S. sau “încă un Alt Joc de Supraviețuire” va reprezenta subiectul temei pe care o veți avea de implementat :). Cerințele de bază ale temei vor conține doar parțial elementele comune unui astfel de joc: controlul unui personaj de catre jucător, comportament inamici și interacțiune de atac doar de la personaj la inamici. Alte elemente comune, precum comportament bazat pe puncte de viață ale personajului și ale inamicilor, animații pentru interacțiunea de atac sau animații pentru dispariția unui inamic învins rămân la latitudinea voastră și realizarea lor se punctează suplimentar :) . De asemenea, jocul va da posibilitatea controlului simultan a două personaje, de la tastatură. Puteți viziona mai jos un filmuleț demonstrativ cu o aplicație construită pe baza framework-ului de laborator, care acoperă cerințele.
Lumea de joc este compusă dintr-o podea pe care se deplasează personajul controlat de jucător și inamicii. Toată geometria din care este realizat personajul sau inamicii, geometrie ce poate fi identică, este desenată cu aceeași culoare de bază. Fiecare inamic are o culoare aleasă aleatoriu.
La distanțe regulate unul de altul, se desenează stâlpi de iluminat. În vârful fiecărui stâlp se află două surse de lumină de tip spot, la mică distanță una de cealaltă.
La poziția personajului se află o sursă de lumină punctiformă și o sursă de lumină de tip spot ce luminează pe direcția de deplasare a personajului. Cele două surse de lumină se deplasează odată cu poziția personajului.
Jucătorul poate controla de la tastatură un personaj. Cu tastele W, A, S și D se poate deplasa personajul de-a lungul direcțiilor față, stânga, spate și dreapta ale camerei observator. Apăsarea simulatană a două taste, de exemplu tastele W și A rezultă în deplasarea jucătorului de-a lungul vectorului compus dintre direcția față și stânga a camerei observator. În filmulețul de mai jos se poate observa acest comportament pentru controlul personajului.
Geometria personajului este orientată astfel încât “fața” lui se află pe direcția de deplasare, descrisă mai sus.
Camera observator se află în partea de sus a personajului pe o direcție înclinată față de axa globală OY. Camera urmărește deplasarea personajului și direcția de vizualizare este întotdeauna spre poziția personajului.
Inamicii încearcă să ajungă la poziția personajului, astfel că ei se deplasează continuu în direcția poziției lui. Doar pentru a fi corect față de jucător, viteza de deplasare a inamicilor este mai mică decât viteza de deplasare a personajului :) . De asemenea, la orice moment de timp, inamicii sunt orientați către personaj.
Prin apăsarea tastei space, jucătorul are opțiunea de a “trage” cu o “armă”. Toți inamicii ce se află în fața personajului, mai exact pe direcția lui de deplasare, la o distanță mai mică de 2 unități față de personaj, dispar din joc. În locul fiecărui inamic care dispare, alt inamic apare în locul lui la o poziție aleatorie în lume.
La apăsarea tastei 0 din zona numerică a tastaturii, numpad în limba engleză sau a tastei enter, în joc apare un nou personaj ce poate fi controlat de la tastatură. Ecranul se împarte pe lățime în două zone de dimensiuni egale, ca în filmulețul demo de mai sus. Pe fiecare din cele două ecrane se desenează geometria lumii din două perspective diferite, câte una pentru fiecare personaj.
Desenarea geometriei pe fiecare din cele 2 porți de afișare se face identic precum desenarea realizată pentru un singur personaj. Singura diferență este dimensiunea porții de afișare. Desenarea lumii din perspectiva personajului inițial se realizează în poarta de afișare din partea stângă, iar desenarea pentru al doilea personaj se realizează în poarta de afișare din dreapta. Cel de-al doilea personaj are o culoare diferită fața de primul.
De la tastatură, se poate controla cel de-al doilea personaj, similar ca în situația celui inițial. Se folosesc săgețile de la tastatură pentru deplasare și tasta 0 din zona numerică a tastaturii sau tasta enter pentru comportamentul de tras.
Geometria personajului și a inamicilor poate fi identică. Ea este realizată din 6 paralelipipede, ce reprezintă trunchiul, capul, piciorul stâng și drept, brațul stâng și drept al personajului, conform imaginii de mai jos.
În situația în care se utilizează framework-ul de laborator, pentru determinarea direcției de deplasare a jucătorului pe baza direcției de vizualizare a camerei observator, se poate utiliza obiectul de tip Camera
, după cum urmează:
auto camera = GetSceneCamera(); glm::vec3 forward = camera->m_transform->GetLocalOZVector(); forward = glm::normalize(glm::vec3(forward.x, 0, forward.z));
Se utilizează o proiecție pe planul XOZ a direcției de vizualizare a camerei. Calculele se realizează analog și pentru celelalte direcții ale obiectului de tip Camera
.
Pentru a orienta geometria personajului în direcția de deplasare, se utilizează o matrice de rotație în jurul axei OY. În situația în care se cunoaște direcția de deplasare, unghiul de rotație se poate calcula după cum urmează:
$$ unghi = arctan(\frac{directie_x}{directie_z}) $$
atan2()
pentru calcularea arctangentei.
În situația în care se utilizează framework-ul de laborator, pentru desenarea geometriei din perspectiva camerei observator, se poate utiliza obiectul de tip Camera
, după cum urmeaza:
auto camera = GetSceneCamera(); // pozitia relativa a camerei fata de pozitia personajului glm::vec3 relativeCameraPosition = ...; // playerPosition este pozitia in lume a personajului controlat de jucator camera->SetPositionAndRotation( playerPosition + relativeCameraPosition, glm::quatLookAt(-glm::normalize(relativeCameraPosition), glm::vec3(0, 1, 0)) );
În calculele de iluminare a geometriei, trebuie utilizată componenta ambientală, componenta difuză și componenta speculară. Se pot utiliza modelele de iluminare deja analizate. Dacă se dorește, se poate înlocui calculul de iluminare pentru oricare din cele 3 componente cu un alt model de iluminare ce oferă rezultate vizuale superioare :) . Utilizarea unor astfel de modele de iluminare se punctează suplimentar.
În situația în care transformarea de modelare conține o transformare neuniformă de modificare a scării, trecerea vectorului normal din spațiul obiectului în spațiul lumii se realizează după cum urmează:
$$ \begin{bmatrix} \vec{N'}_{x} \\ \vec{N'}_{y} \\ \vec{N'}_{z} \\ 0 \end{bmatrix} = {{(Model^{-1})}^t} \cdot \begin{bmatrix} \vec{N}_{x} \\ \vec{N}_{y} \\ \vec{N}_{z} \\ 0 \end{bmatrix} $$
Direcția de iluminare a surselor de lumină de tip spot din vârful stâlpilor se vor roti continuu.
Rezultatul este doar un efect vizual ce curbează geometria în jurul personajului, astfel că acesta poate ajunge la limita geometriei lumii, altfel spus la capătul ei și să și depășească acest capăt :) . De asemenea, este important de menționat că pentru calculele de iluminare NU se ține cont de calculele de creare a curburii geometriei.
Realizeaza curburii obiectelor din lume se realizează la pasul de desenare a obiectelor din scenă. Acest efect se creează prin modificarea componentei y a coordonatelor pentru toate vârfurile obiectelor din lume. Procesul este realizat în vertex shader. Componenta y a tuturor vârfurilor se modifică după cum urmează:
$$ Pozitie_{v_y} = Pozitie_{v_y} - \|{Pozitie_{personaj}-Pozitie_v}\|^2 \cdot factorCurbura $$
Factorul de curbură este proporțional cu dimensiunea obiectelor din lume. Pentru demo-ul de mai sus, este utilizat un factor de 0.02.
La apăsarea tastei space, personajul “trage” cu o “armă”, așa cum s-a menționat mai sus. Pentru a identifica inamicii care se află pe direcția de deplasare a personajului, la distanță mai mică de 2 unități, se poate folosi o abordare simplă ce oferă rezultate satisfăcătoare. Se utilizează un cerc virtual de rază 1, astfel ca diametrul să fie de dimensiune 2, ce se poziționează cu centrul la distanța 1 față de poziția personajului, pe direcția lui de deplasare. Această abordare este descrisă vizual în imaginea de mai jos.
Prin utilizarea acestei abordări, este suficient să identificăm toți inamicii ce au poziția în cercul descris mai sus pentru a afla inamicii ce trebuie eliminați din joc. Se consideră pozițiile personajului și ale inamicilor proiectate paralel pe planul XOZ pentru a lucra într-un spațiu 2D. Pentru a verifica dacă o poziție se află în interiorul unui cerc, se verifică daca distanta între poziție și centrul cercului este mai mică decât raza cercului.
Geometria personajului și a inamicilor trebuie să realizeze o animație continuă de deplasare, conform filmulețului de mai jos:
Doar pentru personajul controlat de jucător, în momentul în care jucătorul se oprește din mișcare, animația trebuie să se întoarcă înapoi la cadrul de animație în care personajul stă pe loc. În filmulețul de mai jos se poate observa acest comportament de joc.
În momentul în care jocul se utilizează în 2, pe ecran se desenează geometria în două porți de afișare cum s-a descris mai sus. Toate elementele vizuale, inclusiv personajul companion și iluminarea cu sursele de lumină proprii personajului companion, trebuie să se deseneze din două perspective diferite, câte una pentru fiecare personaj. De asemenea, curbura geometriei trebuie realizată din poziția personajului din perspectiva căruia se desenează geometria în poarta de afișare.