Gravity Maze handheld

Autor: Gheorghe Mara, 333CD

Introducere

Proiectul este o consola portabila cu joc de labirint controlat prin rotirea dispozitivului. Scopul jocului este ca o bila sa ajunga de la “start” la “finish” in labirint, ea fiind afectata doar de gravitatie, fara interventie directa. Labirintul se roteste odata cu dispozitivul, astfel fiind controlata, indirect, deplasarea bilei. Sunt 2 moduri principale de joc, in care labirintul este fie prestabilit, fie generat pe masura ce bila avanseaza.

Ideea mi-a venit de la jocuri similare pe telefon. Consider ca un astfel de joc se preteaza foarte bine pe un dispozitiv hand-held dedicat, mult mai bine decat jocurile clasice unde actiunea e controlata doar prin butoane.

Descriere generală

gmh_block_diagram.jpg

Descriere generală

Mediul de joc constă într-o grilă în care bila trebuie să ajungă la puncte de tip “Finish” marcate prin pătrate de 2×2. Proiectul utilizează un accelerometru MPU6050 cu un filtru trece-jos (low-pass filter) pentru a izola vectorul gravitațional, eliminând zgomotul cauzat de tremurul mâinilor, fără a necesita calibrarea giroscopului.

Moduri de joc:

Set Level: Labirint delimitat, obiectivul este atingerea unui scor prestabilit (5 puncte).

Endless Mode: Labirint generat live in partea dreapta, pe măsură ce bila avansează. Cand bila depaseste marginea ecranului, se genereaza o noua sectiune de labirint. Jucatorul se poate intoarce la ecranul anterior, dar nu poate da inapoi mai mult de o sectiune de labirint. Nu se poate “castiga”, jocul ruleaza la infinit.

Funcționalități:

Start/Cancel Game: Buton roșu.

Change Gamemode: Buton galben.

Feedback Vizual:

  • LED verde ce sta aprins timp de o secunda ori de cate ori creste scorul jucatorului
  • LED alb ce sta aprins pe toata durata ecranului “Game Won!”
Module Hardware

Unitatea de Procesare (placa Arduino Nano): Este dotata cu microprocesor ATmega328P. Acesta ruleaza codul principal, primeste date de la modulul MPU6050, gestioneaza comunicarea cu perifericele (ecran, butoane) si proceseaza algoritmii de joc.

Senzorul Inertial (MPU6050): Masoara acceleratia pe 3 axe. Detecteaza inclinarea consolei in timp real si trimite datele catre microcontroller prin protocolul I2C.

Modulul de Afisare (OLED SSD1306): Functioneaza prin interfata I2C. Ofera feedback vizual utilizatorului. Afiseaza labirintul, bila, obiectivele si ecrane informationale privind starea jocului.

Modulul de incarcare TP4056: Permite incarcarea bateriei prin USB-C.

Acumulator LiPo: Necesar pentru un dispozitiv portabil. Are capacitate de 1000mAh, permitand cateva ore de functionare pana a avea nevoie de reincarcare. Functioneazza la 3.7V si prezinta protectie PCM si NTC.

MT3608 (Step-up): Ridica tensiunea de la 3.7V (baterie) la 5V constant pentru a asigura functionarea stabila a celorlaltor componente.

Butoane: Ofera optiuni de “start/restart level”, “change gamemode” si “look down”

LED-uri controlate prin PWN: Cele 4 LED-uri albe se aprind atunci cand bila face contact cu peretii de labirint corespunzatori. Cele 3 LED-uri verzi se vor aprinde unul cate unul pe masura ce utilizatorul progreseaza in joc.

Hardware Design

Schema electrica

Lista de piese
Denumire Piesa Schema electrica
Placa de dezvoltare cu microprocesor ATmega328p https://www.arduino.cc/en/uploads/Main/ArduinoNano30Schematic.pdf
Modul Accelerometru si Giroscop cu 3 Axe MPU6050 https://www.researchgate.net/figure/Circuit-diagram-of-MPU6050_fig5_378433285
Modul incarcare LiPo TP4056 https://www.sunrom.com/media/content/86/tp4056-schematic-app.gif
Modul tensiune MT3608 https://bit.ly/mt3608-schem
Afisaj grafic OLED 128×64 GMEI12864-19 cu driver SSD1306 http://wiki.sunfounder.cc/index.php?title=OLED-SSD1306_Module

