Differences

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

Link to this comparison view

pm:prj2026:ciprian.popescu0411:alexandru.stoian05 [2026/05/19 07:34]
alexandru.stoian05 [Structuri de date]
pm:prj2026:ciprian.popescu0411:alexandru.stoian05 [2026/05/19 18:23] (current)
alexandru.stoian05 [Concluzii]
Line 3: Line 3:
  
 Prezentarea pe scurt a proiectului:​ Prezentarea pe scurt a proiectului:​
-  * Proiectul constă într-un joc interactiv inspirat de „Chicken Invaders”,​ cu afișaj pe un ecran LCD, ce poate fi controlat cu ajutorul unui joystick și al unor butoane.+  * Proiectul constă într-un joc interactiv inspirat de „Chicken Invaders”,​ cu afișaj pe un ecran LCD, ce poate fi controlat cu ajutorul unui joystick și al unui buton.
  
-  * Scopul proiectului este de a simula comportamentul unei console de jocuri de tip handheld. Acest concept presupune integrarea tuturor componentelor hardware (microcontrolerul,​ ecranul, joystick-ul și butoanele) într-un format compact și ergonomic.+  * Scopul proiectului este de a simula comportamentul unei console de jocuri de tip handheld. Acest concept presupune integrarea tuturor componentelor hardware (microcontrolerul,​ ecranul, joystick-ul și butonul) într-un format compact și ergonomic.
  
   * Ideea proiectului a pornit de la consolele pe care le-am folosit de-a lungul anilor, cum ar fi Nintendo DS sau Steam Deck, și de la un joc clasic al copilăriei mele: "​Chicken Invaders"​. Practic, mi-am propus să construiesc propria versiune a unei astfel de console, realizată de la zero și la o scară mult mai mică.   * Ideea proiectului a pornit de la consolele pe care le-am folosit de-a lungul anilor, cum ar fi Nintendo DS sau Steam Deck, și de la un joc clasic al copilăriei mele: "​Chicken Invaders"​. Practic, mi-am propus să construiesc propria versiune a unei astfel de console, realizată de la zero și la o scară mult mai mică.
Line 22: Line 22:
   * Controlul mișcării: Coordonatele navei sunt controlate prin joystick. Tensiunile potențiometrelor aferente axelor X și Y sunt convertite în valori numerice prin modulul ADC integrat pe microcontroller.   * Controlul mișcării: Coordonatele navei sunt controlate prin joystick. Tensiunile potențiometrelor aferente axelor X și Y sunt convertite în valori numerice prin modulul ADC integrat pe microcontroller.
  
-  * AcțiuniButoanele sunt conectate ​la pinii digitali ​(GPIO). Pentru a filtra zgomotul mecanic (contact bounce) fără a folosi funcții blocante precum delay(), se utilizează un algoritm de debouncing bazat pe Timere.+  * Acțiune ("​shoot"​)Butonul este conectat ​la un pin digital ​(GPIO). Pentru a filtra zgomotul mecanic (contact bounce) fără a folosi funcții blocante precum delay(), se utilizează un algoritm de debouncing bazat pe Timere.
 ===== Hardware Design ===== ===== Hardware Design =====
  
Line 75: Line 75:
  
 ===== Software Design ===== ===== Software Design =====
- 
- 
-<note tip> 
-Descrierea codului aplicaţiei (firmware): 
-  * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) 
-  * librării şi surse 3rd-party (e.g. Procyon AVRlib) 
-  * algoritmi şi structuri pe care plănuiţi să le implementaţi 
-  * (etapa 3) surse şi funcţii implementate 
-</​note>​ 
  
 ==== Mediu de dezvoltare ==== ==== Mediu de dezvoltare ====
Line 94: Line 85:
  
 ==== Structuri de date ==== ==== Structuri de date ====
-  * **struct Enemy**: Grupează variabilele de poziţie curentă (x, y), memoria grafică locală (oldX, oldY), poziţia de referinţă pentru mişcarea sinusoidală (baseY) şi un flag boolean "​alive"​. Inamicii sunt stocați într-un vector de astfel de structuri. 
  
