This is an old revision of the document!


Tema 1 - Duck Hunt

  • Responsabili: Anca Băluțoiu, Alex Grădinaru, Chris Brandon
  • Lansare: 31 octombrie 2022
  • Termen de predare: 13 noiembrie 2022, ora 23:59
  • Regulament: Regulament general
  • 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 de tipul Duck Hunt. Pentru inspirație, puteți testa jocul original aici: https://www.duck-hunt.org/. :)

Rațe

Construcție

Rațele sunt reprezentate de câteva primitive geometrice 2D (minimum 4: corp, aripi și cap), poziționate sugestiv. Puteți vedea o construcție propusă a raței în imaginea de mai jos, formată din 4 triunghiuri și un cerc (câte un triunghi pentru corp, aripi și cioc, și capul reprezentat de cerc).

Animare

Pentru a construi rața va fi așadar nevoie de un ansamblu de mai multe obiecte definite manual (vedeți modalitatea de definirea a pătratului din laborator) care se vor mișca împreuna, dar vor avea și animații independente. Astfel, rața:

  • Va avea o animație de zbor: va da din aripi - puteți aplica de exemplu o rotație simplă pe fiecare aripă
  • Va zbura în diverse direcții în mod unitar - tot asamblul obiectelor care compun rața se va mișca sau roti împreună

Pentru a obține aceste efecte, recomandăm folosirea de transformări ierarhice: va puteți construi o matrice de transformare a întregii rațe pe care să o aplicați fiecărei primitive în parte, după ce se aplică eventuale transformări individuale ale acestora.

Exemplu de funcționare a transformărilor ierarhice folosind OpenGL și glm (daca porniți de la laboratorul 3, se poate realiza similar folosind funcțiile definite in Transform2D):

  1. Definim o structură ierarhică de transformări (relative la o matrice de modelare părinte)
  2. Modificând o transformare pe lanțul ierarhic, aceasta se va propaga tuturor copiilor

Afișare

Ratele apar cate una pe rand pe ecran, astfel incat la un moment dat sa nu fie decat o rata prezenta in scena. In momentul in care o rata este impuscata sau evadeaza se va putea afisa urmatoarea.

Mișcare

Rațele apar în partea de jos a ecranului și își vor începe zborul pe o direcție aleatoare în plan. Continuând pe acea direcție, la un moment dat vor ajunge la marginea ecranului. În această situație, rața trebuie să se “reflecte” și să își continue drumul în direcția aferentă, asemenea unei bile de biliard care lovește marginea mesei. Dacă rața este împușcată, aceasta va cădea pe sol mișcându-se printr-o animație vertical în jos, respectiv dacă evadează va zbura în afara ecranului mișcându-se printr-o animație vertical in sus.

După un număr rezonabil de secunde, în care rața s-a ciocnit de câteva ori de marginea ecranului, aceasta va evada. Numărul de secunde va depinde de viteza cu care se mișcă rața în implementarea voastră, dar propunem să fie în jur de 3-5 secunde pentru a nu sta foarte mult o singură rață pe ecran.

Hint! Pentru a gestiona timpul, cea mai simplă variantă ar fi să țineți cont de numărul total de secunde care au trecut de la apariția ultimei rațe. Din moment ce va exista o singură rață pe ecran la orice moment de timp, această informație poate lua forma unei variabile în care se aduna deltaTimeSeconds la fiecare apel al funcției Update. În momentul în care numărul de secunde active ale raței este depășit în această variabilă, rața va tranziționa către starea de “evadat”. La apariția unei rațe noi, temporizarea reîncepe de la 0 secunde și se poate continua astfel pentru întreaga durata a jocului. De asemenea, puteți folosi și metode de măsurare a timpului prin funcții C++.

Atenție! Dacă unghiul de plecare al raței este perfect vertical sau orizontal, rața se va mișca doar pe axa respectivă. Ar fi bine să se evite unghiuri prea mici față de axele OX și OY pentru a garanta o traiectorie rezonabilă a rațelor.