Alte componente:

  • Baterie LiPo 103040, 1000mAh, 3.7V, protectie PCM si NTC
  • Butoane
  • LED-uri albe si verzi
  • Rezistente de 220 ohmi (pentru LED-uri)
  • Intrerupator
  • Fire Dupont
  • Placa testing PCB

Software Design

Codul aplicației este dezvoltat “bare-metal” în limbajul C, utilizând direct regiștrii microcontrolerului ATmega328P pentru a asigura o execuție rapidă și o gestionare eficientă a memoriei, aspecte esențiale pentru un joc care rulează la 30 FPS.

1. Prelucrarea Datelor de la MPU6050

Sistemul determină înclinarea consolei folosind exclusiv datele de la accelerometru. Pentru a stabiliza mișcarea bilei și a elimina efectul de tremur al mâinilor, se aplică un Filtru Trece-Jos (Low-Pass Filter) care ignoră variațiile bruște. Pe baza acestor date “netezite”, se calculează direct forța și direcția în care trebuie să cadă bila pe ecran. Am renunțat complet la giroscop pentru a evita acumularea de erori în timp (“gyro drift”), obținând astfel un control constant și precis pe termen nelimitat.

2. Generarea Procedurală a Labirintului

Labirintul este stocat într-o matrice bidimensională. Lățimea dublă a matricii permite stocarea simultană a două secțiuni de ecran, facilitând scrolling-ul fluid în “Endless Mode”. Generarea se face prin algoritmul “Drunkard's Walk” (Mersul Bețivului): * Întreaga secțiune este umplută inițial cu pereți (blocuri pline). * Un generator virtual (“cârtița”) pornește dintr-un punct valid și “sapă” tuneluri. * La fiecare pas, alege aleatoriu o direcție, o lățime a tunelului și o distanță, transformând pereții în zone libere. * În modul infinit, când bila ajunge la capătul din dreapta, jumătatea dreaptă a matricii este mutată în stânga, iar o nouă jumătate este generată pe loc în dreapta.

3. Logica de Coliziune

Coliziunile sunt separate pe axele X și Y, decizie care permite bilei să “alunece” fluid de-a lungul unui perete. Dacă se detectează o coliziune doar pe axa X, viteza orizontală este anulată, dar viteza pe Y rămâne intactă, lăsând gravitația să tragă bila în jos de-a lungul obstacolului. Pentru a optimiza verificările și a nu scana tot ecranul, coordonatele în pixeli ale bilei sunt pur și simplu împărțite la dimensiunea unui bloc, aflând astfel exact indicii celulei curente din matricea labirintului.

4. Subsistemul de Afișare (Display)

Ecranul OLED comunică prin protocolul I2C. Datorită resurselor limitate de memorie RAM, nu folosim un ecran virtual complet (“frame buffer”) în memorie. În schimb, desenarea se face citind direct matricea labirintului: * Se desenează pătrate solide pentru fiecare celulă de tip perete. * Se randează markere grafice pentru destinațiile de tip “Finish”. * La final, se desenează poziția curentă a bilei peste labirint. Această abordare este rulată sincronizat cu un Timer Hardware setat precis pentru a reîmprospăta ecranul de 30 de ori pe secundă, oferind o mișcare vizuală perfect cursivă.

Rezultate Obţinute

Un joculet care te poate tine ocupat macar 5 minute, ce reacționează suficient de repede la mișcare si care incape intr-o carcasa de dimensiuni mici

Demonstratie video (mod de joc Endless Maze): https://youtu.be/hDFpc9VpoJU

Download

Jurnal

7 Mai: au fost livrate componentele comandate.

13 Mai: am conectat ecranul si giroscopul la arduino. Am descoperit ca de fapt ecranul are zone fixe de culoare; vor trebui modificate aspecte ale jocului

17 Mai: am deschis repository pe GitHub cu codul 'bare-metal' necesar interactiunii cu MPU6050 si cu ecranul

18 Mai: lipituri pentru tot circuitul de alimentare: baterie, modul de incarcare, convertor de tensiune si intrerupator

25-26 Mai: finalizare proiect

Bibliografie/Resurse

Resurse Hardware
pm/prj2026/ionut.otelea/mara.gheorghe.txt · Last modified: 2026/05/27 11:11 by mara.gheorghe
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