This is an old revision of the document!


Micro Invaders

Introducere

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.
  • 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:

  • Afișaj video: Comunicarea cu ecranul LCD se realizează prin protocolul SPI.
  • 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țiuni: Butoanele 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.

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

  • Placa Arduino Nano: Aceasta conține microcontroller-ul ATmega328P care gestionează logica jocului, afișajul pe display și citește inputurile date de joystick și butoane.
  • Ecran LCD: Pe acest ecran va fi afișat jocul “Micro Invaders” prin protocolul SPI.
  • Joystick: Acesta conține 2 potențiometre care determină poziția navei pe ecran prin maparea valorilor sale la coordonatele X și Y.
  • Push button: Folosit pentru a trage cu proiectile către inamici.

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.
  • ISR(TIMER2_COMPA_vect): Funcția de întrerupere a Timer-ului 2. Incrementează ceasul intern al jocului și rulează algoritmul de debouncing hardware pentru citirea stabilă a butonului de tras.
  • 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.
  • 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.
  • 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. 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).
  • 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.

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

pm/prj2026/ciprian.popescu0411/alexandru.stoian05.1779165243.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