This is an old revision of the document!
În cadrul acestei teme va trebui să implementați un joc simplu de dame. Un demo ce înfățișează o posibilă implementare îl puteți viziona în continuare:
Regulile pe care le aveți de implementat nu trebuie să acopere toate mecanicile folosite în jocul real de dame, ci doar un subset de mișcări simple. Jocul începe într-o configurație prezentată în imaginea de mai jos.
Pentru simplitate, ambele seturi de piese vor fi controlate de către jucător (nu trebuie să implementați un algoritm pentru adversar). În fiecare tură, jucătorul poate deplasa o singură piesă. Scopul jocului este capturarea tuturor pieselor adversarului. Subsetul de mișcări pe care le aveți de implementat sunt:
Nu trebuie să implementați atacuri multiple sau alte reguli de joc pentru funcționalitățile obligatorii.
Pentru a selecta o piesă de joc se va folosi butonul stânga de la mouse. Mai jos se vor descrie detaliile tehnice pentru a implementa această selecție. În momentul în care o piesă a fost selectată, aceasta primește un “highlight” realizat prin schimbarea culorii piesei. De asemenea, toate căsuțele disponibile pentru mutare vor fi marcate printr-un “highlight”, realizat tot prin colorare.
În momentul în care a fost selectată căsuța destinație (prin click-stânga), piesa se va deplasa pe o traiectorie definită de voi (de exemplu sinusoidală, vezi demo). Deplasarea se va realiza printr-o animație continuă. Atât timp cât piesa își desfășoară animația de mișcare, jucătorul nu va putea selecta/deplasa alte piese de pe tabla de joc.
Obiectele pe care trebuie să le realizați sunt tabla de joc și piesele pentru fiecare adversar.
Tabla de joc va avea un layout de 8×8 (64 de căsuțe). Va trebui să implementați un mecanism pentru selectarea și deplasarea pieselor folosind cursorul, așadar fiecare căsuța va fi realizată plecând de la un mesh de quad. Căsuțele vor fi colorate alternativ și translatate corespunzător configurației.
Pentru generarea pieselor de joc se vor folosi cel puțin 3 suprafețe de rotație. Două exemple de astfel de suprafețe pot fi văzute în imaginea de mai jos. Acestea reprezintă geometria pieselor din demo. Cele 3 suprafețe de rotație care compun geometria obiectului sunt marcate prin culori diferite. Curba utilizată pentru obținerea suprafeței se află în stânga fiecărei imagini. Pentru a calcula pozițiile punctelor de control ale curbei bezier se pot folosi aplicații online, precum cea de aici: https://www.desmos.com/calculator/d1ofwre0fr.
Se va asocia fiecărui obiect un ID unic, care va fi desenat pe ecran împreună cu informația de culoare, în canalul de alpha. Acest canal nu este în final vizibil, astfel că el va fi folosit doar ca sursă de informație. Pe lângă informația de culoare RGB din fiecare fragment, se va păstra în componenta alpha ID-ul asociat obiectului desenat:
out_color.a = id / 255.0f; // id este o valoare intre 0 si 255.
Un exemplu de vizualizare a acestor ID-uri, sub forma de nuanțe de gri (vec3 (id / 255.0f, id / 255.0f, id / 255.0f)
) poate fi cel de mai jos. ID-ul este alocat aleator pentru fiecare piesă și căsuță a tablei de joc.
Când se apasă butonul stânga de la mouse, se obține poziția mouse-ului pe ecran și se interoghează textura din framebuffer pentru a obține ID-ul obiectului din canalul de alpha:
// x si y reprezinta pozitia mouse-ului pe ecran, in pixeli. unsigned char data[4]; y = window->props.resolution.y - y; glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); int id = data [3];
Mediul înconjurător va fi vizibil în scenă sub forma unui cubemap. Acesta se va reflecta pe suprafața tablei și a pieselor de joc. Pentru simplitate, reflexia se va realiza utilizând numai acest cubemap (nu trebuie să implementați reflexia dintre piese sau self-reflection).
Ca să aplicați atât culoarea piesei, cât să reușiți să mapați și reflexia mediului înconjurător pe suprafețele generate, puteți folosi funcția mix (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mix.xhtml).
Pentru a se calcula reflexia pieselor de joc, este necesar să se calculeze în geometry shader poziția și normala în spațiul lume a fiecărui vertex de pe suprafața de rotație. Pentru a se calcula normala unui vertex se va folosi vectorul perpendicular pe triunghiul din care face parte vertexul:
// pos1, pos2 si pos3 reprezinta pozitiile vertecsilor care formeaza un triunghi. vec3 v1 = normalize (pos2 - pos1); vec3 v2 = normalize (pos3 - pos1); vec3 normal = cross (v1, v2);
Capturarea unei piese va fi recompensată de un efect de “spulberare”. Pentru a obține acest efect, în momentul în care piesa adversarului dispare (la finalizarea animației de capturare), va trebui să implementați un sistem de particule care să emită din poziția piesei capturate și pe direcția normală la tabla de joc.
Tema va fi implementată în OpenGL și C++. Este indicat să folosiți framework-ul și Visual Studio.
Pentru implementarea temei, in folderul src/lab_m2 puteti crea un nou folder, de exemplu Tema1, cu fisierele Tema1.cpp si Tema1.h (pentru implementare POO, este indicat sa aveti si alte fisiere). Pentru a vedea fisierele nou create in Visual Studio in Solution Explorer, apasati click dreapta pe filtrul lab_m2 si selectati Add→New Filter. Dupa ce creati un nou filtru, de exemplu Tema1, dati click dreapta si selectati Add→Existing Item. Astfel adaugati toate fisierele din folderul nou creat. In fisierul lab_list.h trebuie adaugata si calea catre header-ul temei. De exemplu: #include “lab_m2/Tema1/Tema1.h”