Așadar, rațele au 3 moduri de mișcare:

  1. Activ: rața a apărut pe ecran și se mișcă pe o direcție, aceasta schimbându-se la momentul ciocnirii cu marginea ecranului. Din această stare, rata va tranziționa ori către starea de împușcat, ori către starea de evadat.
  2. Împușcat: rața a fost împușcată și se va mișca vertical în jos, până ajunge la marginea de jos a ecranului, moment în care dispare
  3. Evadat: rața a evadat și se va mișca vertical in sus, până ajunge la marginea de sus a ecranului, moment în care dispare

Observatie: capul ratei trebuie sa fie indreptat aproximativ spre directia de miscare :) Nu sunt permise rate care merg/zboara cu spatele.

Vieți

Jucătorul va porni inițial cu 3 vieți. În momentul în care o rață scapă (jucătorul a ratat să nimerească rața cu toate cele 3 gloanțe), acesta pierde o viață. Numărul de vieți rămase vor fi desenate pe ecran, în colțul stânga sus, sub forma unor cercuri roșii.

Gloanțe

La orice moment de timp, jucătorul trebuie să știe câte gloanțe mai are la dispoziție. Pentru asta, în colțul stânga sus (sub numărul de vieți) veți afișa și numărul de gloanțe disponibile în mod similar cu numărul de vieți, sub forma unor dreptunghiuri verzi.

Scor

Pentru fiecare rață împușcată, scorul jucătorului va crește. Acesta va fi și el reprezentat în interfața grafică în colțul dreapta-sus cu ajutorul a două dreptunghiuri:

  • Un dreptunghi wireframe, care reprezinta nivelul maxim de scor (puteti considera un nivel maxim de scor de 50 sau orice alta valoare >10)
  • Un dreptunghi solid, albastru, in interiorul celui wireframe, care reprezinta scorul curent

Gameplay

Scopul jocului este ca jucatorul sa impuste cat mai multe rate inainte sa ramana fara vieti. Jocul incepe cu un numar de vieti disponibile, dintre care se pierde cate una de fiecare data cand o rata reuseste sa scape fara sa fie impuscata.

Ratele apar cate una singura pe ecran, pe rand, fiecare dupa disparitia (prin evadarea sau impuscarea) celei anterioare. O rata va cadea pe sol cand este impuscata, si va zbura vertical in sus pentru a simboliza evadarea (sunt descrise deja detalii in sectiunile “Rate - Afisare” si “Rate - Miscare”). Ele se misca dupa regulile descrise la sectiunea “Rate - Miscare”. Dupa generarea a cate 5 rate, viteza de miscare a acestora va creste si, ca atare, dificultatea jocului va creste.

De exemplu: daca primele 5 rate se misca la o viteza v0, urmatoarele 5 ar putea avea viteza v1 = v0 + v0 / 5, urmatoarele v2 = v0 + 2 * v0 / 5 si asa mai departe, pentru a avea o modificare incrementala a dificultatii.

Trasul cu pusca

Pentru a impusca o rata, jucatorul are la dispozitie 3 gloante care se reincarca de fiecare data cand apare o noua rata. De fiecare data cand acesta face clic pe ecran, se va considera ca un glont a fost tras in acel punct pe ecran si numarul de gloante disponibile va scadea cu 1. Daca punctul de pe ecran (detalii sectiunea “Intersectia glontului cu rata”) care a fost impuscat intersecteaza rata, ea va fi considerata impuscata, scorul (detalii sectiunea “Scor”) va creste, si rata va cadea pe sol (detalii sectiunea “Rate - Miscare”).

Intersectia glontului cu rata