-  * **struct ​Spark**: "​Spark-ul"​ reprezintă proiectilul lansat de către inamici. Stochează variabilele de poziție ​și memorie locală, dar și viteza ​de cădere și starea curentă (bool active).+  * **struct ​Enemy**: Grupează variabilele de poziție ​curentă (x, y)coordonatele anterioare utilizate pentru ​ștergerea grafică (oldX, oldY), poziția ​de referință pentru mișcarea sinusoidală (baseYși un indicator boolean de stare (alive). Inamicii sunt stocați într-un vector de astfel de structuri.
  
-  * **Matrice binare stocate în memoria Flash (PROGMEM)**:​ Pentru ​design-ul ​grafic al navelor ​şi inamicilor s-au utilizat vectori de tip "​unsigned char". Această ​structură ​reţine bitmap-urile în memoria Flash pentru funcția ​de redare pe ecran.+  ​* **struct Spark**: Reprezintă proiectilul lansat de inamici. Stochează variabilele de poziție (curentă și anterioară),​ viteza individuală de cădere pe axa Y (speed) și starea curentă a acestuia (active) pentru a permite reutilizarea structurii. 
 + 
 +  * **Variabilele specifice jucător**: Spre deosebire de inamici, starea jucătorului este gestionată prin variabile globale individuale,​ deoarece acesta reprezintă o entitate unică pe ecran și nu necesită gruparea într-un vector. Acestea rețin poziția curentă, coordonatele anterioare pentru ștergerea grafică, scorul acumulat și starea jocului ("​isGameOver"​). 
 + 
 +  ​* **Matrice binare stocate în memoria Flash (PROGMEM)**:​ Pentru ​designul ​grafic al navelor ​șal inamicilor s-au utilizat vectori ​constanți ​de tipul "​unsigned char". Această ​abordare ​reține bitmap-urile ​direct ​în memoria Flash, urmând a fi citite de către metoda ​de redare pe ecran "​drawBitmap()"​. 
 + 
 +==== Algoritmi implementaţi ==== 
 +  * **Algoritmul de detecţie a coliziunilor pe bază de distanţă absolută (AABB simplificat)**:​ Pentru verificarea coliziunilor (Glonţ-Inamic,​ Inamic-Jucător,​ Scânteie-Jucător),​ s-a implementat un algoritm bazat pe determinarea distanţei absolute pe axele X şi Y. Acesta verifică suprapunerea casetelor (boxes) de încadrare ale obiectelor, fiind o variantă optimizată matematic ce evită operaţiile costisitoare hardware (precum ridicarea la pătrat şi radicalul) specifice calculului distanţei Euclidiene. 
 + 
 +  * **Algoritmul de debouncing**:​ Implementat în rutina de întrerupere (ISR) a Timer-ului 2. Algoritmul monitorizează starea brută a pinului digital legat la buton, validează schimbarea de stare doar dacă aceasta rămâne stabilă timp de 20ms şi elimină zgomotul provocat de contactul mecanic. 
 + 
 +  * **Algoritmul de generare a mişcării sinusoidale**:​ Pentru a obţine traiectoria curbată şi fluidă a inamicilor pe axa Y, s-a implementat o ecuaţie de oscilaţie armonică bazată pe funcţia trigonometrică "​sin()",​ unde poziţia finală $y$ este calculată dinamic în funcţie de poziţia curentă $x$: 
 +  $$y = baseY + \sin(x \times 0.15) \times 8$$ 
 + 
 ==== Funcții implementate ==== ==== Funcții implementate ====
 +
 Logica jocului, controlul perifericelor și randarea grafică sunt gestionate prin intermediul următoarelor funcții: Logica jocului, controlul perifericelor și randarea grafică sunt gestionate prin intermediul următoarelor funcții:
  
-  * **setup()**:​ Configurarea inițială a sistemului. Inițializează regiștrii de direcție ai porturilor (DDRB, DDRD) stabilind pinii ca ieșire/​intrare,​ configurează multiplexorul ADC și registrul de control, setează Timer 2 în modul CTC pentru generarea întreruperilor la 1ms și pornește ecranul TFT afișând ecranul inițial.+  * **setup()**:​ Configurarea inițială a sistemului. Inițializează regiștrii de direcție ai porturilor (DDRB, DDRD) stabilind pinii ca ieșire/​intrare,​ configurează multiplexorul ADC și registrul de control, setează Timer 2 în modul CTC pentru generarea întreruperilor la 1ms și pornește ecranul TFTafișând ecranul inițial.
  
   * **loop()**: Nucleul asincron al programului. Rulează pe baza cadrelor de timp (gameTicks),​ executând logica jocului o dată la ~30ms pentru a asigura un framerate stabil. Gestionează citirea potențiometrelor joystick-ului și apelează funcțiile de actualizare (updateEnemies(),​ updatePlayerBullet(),​ updateSparks()). De asemenea, loop() conține și cod specific jucătorului,​ precum definirea limitelor ecranului, desenarea navei, afișarea scorului și verificarea dacă jucătorul a tras spre inamici.   * **loop()**: Nucleul asincron al programului. Rulează pe baza cadrelor de timp (gameTicks),​ executând logica jocului o dată la ~30ms pentru a asigura un framerate stabil. Gestionează citirea potențiometrelor joystick-ului și apelează funcțiile de actualizare (updateEnemies(),​ updatePlayerBullet(),​ updateSparks()). De asemenea, loop() conține și cod specific jucătorului,​ precum definirea limitelor ecranului, desenarea navei, afișarea scorului și verificarea dacă jucătorul a tras spre inamici.
Line 110: Line 114:
   * **readADC(uint8_t channel)**: Schimbă canalul multiplexorului ADC, pornește conversia hardware, așteaptă finalizarea acesteia și returnează valoarea brută (0-1023) a joystick-ului.   * **readADC(uint8_t channel)**: Schimbă canalul multiplexorului ADC, pornește conversia hardware, așteaptă finalizarea acesteia și returnează valoarea brută (0-1023) a joystick-ului.
  
-  * **spawnSpark()**:​ Caută un slot liber în vectorul de proiectile pentru a activa și lansa o „scânteie” cu viteză aleatorie de sub inamicul care trage.+  * **spawnSpark()**:​ Caută un slot liber în vectorul de proiectile pentru a activa și lansa o „scânteie” cu viteză aleatorie ​direct ​de sub inamicul care trage.
  
-  * **respawnEnemies()**:​ Activează toți cei 8 inamici și îi așează ordonat pe două rânduri la coordonatele de pornire pentru a genera un nou val de joc.+  * **respawnEnemies()**:​ Activează toți cei 8 inamici și îi așază ordonat pe două rândurila coordonatele de pornirepentru a genera un nou val de joc.
  
-  * **updateEnemies()**:​ Actualizează poziția pe ecran a inamicilor. Verifică dacă grupul a atins marginile laterale pentru a inversa direcția de mers și calculează șansa aleatorie (~2%) ca un inamic să genereze un proiectil la oricare cadru. Pentru efectul sinusoidal de mișcare al inamiciloram strat valoarea Y de bază (baseY) ​pe care am folosit-o ​în ecuația de update ​a coordonatei Y (flock[i].y). De asemenea, funcția gestionează și logica de coliziune dintre jucător și inamici.+  * **updateEnemies()**:​ Actualizează poziția pe ecran a inamicilor. Verifică dacă grupul a atins marginile laterale pentru a inversa direcția de mers și calculează șansa aleatorie (~2%) ca un inamic să genereze un proiectil la oricare cadru. Pentru efectul sinusoidal de mișcare al floteise strează ​valoarea Y de bază (baseY)care este utilizată ulterior ​în ecuația de actualizare ​a coordonatei Y (flock[i].y). De asemenea, funcția gestionează și logica de coliziune dintre jucător și inamici.
  
-  * **updatePlayerBullet() / updateSparks()**:​ Funcțiile de mișcare ale proiectilelor. Mută pozițiile pe ecran (în sus pentru jucător, în jos pentru inamici), aplică algoritmul de ștergere a pixelilor vechi, redesenează obiectele și verifică continuu coliziunile cu țintele prin calcularea distanțelor absolute (AABB).+  * **updatePlayerBullet() / updateSparks()**:​ Funcțiile ​responsabile ​de mișcarea proiectilelor. Mută pozițiile pe ecran (în sus pentru jucător, în jos pentru inamici), aplică algoritmul de ștergere a pixelilor vechi, redesenează obiectele și verifică continuu coliziunile cu țintele prin calcularea distanțelor absolute (AABB).
  
-  * **drawShip() / drawEnemy()**:​ Funcții ​pentru desenarea ​acestor obiecte pe ecran. Pentru obținerea unor aspecte mai detaliateam desenat "de mănă" ​pixel-artul navei și inamicilor (microcontrollerehence the name "Micro Invaders") prin definirea ​unui bitmap. Pe lăngă bitmap, ​am mai adăugat și alte detalii ​mai simple prin "​fillRect()"​. Pentru ștergerea sprite-urilor de pe pozițiile vechi, se desenează utilizând culoarea fundalului (ST77XX_BLACK).+  * **drawShip() / drawEnemy()**:​ Funcții ​dedicate desenării ​acestor obiecte pe ecran. Pentru ​obține un aspect detaliatdesignul ​de tip pixel-art al navei și al inamicilor (microcontrolerede unde și numele jocului, „Micro Invadersa fost creat manual ​prin definirea ​unor matrice de tip bitmap. Pe lângă aceste ​bitmap-uriau fost adăugate detalii ​grafice suplimentare folosind funcția ​"​fillRect()"​. Pentru ștergerea sprite-urilor de pe pozițiile vechi, se redesenează suprafața locală utilizând culoarea fundalului (ST77XX_BLACK).
  
   * **showGameOver()**:​ Oprește jocul, colorează ecranul în roșu, afișează scorul final și blochează execuția într-o buclă de așteptare până la o nouă apăsare a butonului.   * **showGameOver()**:​ Oprește jocul, colorează ecranul în roșu, afișează scorul final și blochează execuția într-o buclă de așteptare până la o nouă apăsare a butonului.
  
   * **resetGame()**:​ Readuce toate variabilele globale la starea inițială, curăță ecranul, resetează vectorii de proiectile și apelează funcția de respawn pentru a genera un val nou de inamici.   * **resetGame()**:​ Readuce toate variabilele globale la starea inițială, curăță ecranul, resetează vectorii de proiectile și apelează funcția de respawn pentru a genera un val nou de inamici.
 +
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
  
-<note tip> +Rezultatul final este o mini-consolă handheld construită pe un breadboard, cu un design compact. Ecranul, butonul și placa Arduino Nano sunt perfect integrate, singurele elemente care "​ies ​în afară" fiind cablul USB și joystick-ul. Pe această platformă rulează un joc arcade, interactiv și suficient de provocator
-Care au fost rezultatele obţinute ​în urma realizării proiectului vostru+ 
-</note>+Link video: https://​youtu.be/wmc5tNVgK2Y?​si=Ei97VLyqL2z5He_Q
  
 ===== Concluzii ===== ===== Concluzii =====
  
-===== Download =====+Implementarea hardware m-a provocat să mă gândesc mult mai bine la organizarea componentelor pe placă. Cu această ocazie, am învățat să folosesc letconul, fiind necesar să lipesc un header de pini pentru ecranul LCD. De asemenea, am tăiat și am dezizolat firele la dimensiuni cât mai mici pentru a obține o lizibilitate mai mare a circuitului,​ lucru care a făcut consola mult mai ușor de utilizat.
  
-<note warning>​ +Partea software mi-a plăcut în mod deosebit deoarece am văzut ce înseamnă să programezi ​un joc de la zero pe un microcontroler și pe un ecran mic, de 128x128 pixeli. Librăriile utilizate au fost de mare ajutor pentru definirea și redarea elementelor grafice, oferind multe funcționalități de bază. Pe parcursul proiectului s-a resimțit destul de tare memoria limitată a microcontrolerului ATmega328P, fiind necesar sa gestionez resursele cu atenție. Codul final ocupă ~47% din memoria FLASH și ~17% din memoria RAM.
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute ​în urma realizării proiectului:​ surse, scheme, etc. Un fişier README, un ChangeLog, ​un script ​de compilare ş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**. +În final, consider că am reușit să obțin un proiect complet, care mi-a dezvoltat atât abilitățile practice, cât și cele de programare.
-</​note>​+
  
-===== Jurnal ===== +===== Download ​=====
- +
-<note tip> +
-Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. +
-</​note>​ +
- +
-===== Bibliografie/​Resurse ​=====+
  
-<​note>​ +Link Github: https://​github.com/AlexStoianACS/​Micro-Invaders
-Listă cu documente, datasheet-uri,​ resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. +
-</note>+
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
  
pm/prj2026/ciprian.popescu0411/alexandru.stoian05.1779165259.txt.gz · Last modified: 2026/05/19 07:34 by alexandru.stoian05
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