This shows you the differences between two versions of the page.
egc:teme:2023:01 [2023/10/29 16:46] mihnea.tudor circle collision image update |
egc:teme:2023:01 [2023/11/03 20:25] (current) andrei.lambru [Reguli generale de joc] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | <hidden> | ||
===== Tema 1 - Romburi vs hexagoane ===== | ===== Tema 1 - Romburi vs hexagoane ===== | ||
- | * **Responsabili:** | + | * **Responsabili:** Andrei Voicu, Mihnea Tudor, Anca Cristea, Cristian Lambru |
* **Lansare:** 30 octombrie 2023 | * **Lansare:** 30 octombrie 2023 | ||
* **Termen de predare:** 19 noiembrie 2023, ora 23:59 | * **Termen de predare:** 19 noiembrie 2023, ora 23:59 | ||
Line 7: | Line 6: | ||
* **Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!** | * **Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!** | ||
- | În cadrul temei 1, veți avea de implementat un joc similar cu "Plants vs Zombies", dar adaptat pentru a conține o geometrie mult mai simplă :) . Puteți viziona un mic demo construit pe baza framework-ului de laborator, care acoperă cerințele și are un aspect vizual minimal. | + | În cadrul temei 1, veți avea de implementat un joc similar cu [[https://youtu.be/XENla8M3910?feature=shared&t=314 | "Plants vs Zombies"]], dar adaptat pentru a conține o geometrie mult mai simplă :) . Puteți viziona un mic demo construit pe baza framework-ului de laborator, care acoperă cerințele și are un aspect vizual minimal. |
<html> | <html> | ||
Line 17: | Line 16: | ||
De asemenea, puteți descărca demo-ul {{egc:teme:2023:jocrvsh.zip | aici}} pentru a-l testa și a înțelege mai clar comportamentul de joc. | De asemenea, puteți descărca demo-ul {{egc:teme:2023:jocrvsh.zip | aici}} pentru a-l testa și a înțelege mai clar comportamentul de joc. | ||
- | Pe scurt, jocul se va desfasura în cadrul a 3 linii, cu 3 coloane fiecare. Din partea dreaptă, din afara ecranului, apar la intervale aleatoare de timp inamici "răi" de tip hexagon ce parcurg o linie până în partea stângă a ecranului. O dată ce un hexagon parcurge toata linia, jucătorul pierde o viață :( . La 3 vieți pierdute, jocul este pierdut. | + | <note tip> |
+ | Implementarea din demo-ul pus la dispoziție nu identifică corect poziția cursorului, în situația în care se modifică dimensiunea ferestrei. Aceasta rămâne de implementat la latitudinea voastră și este considerată cerință bonus :) . | ||
+ | </note> | ||
+ | |||
+ | Pe scurt, jocul se va desfășura în cadrul a 3 linii, cu 3 coloane fiecare. Din partea dreaptă, din afara ecranului, apar la intervale aleatoare de timp inamici "răi" de tip hexagon ce parcurg o linie până în partea stângă a ecranului. Odată ce un hexagon parcurge toată linia, jucătorul pierde o viață :( . La 3 vieți pierdute, jocul este pierdut. | ||
- | Pentru a combate hexagoanele rele :(, jucătorul are posibilitatea de a plasa într-una din cele 3 celule de pe fiecare linie, un romb salvator care lansează proiectile ce se deplasează în partea dreaptă, de-alungul liniei în care se află rombul ce a lansat proiectilul. Odată întâlnit un hexagon, proiectilul îi creeaza daune și la 3 proiectile atinse, hexagonul dispare și situația este salvată pentru moment <3. | + | Pentru a combate hexagoanele rele :(, jucătorul are posibilitatea de a plasa într-una din cele 3 celule de pe fiecare linie, un romb salvator care lansează proiectile ce se deplasează în partea dreaptă, de-alungul liniei în care se află rombul ce a lansat proiectilul. Odată întâlnit un hexagon, proiectilul îi creează daune și la 3 proiectile atinse, hexagonul dispare și situația este salvată pentru moment <3. |
- | Cu toate acestea, jucătorul are 2 inconveniente :( . El nu poate plasa oricâte romburi dorește, deoarece fiecare romb plasat costă un anumit număr de steluțe. Acestea apar la intervale aleatoare în scenă și jucătorul trebuie să le strângă. În plus, fiecare romb poate răni doar un anumit tip de hexagon, pe baza culorii pe care o are fiecare. | + | Cu toate acestea, jucătorul are 2 inconveniente :( . El nu poate plasa oricâte romburi dorește, deoarece fiecare romb plasat costă un anumit număr de steluțe. Acestea apar la intervale aleatoare în scenă și jucătorul trebuie să le strângă. În plus, fiecare romb poate răni doar un anumit tip de hexagon, pe baza culorii pe care o are fiecare. |
Sunteți gata să ajutați jucătorul să învingă hexagoanele "rele" :) ? | Sunteți gata să ajutați jucătorul să învingă hexagoanele "rele" :) ? | ||
Line 29: | Line 32: | ||
=== Plasare romb în scena de joc === | === Plasare romb în scena de joc === | ||
- | Jocul are un comportament bazat pe culori. Sunt 4 tipuri de triplete romb-proiectil-inamic, fiecare triplet de aceeași culoare de bază. În exemplul nostru, am ales culorile portocaliu, albastru, galben și mov. Voi puteți sa alegeti alte culori. | + | Jocul are un comportament bazat pe culori. Sunt 4 tipuri de triplete romb-proiectil-inamic, fiecare triplet de aceeași culoare de bază. În exemplul nostru, am ales culorile portocaliu, albastru, galben și mov. Voi puteți să alegeți alte culori. |
Vom numi romburi, din acest moment până la final, elementele plasate de jucător. | Vom numi romburi, din acest moment până la final, elementele plasate de jucător. | ||
- | În interfața grafică cu utilizatorul, sau GUI, în partea stânga-sus a ecranului, se regăsesc 4 chenare, cu câte un tip de romb în fiecare. Prin procesul de drag & drop, descris mai sus, se selectează un anumit tip de romb și se plasează într-una din celulele de joc valide, în care nu se regăsește niciun alt romb. | + | În interfața grafică cu utilizatorul, sau GUI, în partea stânga-sus a ecranului, se regăsesc 4 chenare, cu câte un tip de romb în fiecare. Prin procesul de drag & drop, descris mai jos, se selectează un anumit tip de romb și se plasează într-una din celulele de joc valide, în care nu se regăsește niciun alt romb. |
Jucatorului i se va permite selecția unui tip de romb, doar dacă acesta are resurse suficiente pentru plasarea tipului respectiv. Numărul de resurse stabilit de noi este: | Jucatorului i se va permite selecția unui tip de romb, doar dacă acesta are resurse suficiente pentru plasarea tipului respectiv. Numărul de resurse stabilit de noi este: | ||
Line 41: | Line 44: | ||
* 3 steluțe pentru rombul de culoare mov | * 3 steluțe pentru rombul de culoare mov | ||
- | Steluțele apar în scena la intervale aleatoare. Noi am ales sa apară câte 3 odată. Jucătorul poate selecta o steluță când cursorul se află în interiorul ei si apasă butonul stânga de la mouse. Odată selectată o steluță, i se adaugă la numărul de steluțe pe care îl are strâns până în acel moment. | + | Steluțele apar în scenă la intervale aleatoare. Noi am ales să apară câte 3 odată. Jucătorul poate selecta o steluță când cursorul se află în interiorul ei și apasă butonul stânga de la mouse. Odată selectată o steluță, i se adaugă la numărul de steluțe pe care îl are strâns până în acel moment. |
=== Comportament romburi și inamici === | === Comportament romburi și inamici === | ||
- | Din partea dreaptă, la intervale aleatoare de timp, se deplasează un inamic de-alungul unei linii alese aleator. Inamicul face parte din unul din cele 4 tipuri posibile. În situația în care un romb de același tip se regăsește într-una din cele 3 celule ale liniei, acesta începe sa lanseze proiectile la intervale regulate. În situația în care există și **alte tipuri** de romburi pe linie, acestea **nu lansează proiectile**. | + | Din partea dreaptă, la intervale aleatoare de timp, se deplasează un inamic de-alungul unei linii alese aleator. Inamicul face parte din unul din cele 4 tipuri posibile. În situația în care un romb de același tip se regăsește într-una din cele 3 celule ale liniei, acesta începe să lanseze proiectile la intervale regulate. În situația în care un romb **nu are un inamic de același tip cu el pe linie**, rombul respectiv **nu lansează proiectile**, chiar dacă pe linie sunt inamici de alte tipuri. |
+ | |||
+ | <hidden> | ||
+ | În situația în care există și **alte tipuri** de romburi pe linie, acestea din urmă **nu lansează proiectile**. | ||
+ | </hidden> | ||
=== GUI === | === GUI === | ||
- | Jocul are o interfață grafică pentru utilizator ce conține, pe lângă chenarele cu care interacționează pentru plasarea romburilor și informații suplimentare, menite să îl ajute pe jucator. Anume, in această interfața se regăsesc: | + | Jocul are o interfață grafică pentru utilizator ce conține, pe lângă chenarele cu care interacționează pentru plasarea romburilor, și informații suplimentare, menite să îl ajute pe jucator. Anume, în această interfață se regăsesc: |
* Numărul de puncte de viață rămase. Inițial, jocul pleacă de la 3 | * Numărul de puncte de viață rămase. Inițial, jocul pleacă de la 3 | ||
* Numărul de steluțe strânse până la momentul respectiv de joc | * Numărul de steluțe strânse până la momentul respectiv de joc | ||
* Sub chenarul fiecărui tip de romb, sunt desenate mai multe steluțe, specific numărului necesar pentru plasarea tipului respectiv de romb | * Sub chenarul fiecărui tip de romb, sunt desenate mai multe steluțe, specific numărului necesar pentru plasarea tipului respectiv de romb | ||
- | Daca doriți indicații pentru implementarea anumitor mecanici de joc, mai multe detalii se pot găsi în secțiunea dedicată, sub barem. | + | Dacă doriți indicații pentru implementarea anumitor mecanici de joc, mai multe detalii se pot găsi în secțiunea dedicată, sub barem. |
==== Barem ==== | ==== Barem ==== | ||
+ | <note tip> | ||
+ | În cadrul temei, puteți implementa o formă simplă de joc, doar prin realizarea cerințelor de bază. Mecanismul de plasare a unui romb poate fi implementat prin identificarea selecției cu butonul stânga de la mouse a unei celule valide și plasarea unui romb în interiorul celulei. În această situație, nu este necesar să se țină cont de numărul de resurse strânse până la un moment dat, ceea ce înseamnă că se permite jucătorului să plaseze oricâte romburi dorește în celulele disponibile :) . | ||
+ | </note> | ||
- | === Funcționalități de baza (150 puncte) === | + | === Funcționalități de bază (150 puncte) === |
- | * Constructie elemente scena (60p total) | + | * Construcție elemente scenă (60p total) |
- | * Desenare geometrie scena de joc 20p | + | * Desenare geometrie scenă de joc 20p |
* Desenare geometrie romb 10p | * Desenare geometrie romb 10p | ||
* Desenare geometrie inamic 10p | * Desenare geometrie inamic 10p | ||
- | * Desenare geometrie steluta 20p | + | * Desenare geometrie steluță 20p |
- | * Animatii (40p total) | + | * Animații (40p total) |
* Deplasare inamic pe linie 5p | * Deplasare inamic pe linie 5p | ||
- | * Deplasare si rotatie proiectil 15p | + | * Deplasare și rotație proiectil 15p |
- | * Animatie disparitie romb 10p | + | * Animație dispariție romb 10p |
- | * Animatie disparitie inamic 10p | + | * Animație dispariție inamic 10p |
* Comportament de joc (50p in total) | * Comportament de joc (50p in total) | ||
- | * Detectia selectiei unei celule de joc prin apasarea butonului stanga a mouse-ului si plasarea unui romb in celula 10p | + | * Detecția selecției unei celule de joc prin apăsarea butonului stânga al mouse-ului și plasarea unui romb în celulă 10p |
- | * Aparitie inamici la intervale regulate 5p | + | * Apariție inamici la intervale aleatoare 5p |
- | * Detectia faptului ca un inamic a traversat in totalitate o linie 5p | + | * Detecția faptului că un inamic a traversat în totalitate o linie 5p |
- | * Aparitie proiectil de langa un romb in momentul in care exista inamic pe linie 10p | + | * Apariție proiectil de lânga un romb în momentul în care există inamic pe linie 10p |
- | * Detectie coliziune proiectil-inamic 10p | + | * Detecție coliziune proiectil-inamic 10p |
- | * Detectie coliziune romb-inamic 10p | + | * Detecție coliziune romb-inamic 10p |
=== Funcționalități avansate (75p total) === | === Funcționalități avansate (75p total) === | ||
* Comportament drag & drop (25p in total) | * Comportament drag & drop (25p in total) | ||
- | * Desenare in GUI a 4 chenare ce contin dreptunghiuri incadratoare si cele 4 tipuri de romburi 5p | + | * Desenare în GUI a 4 chenare ce conțin dreptunghiuri încadratoare și cele 4 tipuri de romburi 5p |
- | * Detectia selectiei si afisarea rombului pe ecran la pozitia cursorului, in perioada in care butonul stanga de la mouse este apasat 15p | + | * Detecția selecției și afișarea rombului pe ecran la poziția cursorului, în perioada în care butonul stânga de la mouse este apăsat 15p |
- | * Detectia faptului ca nu s-a mai apasat butonul stanga de la mouse, in momentul in care pozitia mouse-ului este in interiorul unei celule valide 5p | + | * Detecția faptului că nu s-a mai apăsat butonul stânga de la mouse, în momentul în care poziția mouse-ului este în interiorul unei celule valide 5p |
- | * Cuantificarea numarului de vieti ramase, initial sunt 3, si afisarea lor in GUI 10p | + | * Cuantificarea numărului de vieți rămase, inițial sunt 3, și afișarea lor in GUI 10p |
- | * Detectia selectiei de stergere a unui romb, prin apasarea butonului dreapta de la mouse in celula in care se afla deja un romb 5p | + | * Detecția selecției de ștergere a unui romb, prin apăsarea butonului dreapta de la mouse în celula în care se află deja un romb 5p |
* Gestionare resurse (20p in total) | * Gestionare resurse (20p in total) | ||
- | * Aparitie stelute pe ecran, la anumite intervale 2.5p | + | * Apariție steluțe pe ecran, la anumite intervale 2.5p |
- | * Detectia selectiei unei stelute prin apasarea butonului stanga a mouse-ului si disparitia ei de pe ecran 10p | + | * Detecția selecției unei steluțe prin apăsarea butonului stânga al mouse-ului și dispariția ei de pe ecran 10p |
- | * Desenarea in GUI, sub fiecare tip de romb, a numarului de stelute necesar pentru plasarea tipului respectiv 2.5p | + | * Desenarea în GUI, sub fiecare tip de romb, a numărului de steluțe necesar pentru plasarea tipului respectiv 2.5p |
- | * Permiterea plasarii unui romb, doar cand numarul de stelute este suficient 2.5p | + | * Permiterea plasării unui romb, doar când numărul de steluțe este suficient 2.5p |
- | * Cuantificarea stelutelor stranse si consumate, desenarea in GUI a numarului de stelute existente la momentul desenarii 2.5p | + | * Cuantificarea steluțelor strânse și consumate, desenarea în GUI a numărului de steluțe existente la momentul desenării 2.5p |
* Gestionare comportament de joc bazat pe culori (15p in total) | * Gestionare comportament de joc bazat pe culori (15p in total) | ||
- | * Desenarea in GUI a 4 tipuri de romburi, diferentiate printr-o culoare specifica pentru fiecare 2.5p | + | * Desenarea în GUI a 4 tipuri de romburi, diferențiate printr-o culoare specifică pentru fiecare 2.5p |
- | * Aparitia la anumite intervale a 4 tipuri diferite de inamici, diferentiati printr-o culoare specifica pentru fiecare 2.5p | + | * Apariția la anumite intervale a 4 tipuri diferite de inamici, diferențiați printr-o culoare specifică pentru fiecare 2.5p |
- | * Aparitia proiectilului de langa un romb ce are o anumita culoare, doar in momentul in care exista pe linia ei un inamic de aceeasi culoare 5p | + | * Apariția proiectilului de lânga un romb ce are o anumită culoare, doar în momentul în care există pe linia lui un inamic de aceeași culoare 5p |
- | * Aparitie proiectil cu aceeasi culoare ca cea a rombului de langa care a aparut 2.5p | + | * Apariție proiectil cu aceeași culoare ca cea a rombului de lânga care a apărut 2.5p |
- | * Detectia coliziunii proiect-inamic doar in situatia in care proiectilul are aceeasi culoare ca cea a inamicului 2.5p | + | * Detecția coliziunii proiectil-inamic, doar în situația în care proiectilul are aceeași culoare ca cea a inamicului 2.5p |
- | ==== Exemple de funcționalități bonus ==== | + | ===== Detalii de implementare ===== |
- | <note warning>Orice funționalitate suplimentară implementată (care nu este inclusă în cerințele obligatorii) poate fi considerată ca punctaj bonus dacă este suficient de complexă. Funcționlitățile bonus se iau în considerare doar dacă funcționalitățile obligatorii au fost realizate.</note> | + | ==== Construcție elemente vizuale ==== |
- | + | ||
- | * Romburi mai speciale (ex: romburi care genereaza, la un anumit interval, resurse care se pot culege; romburi care explodeaza; romburi care ataca mai multe linii de-odata) | + | |
- | * Hexagoane mai speciale (ex: hexagoane care isi schimba culoarea la fiecare 'hit'; hexagoane mai slabe sau puternice, cu indicatori vizuali) | + | |
- | * Cresterea dificultatii pe masura ce avansati in timp | + | |
- | * Implementare de "niveluri" cu durate stabilite, avansarea la urmatorul nivel in urma terminarii celui anterior | + | |
- | * Sistem de "waves" (ca in jocul original): in anumite momente ale jocului, un grup mare de hexagoane este trimis catre romburi | + | |
- | * Resurse care cad din cer si se asaza undeva in scena | + | |
- | * Lawnmowers, ca in plants vs zombies? (TODO: daca vreti sa pastram asta sau nu) | + | |
- | + | ||
- | ==== Întrebări și răspunsuri ==== | + | |
- | + | ||
- | Pentru întrebări vom folosi forumurile de pe moodle. Orice nu este menționat în temă este la latitudinea fiecărui student! | + | |
- | + | ||
- | ==== Notare ==== | + | |
- | + | ||
- | Baremul este orientativ. Fiecare asistent are o anumită libertate în evaluarea temelor (de exemplu, să dea punctaj parțial pentru implementarea incompletă a unei funcționalități sau să scadă pentru hard coding). Același lucru este valabil atât pentru funcționalitățile obligatorii, cât și pentru bonusuri. | + | |
- | + | ||
- | <note warning> | + | |
- | Tema trebuie încărcată pe moodle. Pentru a fi punctată, tema trebuie prezentată la laborator. Vor exista laboratoare speciale de prezentare a temelor (care vor fi anunțate).</note> | + | |
- | + | ||
- | + | ||
- | + | ||
- | ==== Detalii de implementare ==== | + | |
- | + | ||
- | ==== Constructie elemente vizuale ==== | + | |
<note tip> | <note tip> | ||
- | Aveti libertate totala asupra felului in care se construiesc elementele vizuale necesare pentru joc, ce vor fi si descrise in continuare. Mai exact: | + | Aveți libertate totală asupra felului în care se construiesc elementele vizuale necesare pentru joc, ce vor fi și descrise în continuare. Mai exact: |
- | * Puteti construi geometria unui element dintr-o singura retea de triunghiuri, model 2D, care sa descrie toata forma, prin varfuri si indici. Pentru a atribui mai usor coordonate varfurilor, va recomandam sa utilizati platforma https://www.geogebra.org/calculator. | + | * Puteți construi geometria unui element dintr-o singură rețea de triunghiuri, model 2D, care să descrie toată forma, prin vârfuri și indici. Pentru a atribui mai ușor coordonate vârfurilor, vă recomandăm să utilizați platforma https://www.geogebra.org/calculator. |
- | * Puteti construi geometria unui element vizual prin afisarea mai multor figuri geometrice de baza, patrat, triunghi, pentru care sa aplicati transformari de translatie, scalare sau rotatie. | + | * Puteți construi geometria unui element vizual prin afișarea mai multor figuri geometrice de bază, pătrat, triunghi, pentru care să aplicați transformări de translație, scalare sau rotație. |
- | In vederea crearii animatiilor, va recomandam sa fiti atentiei asupra formei de constructie. O stea sau un hexagon cu centrul in originea axelor de coordonate este mai usor de prelucrat :) . | + | În vederea creării animațiilor, vă recomandăm să fiți atenți asupra formei de construcție. O stea sau un hexagon cu centrul în originea axelor de coordonate este mai ușor de prelucrat :) . |
</note> | </note> | ||
=== Scena de joc === | === Scena de joc === | ||
- | Scena de joc este compusa din mai multe patrate amplasate pe o grila cu 3 linii si 3 coloane. Aceasta poate fi vizualizata in imaginea de mai jos. Culoarea aleasa de noi pentru fiecare patrat ce reprezinta o celula din grila, este verde, dar voi puteti alege orice alta culoare, atata timp cat poate fi distinsa fata de culoarea de fundal. In partea stanga a grilei, am adaugat un dreptunghi rosu, pentru a marca zona in care se considera ca inamicii iau un punct de viata :( in situatia in care ajung la ea. | + | Scena de joc este compusă din mai multe pătrate amplasate pe o grilă cu 3 linii și 3 coloane. Aceasta poate fi vizualizată în imaginea de mai jos. Culoarea aleasă de noi pentru fiecare pătrat ce reprezintă o celulă din grilă, este verde, dar voi puteți alege orice altă culoare, atâta timp cât poate fi distinsă față de culoarea de fundal. În partea stânga a grilei, am adăugat un dreptunghi roșu, pentru a marca zona în care se consideră că inamicii iau un punct de viață :( în situația în care ajung la ea. |
{{ :egc:teme:2023:scene.png?600 |}} | {{ :egc:teme:2023:scene.png?600 |}} | ||
Line 146: | Line 131: | ||
=== Romb === | === Romb === | ||
- | Geometria elementelor ce sunt plaste in celulele scenei de joc, descrisa mai sus, este formata dintr-un romb si un dreptunghi in partea din dreapta a rombului. O imagine individuala a acestui element poate fi vazuta mai jos. | + | Geometria elementelor ce sunt plasate în celulele scenei de joc, descrisă mai sus, este formată dintr-un romb și un dreptunghi în partea din dreapta a rombului. O imagine individuală a acestui element poate fi văzută mai jos. |
{{ :egc:teme:2023:diamond.png?100 |}} | {{ :egc:teme:2023:diamond.png?100 |}} | ||
Line 152: | Line 137: | ||
=== Inamic === | === Inamic === | ||
- | Geometria inamicului este reprezentata de 2 hexagoane de dimensiuni diferite, ce au centrul in acelasi punct. Hexagonul mic trebuie sa fie desenat in fata hexagonului mare. Culorile celor 2 hexagoane trebuie sa fie diferite. O imagine cu un astfel de rezultat poate fi vizualizata mai jos. | + | Geometria inamicului este reprezentată de 2 hexagoane de dimensiuni diferite, ce au centrul în același punct. Hexagonul mic trebuie să fie desenat în fața hexagonului mare. Culorile celor 2 hexagoane trebuie să fie diferite. O imagine cu un astfel de rezultat poate fi vizualizată mai jos. |
{{ :egc:teme:2023:hexagon.png?100 |}} | {{ :egc:teme:2023:hexagon.png?100 |}} | ||
<note tip> | <note tip> | ||
- | Pentru a desena o forma geometrica in fata altei forme, puteti folosi componenta z a coordonatelor varfurilor. Pe ecran ramane desenata geometria ce are componenta z cea mai mare. | + | Pentru a desena o formă geometrică în fața altei forme, puteți folosi componenta z a coordonatelor vârfurilor. Pe ecran rămâne desenată geometria ce are componenta z cea mai mare. |
</note> | </note> | ||
- | === Steluta === | + | === Steluța === |
- | Geometria proiectilelor, a resurselor si a unui set de elemente din GUI este sub forma unor stelute cu 5 colturi, de culori diferite. Imaginea de mai jos prezinta geometria stelutei. | + | Geometria proiectilelor, a resurselor și a unui set de elemente din GUI este sub forma unor steluțe cu 5 colțuri, de culori diferite. Imaginea de mai jos prezintă geometria steluței. |
{{ :egc:teme:2023:star.png?100 |}} | {{ :egc:teme:2023:star.png?100 |}} | ||
Line 169: | Line 154: | ||
=== GUI === | === GUI === | ||
- | In partea de sus este afisata o interfata grafica pentru utilizator. Interactiunea cu aceasta interfata, prin mecanismul de drag & drop, este explicat mai jos. Elementele vizuale ale interfetei sunt: | + | În partea de sus este afișată o interfață grafică pentru utilizator. Interacțiunea cu această interfață, prin mecanismul de drag & drop, este explicată mai jos. Elementele vizuale ale interfeței sunt: |
- | * 4 chenare asezate in linie, ce contine geometria romburilor, cu o culoare spefica tipului. Fiecare chenar are un dreptunghi incadrator. Sub fiecare chenar se afiseaza mai multe stelute, specific numarului de resurse steluta ce trebuie consumate pentru a plasa tipul de romb specific chenarului. | + | * 4 chenare așezate în linie, ce conțin geometria romburilor, cu o culoare spefică tipului. Fiecare chenar are un dreptunghi încadrator. Sub fiecare chenar se afișează mai multe steluțe, specific numărului de resurse steluță ce trebuie consumate pentru a plasa tipul de romb specific chenarului. |
- | * Punctele de viata ramase pentru jucator la un moment dat, reprezentate de patrate de culoare rosie, asezate in linie. | + | * Punctele de viață rămase pentru jucator la un moment dat, reprezentate de pătrate de culoare roșie, așezate în linie. |
- | * Stelutele selectate, afisate in line. | + | * Steluțele colectate, afișate în linie. |
- | Interfata grafica pentru utilizator poate fi vazuta in imaginea de mai jos. | + | Interfața grafică pentru utilizator poate fi văzută în imaginea de mai jos. |
{{ :egc:teme:2023:gui.png?600 |}} | {{ :egc:teme:2023:gui.png?600 |}} | ||
- | ==== Animatii ==== | + | ==== Animații ==== |
<note important> | <note important> | ||
- | Pentru toate animatiile din joc, utilizati parametrul ''deltaTime'' pentru a crea animatii independente de numarul de cadre desenate pe secunda. | + | Pentru toate animațiile din joc, utilizați parametrul ''deltaTime'' pentru a crea animații independente de numărul de cadre desenate pe secundă. |
</note> | </note> | ||
=== Deplasare de-alungul liniilor de joc === | === Deplasare de-alungul liniilor de joc === | ||
- | Pentru deplasarea proiectilelor si a inamicilor de-alungul unei linii de joc, se utilizeaza o transformare de translatie. Suplimentar, proiectilul cu forma de steluta va avea o transformare de rotatie, **in sens orar**, fata de centru in acelasi timp cu deplasarea. | + | Pentru deplasarea proiectilelor și a inamicilor de-alungul unei linii de joc, se utilizează o transformare de translație. Suplimentar, proiectilul cu formă de steluță va avea o transformare de rotație, **în sens orar**, față de centru, în același timp cu deplasarea. |
- | === Disparitie romb din joc === | + | === Dispariție romb din joc === |
- | In momentul in care un romb dintr-o celula de joc, plasat anterior de catre jucator, trebuie sa dispara din scena, rombul trebuie sa aiba o animatie de micsorare fata de centru, pana ajunge la scara (0, 0). Acest efect se poate obtine printr-o transformare de scalare. | + | În momentul în care un romb dintr-o celulă de joc, plasat anterior de către jucător, trebuie să dispară din scenă, rombul trebuie să aibă o animație de micșorare față de centru, până ajunge la scara (0, 0). Acest efect se poate obține printr-o transformare de scalare. |
- | Situatiile in care un romb este eliminat din joc sunt urmatoarele: | + | Situațiile în care un romb este eliminat din joc sunt următoarele: |
- | * In momentul in care un inamic s-a intersectat cu un romb, rombul dispare prin aceasta animatie, iar inamicul isi continua deplasarea spre stanga. | + | * În momentul în care un inamic s-a intersectat cu un romb, rombul dispare prin această animație, iar inamicul își continuă deplasarea spre stânga. |
- | * In momentul in care utilizatorul apasa butonul stanga de la mouse si cursorul este deasupra unei celule in care se afla un romb, rombul dispare prin aceasta animatie din celula. | + | * În momentul în care utilizatorul apasă butonul dreapta de la mouse și cursorul este deasupra unei celule în care se află un romb, rombul dispare prin această animație din celulă. |
- | === Disparitie inamic din joc === | + | === Dispariție inamic din joc === |
- | In momentul in care un proiectil se intersecteaza cu un inamic, acesta din urma dispare din scena printr-o animatie de micsorare fata de centrul comun al celor doua hexagoane care formeaza geometria inamicului. Aceasta animatie poate fi realizata, similar cu cea de micsorare a rombului, printr-o transformare de scalare. Proiectilul dispare si el la intersectia lui cu inamicul, doar ca nu realizeaza nicio animatie, doar nu se mai afiseaza de la cadrul urmator dupa detectia intersectiei. | + | În momentul în care un proiectil se intersectează cu un inamic, acesta din urmă dispare din scenă printr-o animație de micșorare față de centrul comun al celor două hexagoane care formează geometria inamicului. Această animație poate fi realizată, similar cu cea de micșorare a rombului, printr-o transformare de scalare. Proiectilul dispare și el la intersecția lui cu inamicul, doar că nu realizează nicio animație, doar nu se mai afișează de la cadrul următor după detecția intersecției. |
- | === Detectie coliziuni === | + | ==== Detecție coliziuni ==== |
- | ==== Detectie coliziuni intre obiecte ==== | + | Mecanismul de detecție a coliziunilor între diverse obiecte din scenă reprezintă un feature esențial în cam orice joc la care vă puteți gândi. În [[https://www.youtube.com/watch?v=fiShX2pTz9A|Pong]] trebuie verificată coliziunea mingii, atât cu ecranul jocului, cât și cu "paleta" fiecărui jucător. În jocurile [[https://www.youtube.com/watch?v=QLF0FXcW25E|Mario]], trebuie verificată coliziunea dintre jucător și toate obiectele înconjurătoare: cuburi, inamici, power-ups etc. În jocul nostru, avem nevoie de o implementare puțin mai simplificată a coliziunilor. |
- | Mecanismul de detectie a coliziunilor intre diverse obiecte din scena reprezinta un feature esential in cam orice joc la care va puteti gandi. In [[https://www.youtube.com/watch?v=fiShX2pTz9A|Pong]] trebuie verificata coliziunea mingii, atat cu ecranul jocului, cat si cu "paleta" fiecarui jucator. In jocurile [[https://www.youtube.com/watch?v=QLF0FXcW25E|Mario]], trebuie verificata coliziunea dintre jucator si toate obiectele inconjuratoare: cuburi, inamici, power-ups etc. In jocul nostru, avem nevoie de o implementare putin mai simplificata a coliziunilor. | + | Există două interacțiuni esențiale între obiecte, care necesită verificarea coliziunilor: |
+ | * între hexagon și romb - când hexagonul avansează la stânga până întâlnește un romb, moment în care rombul este distrus | ||
+ | * între proiectil și hexagon - când un romb lansează la dreapta un proiectil și se intersectează, pe drum, cu un hexagon | ||
- | Exista doua interactiuni esentiale intre obiecte, care necesita verificarea coliziunilor: | + | Deoarece formele obiectelor sunt mai complexe, iar implementarea unor coliziuni care să coincidă cu forma obiectului este mult prea complicată, vom folosi cercuri (mai multe detalii se pot găsi [[https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#circle_collision|aici]]). Pe scurt, aceste cercuri oferă o aproximare a formei unui obiect: un disc al cărui centru coincide cu centrul obiectului. Această abordare se implementează ușor și necesită mai puțină putere de procesare. O imagine care demonstrează funcționarea unei coliziuni între cercuri este următoarea: |
- | * intre hexagon si romb - cand hexagonul avanseaza la stanga pana intalneste un romb, moment in care rombul este distrus | + | |
- | * intre proiectil si hexagon - cand un romb lanseaza la dreapta un proiectil si se intersecteaza, pe drum, cu un hexagon | + | |
- | + | ||
- | Deoarece formele obiectelor sunt mai complexe, iar implementarea unor coliziuni care sa coincida cu forma obiectului este mult prea complicata, vom folosi cercuri (mai multe detalii se pot gasi [[https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#circle_collision|aici]]). Pe scurt, aceste cercuri ofera o aproximare a formei unui obiect: un disc al carui centru coincide cu centrul obiectului. Aceasta abordare se implementeaza usor si necesita mai putina putere de procesare. O poza care demonstreaza functionarea unei coliziuni intre cercuri este urmatoarea: | + | |
{{ :egc:teme:2023:circle_collision.png?300 |}} | {{ :egc:teme:2023:circle_collision.png?300 |}} | ||
- | Astfel, se va defini aceasta forma de coliziune pentru proiectile, hexagoane si romburi. Cercurile **nu** vor fi desenate pe ecran, ci vor fi folosite doar pentru a crea logica jocului. Pentru a detecta coliziunea intre 2 obiecte, trebuie sa urmariti pasii: | + | Astfel, se va defini această formă de coliziune pentru proiectile, hexagoane și romburi. Cercurile **nu** vor fi desenate pe ecran, ci vor fi folosite doar pentru a crea logica jocului. Pentru a detecta coliziunea între 2 obiecte, trebuie să urmăriți pașii: |
- | - Aflarea coordonatelor centrelor celor doua obiecte | + | - Aflarea coordonatelor centrelor celor două obiecte |
- | - Stabilirea razei fiecarui cerc | + | - Stabilirea razei fiecărui cerc |
- | - Aflarea distantei dintre cele doua centre (hint: [[https://registry.khronos.org/OpenGL-Refpages/gl4/html/distance.xhtml|glm::distance()]]) | + | - Aflarea distanței dintre cele două centre (hint: [[https://registry.khronos.org/OpenGL-Refpages/gl4/html/distance.xhtml|glm::distance()]]) |
- | - Verificarea daca distanta este mai mica decat suma razelor cercurilor | + | - Verificarea dacă distanța este mai mică decât suma razelor cercurilor |
- | <note important>Aveti grija cum definiti formele geometrice: proiectil, romb, hexagon. Daca ati definit obiectul original astfel incat centrul formei geometrice sa se afle in punctul (0, 0), atunci centrul cercului va coincide cu centrul formei. Altfel, este posibil sa intervina niste deplasari care trebuie luate in calcul. De asemenea, fiti atenti la eventuale rotatii si translatii ale obiectelor in scena.</note> | + | <note important>Aveți grijă cum definiți formele geometrice: proiectil, romb, hexagon. Dacă ați definit obiectul original astfel încât centrul formei geometrice să se afle în punctul (0, 0), atunci centrul cercului va coincide cu centrul formei. Altfel, este posibil să intervină niște deplasări care trebuie luate în calcul. De asemenea, fiți atenți la eventuale rotații și translații ale obiectelor în scenă.</note> |
- | <note>Aproximarea formei unui obiect se mai poate exprima prin dreptunghiuri incadratoare aliniate cu axele (axis-aligned bounding boxes, mai multe detalii [[https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#axis-aligned_bounding_box|aici]]). Implementarea este putin mai complicata decat coliziunile cerc-cerc, dar este totusi printre cele mai simple alternative de aproximare. In implementarea temei, noi recomandam aproximarea cu cercuri, fiind mai simpla, dar puteti alege oricare varianta.</note> | + | ==== Interacțiune jucător ==== |
- | ==== Detectie coliziuni intre obiecte si cursor ==== | + | Un alt aspect esențial este interacțiunea jucătorului cu obiectele din scenă, în acest caz, prin intermediul mouse-ului. Avem două astfel de interacțiuni: |
+ | * colectarea de resurse, prin apăsarea unui buton pe mouse | ||
+ | * plasarea romburilor în celule, prin intermediul drag & drop | ||
+ | * ștergerea romburilor din celule | ||
- | Un alt aspect esential este interactiunea jucatorului cu obiectele din scena, in acest caz, prin intermediul mouse-ului. Avem doua astfel de interactiuni: | + | Modul de funcționare este similar cu cel de la coliziunea obiect-obiect, fiind nevoie să determinăm marginile fiecărui obiect. În schimb, în acest caz, trebuie determinată poziția curentă a cursorului pe ecran, după care verificăm dacă se află în interiorul marginilor obiectului. |
- | * colectarea de resurse, prin apasarea unui buton pe mouse | + | |
- | * plasarea romburilor in celule, prin intermediul drag & drop | + | |
- | Modul de functionare este similar cu cel de la coliziunea obiect-obiect, fiind nevoie sa determinam marginile fiecarui obiect. In schimb, in acest caz, trebuie determinata pozitia curenta a cursorului pe ecran, dupa care verificam daca se afla in interiorul marginilor obiectului. | + | În funcțiile callback care sunt apelate la mișcări sau apăsări de buton ale mouse-ului ('OnMouseMove()', 'OnMouseBtnPress()'), coordonatele cursorului sunt date ca parametri, astfel că poziția cursorului este (mouseX, mouseY). Cele două valori sunt numere **întregi** ce reprezintă poziția cursorului în spațiul de vizualizare (pe fereastra jocului) pe orizontală, respectiv pe verticală. |
- | In functiile callback care sunt apelate la miscari sau apasari de buton ale mouse-ului ('OnMouseMove()', 'OnMouseBtnPress()'), coordonatele cursorului sunt date ca parametri, astfel ca pozitia cursorului este (mouseX, mouseY). Cele doua valori sunt numere **intregi** ce reprezinta pozitia cursorului in spatiul de vizualizare (pe fereastra jocului) pe orizontala, respectiv pe verticala. | + | <note important>Poziția cursorului pe fereastra jocului are ca punct de origine **colțul din stânga sus**, în timp ce spațiul de joc/logic are ca punct de origine **colțul din stânga jos**. Din acest motiv, pentru a folosi coordonata y a cursorului pentru obiectele din scena de joc, trebuie să utilizăm următorul calcul: //y_scena_joc = 720 - y_cursor//. Valoarea 720 reprezintă înălțimea ferestrei.</note> |
- | Pentru coliziunile cursor-obiect, vom folosi dreptunghiuri incadratoare aliniate cu axele (axis-aligned bounding boxes, mai multe detalii [[https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#axis-aligned_bounding_box|aici]]) pentru obiecte. Pe scurt, ne vom imagina un dreptunghi (in locul cercului de la coliziunile obiect-obiect) cu laturile paralele cu axele Ox si Oy, si cu centrul in cel al obiectului. | + | Pentru detecția situației în care poziția cursorului se află în interiorul unui element vizual din joc, vom folosi dreptunghiuri încadratoare aliniate cu axele (axis-aligned bounding boxes, mai multe detalii [[https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection#axis-aligned_bounding_box|aici]]) pentru obiecte. Pe scurt, ne vom imagina un dreptunghi (în locul cercului de la coliziunile obiect-obiect) cu laturile paralele cu axele Ox și Oy, și cu centrul în cel al obiectului. |
- | Pentru a verifica coliziunea mouse-ului cu un obiect, trebuie sa: | + | Pentru a verifica apăsarea unui buton de la mouse, când cursorul se află în interiorul unui obiect, trebuie să: |
- | - Traducem coordonatele cursorului din coordonate de vizualizare in coordonate logice (pornind de la scheletul laboratorului 3, acestea coincid 1:1, adica amandoua sunt intre coodronatele (0, 0) - (1280, 720), cu mentiunea de mai jos - atentie la coordonata verticala) | + | - Transformăm coordonatele cursorului de pe ecran în coordonatele scenei de joc |
- | - Calculam marginile dreptunghiului, in urma eventualelor aplicari de translatii si scalari | + | - Calculăm marginile dreptunghiului, în urma eventualelor aplicări de translații și scalări |
- | - Verificam daca pozitia cursorului este intre marginile dreptunghiului | + | - Verificăm dacă poziția cursorului este între marginile dreptunghiului |
- | <note important>Pozitia mouse-ului pe fereastra jocului are ca punct de origine **coltul din stanga sus**, in timp ce spatiul de joc/logic are ca punct de origine **coltul din stanga jos**.</note> | + | ==== Drag & drop ==== |
- | <note tip>Daca vreti sa functioneze corect detectia si in cazul redimensionarii ferestrei de joc, lucrurile se complica putin. | + | Pentru a plasa un romb pe una dintre celule, acesta trebuie selectat cu mouse-ul din bara romburilor disponibile, după care trebuie tras deasupra unei celule **libere**. O celulă liberă este o celulă care nu este deja ocupată de un romb. |
- | Initial, daca incepeti cu scheletul din laboratorul 3, spatiul logic coincide 1:1 cu spatiul de vizualizare, adica toate pozitiile obiectelor coincid cu coordonata respectiva de pe ecran. Marginea dreapta a spatiului logic va coincide cu marginea dreapta a ferestrei de joc, adica lungimea ferestrei (resolution.x), iar marginea de sus cu inaltimea ferestrei (resolution.y). | + | Pentru a crea acest mecanism, trebuie realizați următorii pași: |
+ | - Detecția apăsării butonului stâng al mouse-ului | ||
+ | - Detecția poziției cursorului într-una dintre căsuțele cu romburi disponibile (pentru care avem suficiente resurse) | ||
+ | - Randarea rombului la poziția cursorului, în fiecare frame, cât timp butonul rămâne apăsat | ||
+ | - Detecția eliberării (release) al aceluiași buton de mouse (cel stâng) | ||
+ | - Detecția poziției cursorului într-una dintre celulele libere | ||
+ | - Plasarea rombului în celulă | ||
+ | - Reducerea resurselor disponibile, în funcție de costul rombului | ||
- | Sa zicem ca vrem sa jucam in modul fullscreen. Vom nota rezolutia initiala (cea aleasa in functia 'main()') cu (init_width, init_height), iar cea noua cu (new_width, new_height). Spatiul logic ramane cel initial, intre coordonatele (0, 0) si (init_width, init_height), dar spatiul de vizualizare se mareste, fiind intre (0, 0) si (new_width, new_height). De aceea, pentru o functionare corecta, este necesara o transformare fereastra-poarta din noul spatiu de vizualizare in cel initial, pentru a coincide iarasi cu spatiul logic initial. | + | {{ :egc:teme:2023:drag-n-drop.gif?300 |}} |
- | Aceasta transformare trebuie aplicata pentru oricare alt fragment de cod sau logica ce se folosesc de marginile ecranului.</note> | + | <note>În cazul în care utilizatorul apasă pe un romb pentru care nu are suficiente resurse, algoritmul se oprește la pasul 2. De asemenea, dacă butonul mouse-ului este eliberat într-o poziție invalidă (oriunde în afara unei celule libere), desenarea rombului la poziția cursorului este oprită, iar resursele **nu** sunt consumate (practic, plasarea rombului într-o pozitie invalidă nu are niciun efect).</note> |
- | === Drag & drop === | + | ==== Exemple de funcționalități bonus ==== |
- | Pentru a plasa un romb pe una dintre celule, acesta trebuie selectat cu mouse-ul din bara romburilor disponibile, dupa care trebuie tras deasupra unei celule **libere**. O celula libera este o celula care nu este deja ocupata de un romb. | + | <note warning>Orice funcționalitate suplimentară implementată (care nu este inclusă în cerințele obligatorii) poate fi considerată ca punctaj bonus dacă este suficient de complexă. Funcționlitățile bonus se iau în considerare doar dacă funcționalitățile obligatorii au fost realizate.</note> |
- | Pentru a crea acest mecanism, trebuie realizati urmatorii pasi: | + | * Geometrie mai complexă față de cea din cerința de bază pentru elementele vizuale din joc |
- | - Detectia apasarii butonului stang al mouse-ului | + | * Utilizarea transformării fereastră-poartă pentru detecția corectă a poziției cursorului, la orice dimensiune a ferestrei |
- | - Detectia pozitiei cursorului intr-una dintre casutele cu romburi disponibile (pentru care avem suficiente resurse) | + | * Romburi mai speciale (ex: romburi care generează, la un anumit interval, resurse care se pot culege; romburi care explodează; romburi care atacă mai multe linii de-odata) |
- | - Randarea rombului la pozitia cursorului, in fiecare frame, cat timp butonul ramane apasat | + | * Hexagoane mai speciale (ex: hexagoane care își schimbă culoarea la fiecare 'hit'; hexagoane mai slabe sau puternice, cu indicatori vizuali) |
- | - Detectia eliberarii (release) al aceluiasi buton de mouse (cel stang) | + | * Creșterea dificultății pe măsură ce avansați în timp |
- | - Detectia pozitiei cursorului intr-una dintre celulele libere | + | * Implementare de "niveluri" cu durate stabilite, avansarea la următorul nivel în urma terminării celui anterior |
- | - Plasarea rombului in celula | + | * Sistem de "waves" (ca în jocul original): în anumite momente ale jocului, un grup mare de hexagoane este trimis către romburi |
- | - Reducerea resurselor disponibile, in functie de costul rombului | + | * Resurse care cad din cer și se așază undeva în scenă |
+ | * Lawnmowers, ca în Plants vs Zombies | ||
+ | * Orice aduce îmbunătățiri vizuale jocului | ||
- | {{ :egc:teme:2023:drag-n-drop.gif?300 |}} | + | <note tip>Dacă vreți să funcționeze corect detecția în cazul redimensionării ferestrei de joc, se va aplica următoarea abordare: |
- | <note>In cazul in care utilizatorul apasa pe un romb pentru care nu are suficiente resurse, algoritmul se opreste la pasul 2. De asemenea, daca butonul mouse-ului este eliberat intr-o pozitie invalida (oriunde in afara unei celule libere), desenarea rombului la pozitia cursorului este oprita, iar resursele **nu** sunt consumate (practic, plasarea rombului intr-o pozitie invalida nu are niciun efect).</note> | + | Inițial, dacă începeți cu scheletul din laboratorul 3, spațiul logic coincide 1:1 cu spațiul de vizualizare, adică toate pozițiile obiectelor coincid cu coordonata respectivă de pe ecran. Marginea dreaptă a spațiului logic va coincide cu marginea dreaptă a ferestrei de joc, adică lungimea ferestrei (resolution.x), iar marginea de sus cu înălțimea ferestrei (resolution.y). |
+ | |||
+ | Dacă vrem să redimensionăm fereastra, este nevoie să aplicăm o transformare fereastră-poartă din noua rezoluție în cea inițială. Mai exact, daca notăm noua rezoluție cu coordonatele (new_width, new_height), vrem să traducem noul spațiu de coordonate, cuprins între (0, 0) - (new_width, new_height), în cel inițial (corespunzător celui logic), cuprins între (0, 0) - (1280, 720). De notat este faptul că (1280, 720) este rezoluția inițială a ecranului, și este setată în funcția //main()//. | ||
+ | |||
+ | Această transformare trebuie aplicată pentru oricare alt fragment de cod sau logică ce se folosesc de marginile ecranului.</note> | ||
+ | |||
+ | ==== Întrebări și răspunsuri ==== | ||
+ | |||
+ | Pentru întrebări vom folosi forumurile de pe moodle. Orice nu este menționat în temă este la latitudinea fiecărui student! | ||
+ | |||
+ | ==== Notare ==== | ||
+ | |||
+ | Baremul este orientativ. Fiecare asistent are o anumită libertate în evaluarea temelor (de exemplu, să dea punctaj parțial pentru implementarea incompletă a unei funcționalități sau să scadă pentru hard coding). Același lucru este valabil atât pentru funcționalitățile obligatorii, cât și pentru bonusuri. | ||
+ | |||
+ | <note warning> | ||
+ | Tema trebuie încărcată pe moodle. Pentru a fi punctată, tema trebuie prezentată la laborator. Vor exista laboratoare speciale de prezentare a temelor (care vor fi anunțate).</note> | ||
==== Indicații suplimentare ==== | ==== Indicații suplimentare ==== | ||
Line 282: | Line 290: | ||
</note> | </note> | ||
- | </hidden> |