Differences

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

Link to this comparison view

pm:prj2021:dbrigalda:2048-deluxe [2021/05/23 15:18]
ionut.ranja [Detalii despre implementare]
pm:prj2021:dbrigalda:2048-deluxe [2021/05/27 00:30] (current)
ionut.ranja [Rezultate Obţinute]
Line 35: Line 35:
 === Schema Electrică === === Schema Electrică ===
 {{ :​pm:​prj2021:​dbrigalda:​schema_eagle_2048_deluxe.png?​nolink&​725 |}} {{ :​pm:​prj2021:​dbrigalda:​schema_eagle_2048_deluxe.png?​nolink&​725 |}}
 +
 +
 +=== Hardware ===
 +Mai jos se găsesc poze cu montajul hardware realizat și cu câteva imagini din joc:
 +  * **Montaj**
 +{{ :​pm:​prj2021:​dbrigalda:​montaj_2048_deluxe.jpg?​nolink&​800 |}}
 +  * **Meniu principal**
 +{{ :​pm:​prj2021:​dbrigalda:​menu_2048_deluxe.jpg?​nolink&​350 |}}
 +  * **Highscores**
 +{{ :​pm:​prj2021:​dbrigalda:​scores_2048_deluxe.jpg?​nolink&​350 |}}
 +  * **Start Game**
 +{{ :​pm:​prj2021:​dbrigalda:​gameinit_2048_deluxe.jpg?​nolink&​350 |}}
 +  * **Game Won**
 +{{ :​pm:​prj2021:​dbrigalda:​won_2048_deluxe.jpg?​nolink&​350 |}}
 ===== Software Design ===== ===== Software Design =====
 <​note>​ <​note>​