Avand in vedere ca ratele au o forma destul de complexa, ar fi greu de calculat exact ce puncte de pe ecran se intersecteaza cu ele. Asadar, le puteti aproxima sub forma unui dreptunghi in care este incadrata rata (similar figurii de mai jos). Pentru a calcula coordonatele colturilor acestui patrat, puteti folosi cateva notiuni de geometrie in plan, aplicate in functie de coordonatele la care se afla punctele de pe silueta ratei.

Patratul incadrator este mult mai usor de calculat daca toate coordonatele locale ale primitivelor din care este construita rata sunt calculate fata de un punct cat mai apropiat de centrul ratei (detalii sectiunea “Rata - Constructie”).

Mai multe detalii despre aproximarea coliziunilor 2D: https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

Pentru a afla daca mouse-ul se afla in interiorul dreptunghiului incadrator al ratei, trebuie facuta o conversie din coordonate de vizualizare catre coordonatele logice in care rata se plimba pe ecran. Daca va folositi de scheletul laboratorului 3, aceste 2 spatii de coordonate corespund 1:1 intrucat spatiul de desenare este limitat la rezolutia portii de afisare si se poate considera ca pozitia cursorului de mouse este si pozitia sa in coordonate logice. Altfel, va trebui aplicata o transformare similara cu cea fereastra poarta (detaliata tot in laboratorul 3), doar ca inversa. Atentie la corectia coordonatei Y.

Dupa ce cursorul si dreptunghiul se afla in acelasi spatiu de coordonate, verificarea intersectiei se rezuma la verificarea daca un punct in plan se afla intr-un dreptunghi aliniat cu axele Ox si Oy. Detaliile acestui calcul sunt lasate ca exercitiu pentru student.

Inputul de la mouse se poate trata in functia “OnMouseMove” din framework. Aceasta are 4 parametri: mouseX, mouseY, deltaX, deltaY. Primele 2 se refera la pozitia la care se afla cursorul in momentul in care se apeleaza functia, in pixeli. Numerotarea incepe din coltul stanga-sus al ferestrei de vizualizare in (0, 0). Cei 2 parametri din urma se refera la deplasarea exacta (tot in pixeli) a cursorului de la pozitia sa in frame-ul anterior pana la pozitia sa in frame-ul in care a fost apelata functia. De exemplu, daca mouse-ul s-a miscat de la pozitia (1200, 300) la pozitia (1220, 294) in intervalul de la ultimul frame pana la cel curent, vom avea urmatoarele valori: mouseX = 1220, mouseY = 294, deltaX = 20, deltaY = 294.

Atentie! Aceste valori sunt intregi, aveti grija la tipurile de date daca intentionati sa le impartiti. De asemenea, deltaX si deltaY deja sunt calculate fata de frame-ul anterior. Ca atare, nu mai este nevoie sa ne legam de deltaTimeSeconds pentru a avea o miscare independenta de frame rate.

Evadarea ratei

In momentul in care toate cele 3 gloante au fost consumate fara a fi fost impuscata rata, aceasta evadeaza. De asemenea, daca rata nu a fost impuscata timp de un numar de secunde, va evada. In ambele situatii in care rata evadeaza, jucatorul va pierde o viata (detalii sectiunea “Vieti”) si nu va primi scorul aferent ratei respective.

Funcționalități obligatorii (150 puncte)

  • Miscare/animatii rata (75p total)
    • Desenare/asamblare figura geometrica rata 15p
    • Deplasare activa (deplasare ansamblu rata si animatii aripi) 20p
    • Pozitionare si directie initiala 10p
    • Reflexii 10p
    • Impuscat 10p
    • Evadare 10p
  • Gameplay (75p total)
    • Aparitie rate, cate una pe ecran 5p
    • Incrementare viteza rate 5p
    • Temporizare evadare 5p
    • Trasul cu pusca
      • Tintire 20p
      • Coliziuni rata 20p
    • Interfata grafica (functionalitate si afisare)
      • Vieti 5p
      • Gloante 5p
      • Scor 10p

Exemple de funcționalități bonus

