Differences

This shows you the differences between two versions of the page.

Link to this comparison view

egc:teme:2023:01 [2023/10/29 19:57]
andrei.lambru
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:​** Andrei Voicu, Mihnea Tudor, Anca Cristea, Cristian Lambru   * **Responsabili:​** Andrei Voicu, Mihnea Tudor, Anca Cristea, Cristian Lambru
Line 18: Line 17:
  
 <note tip> <note tip>
-Implementarea din demo-ul pus la dispoziție nu va mai identifica ​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 :) .+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>​ </​note>​
  
Line 37: Line 36:
 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 49: Line 48:
 === 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 să 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 ===
Line 80: Line 83:
   * Comportament de joc (50p in total)   * Comportament de joc (50p in total)
     * Detecția selecției unei celule de joc prin apăsarea butonului stânga al mouse-ului și plasarea unui romb în celulă 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
-    * Apariție inamici la intervale ​regulate ​5p+    * Apariție inamici la intervale ​aleatoare ​5p
     * Detecția faptului că un inamic a traversat în totalitate o linie 5p     * Detecția faptului că un inamic a traversat în totalitate o linie 5p
     * Apariție proiectil de lânga un romb în momentul în care există inamic pe linie 10p     * Apariție proiectil de lânga un romb în momentul în care există inamic pe linie 10p
Line 107: Line 110:
     * Detecția coliziunii proiectil-inamic,​ doar în situația în care proiectilul are aceeași 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
  
-==== Detalii de implementare ====+===== Detalii de implementare ​=====
  
 ==== Construcție elemente vizuale ==== ==== Construcție elemente vizuale ====
Line 182: Line 185:
 Î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. Î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.
  
-=== Detecție coliziuni === +==== Detecție coliziuni ====
- +
-==== Detecție coliziuni ​între 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 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.
Line 204: Line 205:
 <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 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>​
  
-==== Detecție coliziuni între obiecte și cursor ​====+==== Interacțiune jucător ​====
  
 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:​ 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   * colectarea de resurse, prin apăsarea unui buton pe mouse
   * plasarea romburilor în celule, prin intermediul drag & drop   * plasarea romburilor în celule, prin intermediul drag & drop
 +  * ștergerea romburilor din celule
  
 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. 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.
Line 216: Line 218:
 <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>​ <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 î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 ​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 apăsarea unui buton de la mouse, când cursorul se află în interiorul unui obiect, trebuie să: Pentru a verifica apăsarea unui buton de la mouse, când cursorul se află în interiorul unui obiect, trebuie să:
-  - Traducem ​coordonatele cursorului de pe ecran în coordonatele scenei de joc+  - Transformăm ​coordonatele cursorului de pe ecran în coordonatele scenei de joc
   - Calculăm marginile dreptunghiului,​ în urma eventualelor aplicări de translații și scalări   - Calculăm marginile dreptunghiului,​ în urma eventualelor aplicări de translații și scalări
   - Verificăm dacă poziția cursorului este între marginile dreptunghiului   - Verificăm dacă poziția cursorului este între marginile dreptunghiului
  
-<note tip>Daca vreti sa functioneze corect detectia si in cazul redimensionarii ferestrei de joc, lucrurile se complica putin.+==== Drag & drop ====
  
-Initialdaca incepeti ​cu scheletul ​din laboratorul 3spatiul logic coincide 1:1 cu spatiul de vizualizare,​ adica toate pozitiile obiectelor coincid cu coordonata respectiva de pe ecranMarginea 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 plasa un romb pe una dintre celuleacesta trebuie selectat ​cu mouse-ul ​din bara romburilor disponibiledupă care trebuie tras deasupra unei celule **libere**O celulă liberă este o celulă care nu este deja ocupată ​de un romb.
  
-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. +Pentru a crea acest mecanism, trebuie ​realizați următorii pași
- +  - Detecția apăsării ​butonului ​stâng ​al mouse-ului 
-Aceasta transformare trebuie aplicata pentru oricare alt fragment de cod sau logica ce se folosesc de marginile ecranului.</​note>​ +  - 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 
-=== Drag & drop === +  - Detecția eliberării ​(release) al aceluiași ​buton de mouse (cel stâng
- +  - Detecția poziției ​cursorului ​într-una dintre celulele libere 
-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. +  - Plasarea rombului ​în celulă 
- +  - Reducerea resurselor disponibile, ​în funcție ​de costul rombului
-Pentru a crea acest mecanism, trebuie ​realizati urmatorii pasi+
-  - Detectia apasarii ​butonului ​stang al mouse-ului +
-  - Detectia pozitiei ​cursorului ​intr-una dintre ​casutele ​cu romburi disponibile (pentru care avem suficiente resurse) +
-  - Randarea rombului la pozitia ​cursorului, ​in fiecare frame, ​cat timp butonul ​ramane apasat +
-  - Detectia eliberarii ​(release) al aceluiasi ​buton de mouse (cel stang+
-  - Detectia pozitiei ​cursorului ​intr-una dintre celulele libere +
-  - Plasarea rombului ​in celula +
-  - Reducerea resurselor disponibile, ​in functie ​de costul rombului+
  
 {{ :​egc:​teme:​2023:​drag-n-drop.gif?​300 |}} {{ :​egc:​teme:​2023:​drag-n-drop.gif?​300 |}}
  
-<​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>​+<​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>​
  
 ==== Exemple de funcționalități bonus ==== ==== Exemple de funcționalități bonus ====
Line 259: Line 253:
   * Implementare de "​niveluri"​ cu durate stabilite, avansarea la următorul nivel în urma terminării celui anterior   * Implementare de "​niveluri"​ cu durate stabilite, avansarea la următorul nivel în urma terminării celui anterior
   * Sistem de "​waves"​ (ca în jocul original): în anumite momente ale jocului, un grup mare de hexagoane este trimis către romburi   * Sistem de "​waves"​ (ca în jocul original): în anumite momente ale jocului, un grup mare de hexagoane este trimis către romburi
-  * Resurse care cad din cer și se așază undeva în scena +  * Resurse care cad din cer și se așază undeva în scenă 
-  * Lawnmowers, ca în plants ​vs zombies +  * Lawnmowers, ca în Plants ​vs Zombies 
-  * Orice aduce imbunatatiri ​vizuale jocului+  * Orice aduce îmbunătățiri ​vizuale jocului 
 + 
 +<note tip>​Dacă vreți să funcționeze corect detecția în cazul redimensionării ferestrei de joc, se va aplica următoarea abordare: 
 + 
 +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 ==== ==== Întrebări și răspunsuri ====
Line 288: Line 290:
 </​note>​ </​note>​
  
-</​hidden>​ 
egc/teme/2023/01.1698602247.txt.gz · Last modified: 2023/10/29 19:57 by andrei.lambru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0