Line 132: Line 146:
  
 În funcția de **loop** se apelează doar **DISPLAY_GameLogic** care se va ocupa de toată logica jocului. În funcția de **loop** se apelează doar **DISPLAY_GameLogic** care se va ocupa de toată logica jocului.
 +În funcția de //​GameLogic//​ se apelează diverse alte funcții după valoarea variabilei //​g_state//​. La începutul programului variabila are valoarea
 +//​quit_state//​ care indică faptul că fie ne aflăm la începutul rulării, fie că s-a apăsat butonul //quit//, iar jocul a fost resetat. În această
 +stare se citește cu **ARDUINO_MyRead** valoarea de pe axa Oy a joystick-ului. Dacă scade/​crește față de pragul de repaus, atunci se schimbă
 +valoarea variabilei //​g_option//​ fie în //scores// (joystick-ul a fost mutat în jos și a fost selectat //​Highscores//​),​ fie în //start//
 +(joystick-ul a fost mutat în sus și a fost selectat //Start Game//). În această stare se printează meniul principal cu selecția conform //​g_option//,​
 +se redă un sunet specific operației de //select// și se schimbă culoarea led-ului.
 +
 +Cât timp jocul se află în starea de //​quit_state//​ singurele butoane care pot schimba starea sunt **quit** (care duce la resetarea jocului și, implicit,
 +la întoarcerea în //​quit_state//​ cu //​g_option//​ setat pe //start//) sau **continue** care va schimba starea fie în //​score_state//,​ fie în //​game_state//​.
 +
 +În cazul //​score_state//​ se apelează funcția **DISPLAY_PrintScores** care va afișa primele 5 cele mai mari scoruri obținute în joc sub forma
 +//X. [][][] - SCORE// unde **X** reprezintă un număr de la 1 la 5, **[]** reprezintă un caracter de la A la Z iar **SCORE** reprezintă scorul jucătorului
 +identificat de cele 3 caractere. Aceste date sunt preluate din memoria EEPROM a plăcuței Arduino, iar fiecare intrare reprezintă 5 bytes (3 pentru
 +numele jucătorului și 2 pentru scor - //int// este reprezentat pe 2 bytes).
 +Din această stare se poate reveni doar la starea //​quit_state//​ apăsând **quit**.
 +
 +În cazul //​game_state//​ se citesc atât valoarea pe Oy cât și valoarea pe Ox a joystick-ului pentru a ști ce funcție trebuie apelată în continuare.
 +Este posibil să se apeleze o singură funcție la un moment dat dintre cele 4 funcții **DISPLAY_MoveUp/​Down/​Left/​Right** în funcție de valorile citite
 +pe x și pe y, apoi se va apela funcția **DISPLAY_PrintBoard** care va afișa scorul și piesele curente de pe tabla de joc. //​PrintBoard//​ apelează
 +**DISPLAY_PrintPiece** pentru a afișa centrat orice piesă indiferent de valoare folosind calcule care țin cont de valorile posibile ale pieselor și
 +de numărul de pixeli ocupați pe axa Ox a display-ului (3 pixeli + 1 pixel spațiu).
 +
 +Funcțiile //MoveXYZ// folosesc același algoritm cu modificări în funcție de direcție, pentru simplitate voi explica ce se întâmplă în cazul //MoveUp//, pentru
 +celelalte cazuri ideea este asemănătoare. //MoveUp// iterează prin fiecare linie, coloană cu coloană căutând o piesă validă (valoarea != 0). Când
 +întâlnește o astfel de piesă începe să o „tragă” în sus până la o linie de stop; aici există două cazuri:
 +  - nu există o altă piesă până la linia de stop sau, există o altă piesă, dar de valoare diferită de piesa curentă
 +    {{ :​pm:​prj2021:​dbrigalda:​caz1_2048_deluxe.png?​nolink&​800 |}}
 +  - există o altă piesă de aceeași valoare cu piesa curentă, se va executa combinarea pieselor și se va actualiza linia de stop
 +    {{ :​pm:​prj2021:​dbrigalda:​caz2_2048_deluxe.png?​nolink |}}
 +În cazul 2. se verifică dacă prin combinarea celor 2 piese s-a obținut **2048** apelând **DISPLAY_CheckIfWon**.
 +La final după ce toate piesele au fost mutate în locul corespunzător se redă un sunet specific acțiunii de //move//, led-ul își schimbă culoarea
 +și se generează o noua piesă apelând **DISPLAY_GeneratePiece**.
 +
 +//​GeneratePiece//​ iterează prin vectorul g_empty_tiles selectând doar spațiile goale (valoarea == //empty//) din tabla de joc și apoi selectează
 +aleatoriu un spațiu din cele goale în care să pună un 2 sau un 4 (90% șansă pentru 2 și 10% pentru 4). Dacă în urma generării unei piese noi nu
 +mai există niciun spațiu liber pe tabla de joc se verifică dacă jocul a fost sau nu pierdut apelând **DISPLAY_CheckIfLost**. //​CheckIfLost//​ verifică
 +dacă se poate realiza cel puțin o combinație mutând sus/​jos/​stânga/​dreapta,​ caz în care jocul nu a fost încă pierdut, altfel jocul s-a terminat și
 +jucătorul a pierdut.
 +
 +//​CheckIfWon//​ este o funcție simplă în care se verifică dacă jucătorul a obținut **2048**, caz în care starea curentă se schimbă în //​win_state//​.
 +Alte stări posibile din //​game_state//​ sunt //​pause_state//​ (a fost apăsat butonul //pause//), //​quit_state//​ (a fost apăsat butonul //quit//) sau,
 +conform celor menționate mai sus, în stare //​lose_state//​.
 +
 +Starea //​pause_state//​ afișează pe ecran un mesaj corespunzător (//GAME PAUSED!//) și setează //g_pause// pe 1, oprind scăderea scorului cu 10 puncte
 +care se întâmplă în timpul stării //​game_state//​. Această stare ascunde tabla de joc pentru a nu oferi jucătorului timp de gândire fără penalizarea
 +scorului. Din //​pause_state//​ se poate reveni în //​game_state//​ apăsând pe butonul //​continue//​ care va afișa tabla de joc de la momentul de timp anterior
 +apăsării butonului de //pause//.
 +
 +În starea //​lose_state//​ se afișează un mesaj corespunzător,​ se redă o melodie scurtă specifică înfrângerii și se setează led-ul pe roșu. În final se
 +resetează jocul apelând **DISPLAY_ResetGame** care zeroizează tabla de joc, resetează starea la //​quit_state//,​ precum și celelalte variabile la valorile
 +inițiale.
 +
 +Starea //​win_state//​ este mai specială (funcția **DISPLAY_PrintWin**). Inițial, se urmează pașii de la //​lose_state//​ afișând un mesaj corespunzător,​ melodia din //​g_win_melody//​
 +și schimbând culorile led-ului; după ce se termină această etapă, se realizează citirea valorilor de pe Ox și Oy ale joystick-ului pentru a itera
 +prin 3 caractere '​A''​A''​A'​ care pot fi schimbate în intervalul A-Z. Când jucătorul și-a ales numele, acesta va apăsa pe butonul //​continue//​
 +pentru a începe operația de înregistrare a scorului său în top. Dacă se apasă pe //quit// în loc de //​continue//,​ atunci se va reseta jocul, iar
 +scorul nu va fi înregistrat.
 +Înregistrarea scorului presupune obținerea datelor din memoria EEPROM și identificarea primului scor mai mic decât cel obținut de jucător. Dacă
 +nu există niciun scor mai mic decât cel curent, atunci nu se înregistrează,​ în caz contrar, scorul curent îl înlocuiește pe cel din top, iar restul
 +scorurilor mai mici ca acesta sunt coborâte cu o poziție (inclusiv cel înlocuit).
 +
 +După ce jucătorul a câștigat/​pierdut jocul, se realizează resetarea acestuia și întoarcerea în meniul principal. Acum acesta poate porni un joc nou
 +sau poate vedea noul top.
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
-TODO +Proiectul a ieșit în mare parte exact cum mi-am propus de la început. Din păcate am rămas foarte rapid fără pini liberi pe plăcuța Arduino și a trebuit 
-<note tip> +să renunț la ideea originală ​în care foloseam mai multe led-uri și buzzere pentru //quality of life//, dar am reușit să mă încadrez în pinii 
-Care au fost rezultatele obţinute ​în urma realizării proiectului vostru+puși la dispoziție de plăcuță. În afară de acest mic inconvenient am realizat exact tot ceea ce am dorit să fac pentru acest proiect. Personal, consider 
-</​note>​+că rezultatul final este mult mai bun față de imaginea pe care o aveam la început ;-).
  
 +== Link YouTube 4K ==
 +[[https://​www.youtube.com/​watch?​v=4oP4yuQnGWk|{{:​pm:​prj2021:​dbrigalda:​montaj_2048_deluxe.jpg?​500|}}]]
 ===== Concluzii ===== ===== Concluzii =====
-TODO+Când am început lucrul efectiv pentru proiect am avut multe momente când nu știam cu siguranță dacă ceea ce mi-am propus era în totalitate posibil 
 +de realizat, majoritatea problemelor venind din partea lucrului cu LCD-ul; am trecut prin multe iterații ale mesajelor afișate și ale reprezentării 
 +pieselor pe ecran. Am căutat foarte multe biblioteci care să ofere suport pentru un font mai mic astfel încât să încapă 4 numere pe 4 cifre pe o 
 +linie. Din păcate, majoritatea bibliotecilor disponibile pentru lucrul cu Nokia 5110 nu aveau nici măcar pe aproape la fel de multe funcționalități 
 +precum biblioteca din partea ADAFRUIT. Pe această problemă am pierdut cel mai mult timp, în final alegând să rămân la ADAFRUIT și găsind după foarte 
 +multe căutări o bibliotecă de fonturi compatibile cu //​Adafruit_GFX//​. 
 + 
 +Un alt **challenge**,​ din nefericire, a venit încă de la început când am primit piesele. Ecranul Nokia 5110 nu a venit lipit (nu mai există modelul 
 +gata lipit) și a trebuit să realizez lipirea ecranului pe coloana de pini :-(. Rezultatul putea fi mai bun, dar cel puțin funcționează cum trebuie :-). 
 + 
 +Cu toate acestea, am reușit să duc proiectul la bun sfârșit și consider că am reușit să aprofundez mai mult și mai bine noțiunile prezentate la 
 +laborator. Proiectul a fost într-adevăr o provocare foarte bună care a venit ca un suport pentru ce ne-a fost prezentat atât la curs cât și în 
 +cadrul laboratoarelor. 
 + 
 +De-a lungul procesului de realizare a proiectului am obținut motivația de a face și alte astfel de proiecte orientate pe partea de hardware. Concluzionând,​ 
 +consider că proiectul a fost un challenge bine-venit și sunt foarte satisfăcut de rezultatul final :-D.
 ===== Download ===== ===== Download =====
-TODO +<​note>​ 
-<​note ​warning+Arhiva ​cu sursele
-O arhivă (sau mai multe dacă este cazul) ​cu fişierele obţinute în urma realizării proiectuluisurse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). + 
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:prj20??:c?** sau **:pm:​prj20??:​c?:​nume_student** (dacă este cazul)**Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**.+{{:pm:prj2021:dbrigalda:ranja_ionut_335cc_pm_2048_deluxe.zip|2048_Deluxe.zip}}
 </​note>​ </​note>​
 ===== Jurnal ===== ===== Jurnal =====
Line 150: Line 244:
   * 23.04.2021 - Am creat pagina de wiki.   * 23.04.2021 - Am creat pagina de wiki.
   * 25.04.2021 - Am completat secțiunile necesare din wiki conform assignment-ului de pe moodle.   * 25.04.2021 - Am completat secțiunile necesare din wiki conform assignment-ului de pe moodle.
 +  * 07.05.2021 - Am finalizat în mare parte jocul 2048.
 +  * 13.05.2021 - Am terminat proiectul + adăugat toate componentele.
 +  * 22.05.2021 - Am făcut clean up codului sursă + coding style + completat pagina de wiki.
 +  * 23.05.2021 - Am terminat pagina de wiki.
 +  * 26.05.2021 - Am pus poze + link youtube.
 </​note>​ </​note>​
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
-TODO +=== Biblioteci externe === 
-<​note>​ +  * [[ https://​github.com/​adafruit/​Adafruit-GFX-Library|Adafruit_GFX.h ]] 
-Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse ​Software** şi **Resurse Hardware**. +  * [[ https://​github.com/​adafruit/​Adafruit-PCD8544-Nokia-5110-LCD-library|Adafruit_PCD8544.h ]] 
-</note> +  ​[[ https://​github.com/​robjen/​GFX_fonts|Font4x7Fixed.h ]] 
 +=== Resurse ​Eagle === 
 +  ​[[ https://​github.com/​adafruit/​Adafruit-Eagle-Library | adafruit.lbr ]] 
 +    ​schema Eagle pentru Arduino Uno R3 
 +  ​[[ https://​www.diymodules.org/​eagle|diy-modules.lbr ]] 
 +    ​diverse scheme Eagle compatibile cu Arduino (cum ar fi display-ul Nokia 5110) 
 +  ​[[ https://​github.com/​sparkfun/​SparkFun-Eagle-Libraries/​blob/​master/​SparkFun-LED.lbr|SparkFun-LED.lbr ]] 
 +    ​led RGB catod comun 
 +=== Bibliografie/​alte resurse === 
 +  * Laboratoarele de pe OCW 
 +  * Google ;-) 
 +  * [[ https://​ocw.cs.pub.ro/​courses/​_media/​pm/​lab/​uno.jpg?​cache=|Pinout Arduino Uno ]] 
 +  * [[ https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|Datasheet ATMEGA328P ]] 
 +  * [[ https://​app.diagrams.net/​|draw.io ]] 
 +  * [[ https://​www.autodesk.com/​products/​eagle/​free-download|Eagle ]] 
 +  * [[ https://​www.arduino.cc/​en/​software|Arduino IDE ]]
 ==== Pagina în format PDF ==== ==== Pagina în format PDF ====
 ---- ----
 <​note>​[[https://​ocw.cs.pub.ro/​courses/​pm/​prj2021/​dbrigalda/​2048-deluxe?​do=export_pdf | 2048-deluxe.pdf]]</​note>​ <​note>​[[https://​ocw.cs.pub.ro/​courses/​pm/​prj2021/​dbrigalda/​2048-deluxe?​do=export_pdf | 2048-deluxe.pdf]]</​note>​
  
pm/prj2021/dbrigalda/2048-deluxe.1621772310.txt.gz · Last modified: 2021/05/23 15:18 by ionut.ranja
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