Orice funtionalitate suplimentara implementata (care nu este inclusa in cerintele obligatorii) poate fi considerata ca punctaj bonus daca este suficient de complexa. Functionlitatile bonus se iau in considerare doar daca functionalitatile obligatorii au fost realizate.

  • Scor variabil in functie de viteza ratei si multiplier aplicat pentru numar de rate impuscate consecutiv (killing spree). Este necesara afisarea unui element animat (de ex o forma simpla de romb care se roteste) in momentul atingerii acestui prag.
  • Dupa ce apar 5 rate, se trece la urmatorul nivel: se afiseaza pe ecran un text care ii comunica jucatorului aceasta schimbare si urmatoarele 5 rate (pana la schimbarea din nou a nivelului) se vor misca mai repede.
  • Boss fight, care apare de exemplu o data la 10 rate - e o rata mai mare care se misca mai greu si trebuie impuscata de mai multe ori.
  • Fiecare rata are o culoare aleatorie (similar cu jocul original) si isi poate schimba directia brusc/random, chiar daca nu atinge marginea ecranului (poate face de exemplu o miscare zig-zag cu temporizare aleatoare).
  • Realizarea gazonului de jos in spatele caruia apare rata, astfel incat sa nu apara brusc pe ecran de nicaieri.
  • Rate mai detaliate/complexe ca geometrie.
  • Crosshair pe mouse si eventual o pusca/arma animata in functie de pozitia cursorului pe ecran (sa fie indreptata/rotita spre cursor).
  • Sistem de tragere animat (gloante vizibile, o mica animatie in momentul in care se atinge rata - de ex sar niste ‘pene’ aproximate in directii aleatorii).
  • Rațe “speciale” care dau jucătorului anumite abilități (o viață extra, un glonț extra, toate rațele se vor mișca foarte încet pentru câteva secunde). Fiecare astfel de rață va avea o culoare specifică power up-ului pe care îl acordă si va exista un indicator de timp care arata cat timp mai dureaza acea abilitate (de ex o bara similara cu cea de scor, care scade in timp si dispare cand nu mai e valabila abilitatea).
  • Animație complexa când moare rata.
  • Posibilitatea de a avea mai multe rate pe ecran in acealasi timp si sistem de gestiune a gloantelor corespunzator/imbunatatit pentru mai multe rate.

Î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 anumita libertate in evaluarea temelor (de exemplu, sa dea punctaj partial pentru implementarea incompleta a unei functionalitati sau sa scada pentru hard coding). Acelasi lucru este valabil atat pentru functionalitatile obligatorii, cat si pentru bonusuri.

Tema trebuie incarcata pe moodle. Pentru a fi punctata, tema trebuie prezentata la laborator. Vor exista laboratoare speciale de prezentare a temelor (care vor fi anuntate).

Indicații suplimentare

Tema va fi implementata in OpenGL si C++. Este indicat sa folositi framework-ul si Visual Studio.

Pentru implementarea temei, in folderul src/lab_m1 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_m1 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_m1/Tema1/Tema1.h”

Arhivarea Proiectului

  • in mod normal arhiva trebuie sa contina toate resursele necesare compilarii si rularii
  • inainte de a face arhiva asigurati-va ca ati curatat proiectul Visual Studio:
    • click dreapta pe proiect in Solution ExplorerClean Solution
    • si stergeti folderul /build/.vs (daca nu il vedeti, este posibil sa fie ascuns)
  • SAU stergeti complet folderul /build
  • in cazul in care arhiva tot depaseste limita de 50MB (nu ar trebui), puteti sa stergeti si folderul /deps sau /assets intrucat se pot adauga la testare. Nu este recomandat sa faceti acest lucru intrucat ingreuneaza mult testarea in cazul in care versiunea curenta a librariilor/resurselor difera de versiunea utilizata la momentul scrierii temei.

egc/teme/2022/01.1667154810.txt.gz · Last modified: 2022/10/30 20:33 by maria_anca.balutoiu
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