This is an old revision of the document!
Micro Invaders
Introducere
Prezentarea pe scurt a proiectului:
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.
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ă.
Proiectul este, de asemenea, un exercițiu bun de optimizare și adaptare a codului unui joc video pentru un microcontroller, care are mai multe limitări (memorie redusă, clock speed scăzut, etc.).
Descriere generală
Jocul este implementat pe microcontroller-ul ATmega328P și include următoarele funcționalități:
Hardware Design
Bill of Materials
| Nr. crt. | Nume componentă | Specificații | Cantitate |
| 1 | Arduino Nano | Placă de dezvoltare bazată pe microcontroller-ul ATmega328P | 1 |
| 2 | Modul ecran LCD | Modul LCD de 1.44'' cu SPI și Controller ST7735 (128×128 px) | 1 |
| 3 | Joystick analogic | Modul joystick cu 2 potențiometre (axa X, axa Y) | 1 |
| 4 | Buton (Push button) | Microîntrerupător tactil | 1 |
| 5 | Breadboard | Placă de test 830 de puncte | 1 |
| 6 | Fire de conexiune | Fire cu izolație PVC (22AWG) | 1 set |
| 7 | Cablu USB | Pentru alimentare și programare | 1 |
Descriere componente
Pinout
| Componentă | Pin Componentă | Pin Arduino Nano | Port / Registru ATmega328P | Descriere |
| Display LCD | VCC | 5V | — | Alimentare logică ecran. |
| | GND | GND | — | Masă circuit. |
| | SCL | Pin 13 | PORTB (PB5) | Hardware SPI Clock: Sincronizează transferul rapid de date. |
| | SDA | Pin 11 | PORTB (PB3) | Hardware SPI MOSI: Linie master-to-slave pentru trimis pixeli. |
| | RES | Pin 9 | PORTB (PB1) | Reset hardware la inițializarea ecranului. |
| | DC | Pin 8 | PORTB (PB0) | Data/Command: Schimbă starea între comenzi (0) și pixeli (1). |
| | CS | Pin 10 | PORTB (PB2) | Chip Select: Activează/dezactivează magistrala SPI pentru ecran. |
| | BLK | 3.3V | — | Alimentare LED Backlight (lumină fundal). |
| Joystick | 5V | 5V | — | Alimentare potențiometre interne. |
| | GND | GND | — | Referință masă (0V). |
| | VRx | Pin A0 | ADC0 (Canal 0) | Convertor Analog-Digital: Citește poziția X (valori 0-1023). |
| | VRy | Pin A1 | ADC1 (Canal 1) | Convertor Analog-Digital: Citește poziția Y (valori 0-1023). |
| Push Button | Pin 1 | Pin 3 | PORTD (PD3) | Citire rapidă stare buton. Are Pull-up intern activat. |
| | Pin 2 | GND | — | Închide circuitul la masă când butonul este apăsat. |
Schematic
Demo
Software Design
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
Mediu de dezvoltare
Aplicația a fost dezvoltată pe VS Code cu extensia PlatformIO.
Librării şi surse 3rd-party
Pentru controlul ecranului TFT și randarea primitivelor grafice, au fost utilizate următoarele librării externe:
Adafruit_GFX Library: Oferă funcțiile de bază pentru desenarea figurilor geometrice (linii, dreptunghiuri).
Adafruit_ST7735 Library: Asigură comunicarea SPI dintre ATmega328P și modulul LCD ST7735.
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).
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.
Funcții implementate
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.
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.
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 inamicilor, am pă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.
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).
drawShip() / drawEnemy(): Funcții pentru desenarea acestor obiecte pe ecran. Pentru obținerea unor aspecte mai detaliate, am desenat “de mănă” pixel-artul navei și a inamicilor (microcontrollere, hence the name “Micro Invaders”) prin definirea unui bitmap (care este incărcat în memoria SRAM prin “PROGMEM” pentru metoda de desenare “drawBitmap()”). 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).
Rezultate Obţinute
Care au fost rezultatele obţinute în urma realizării proiectului vostru.
Concluzii
Download
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 ş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.
Jurnal
Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului.
Bibliografie/Resurse
Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe Resurse Software şi Resurse Hardware.
Export to PDF