This shows you the differences between two versions of the page.
|
pm:prj2025:rnedelcu:ioan_alexandru.popa [2025/05/28 15:41] ioan_alexandru.popa |
pm:prj2025:rnedelcu:ioan_alexandru.popa [2025/05/28 17:05] (current) ioan_alexandru.popa |
||
|---|---|---|---|
| Line 85: | Line 85: | ||
| * Simpla folosire a Arduino IDE și a convențiilor sale de compilare mi se părea un regres mare, fiind obișnuit cu mediile de dezvoltare software unde dependențele pot fi specificate clar într-un fișier aferent, fără să te bazezi pe un mecanism de forma //alege biblioteca cutare din interfața IDE-ului și descarc-o într-un folder global tuturor proiectelor//. | * Simpla folosire a Arduino IDE și a convențiilor sale de compilare mi se părea un regres mare, fiind obișnuit cu mediile de dezvoltare software unde dependențele pot fi specificate clar într-un fișier aferent, fără să te bazezi pe un mecanism de forma //alege biblioteca cutare din interfața IDE-ului și descarc-o într-un folder global tuturor proiectelor//. | ||
| * La un moment dat al dezvoltării proiectului s-a manifestat o eroare a platformei implicite PlatformIO pentru Raspberry Pi Pico ce m-a chinuit mult timp (mi se tot apelau interrupt-urile dacă dădeam ''analogWrite'' sau ceva de genul), până când am încercat platforma lui maxgerhardt și m-am convins că ea e de folosit cănd folosim PlatformIO pe Raspberry Pi Pico. | * La un moment dat al dezvoltării proiectului s-a manifestat o eroare a platformei implicite PlatformIO pentru Raspberry Pi Pico ce m-a chinuit mult timp (mi se tot apelau interrupt-urile dacă dădeam ''analogWrite'' sau ceva de genul), până când am încercat platforma lui maxgerhardt și m-am convins că ea e de folosit cănd folosim PlatformIO pe Raspberry Pi Pico. | ||
| - | * Pentru ideea de scriere a jocurilor într-un limbaj dinamic am încercat inițial cu [[https://github.com/lua/lua|Lua]], dar inegrarea bibliotecii în proiect era dificilă. Am găsit Duktape ca bibliotecă ușor integrabilă (am pus fișierul (unul singur) ''.c'' și cele ''.h'' în directorul ''lib'' al codului sursă), într-adevăr, pentru JavaScript - [[https://compat-table.github.io/compat-table/es6/|o versiune mai veche a limbajului]] fără anumite caracteristici moderne cu care eram obișnuit din lucrul meu anterior cu JavaScript (''let'', arrow functions), dar pentru scopul proiectului este suficient. | + | * Pentru ideea de scriere a jocurilor într-un limbaj dinamic am încercat inițial cu [[https://github.com/lua/lua|Lua]], dar inegrarea bibliotecii în proiect era dificilă. Am găsit Duktape ca bibliotecă ușor integrabilă (am pus fișierul (unul singur) ''.c'' și cele ''.h'' în directorul ''lib'' al codului sursă); într-adevăr, pentru JavaScript - [[https://compat-table.github.io/compat-table/es6/|o versiune mai veche a limbajului]] fără anumite caracteristici moderne cu care eram obișnuit din lucrul meu anterior cu JavaScript (''let'', arrow functions), dar pentru scopul proiectului este suficient. |
| * Aveam dorința de a scrie codul JavaScript al jocurilor în fișiere ''.js'', care să fie incluse ulterior în codul C++ ca șiruri de caractere și încărcate în interpretor. Am găsit ca soluție pentru acest lucru funcționalitatea PlatformIO de imagini ale sistemului de fișiere LittleFS cu fișierele aflate în directorul ''data'', unde am pus fișierele ''.js'' cu logica jocurilor. Un dezavantaj al acestei abordări este că încărcarea codului pe plăcuță se face în 2 pași (în funcție de ce parte de cod s-a actualizat): | * Aveam dorința de a scrie codul JavaScript al jocurilor în fișiere ''.js'', care să fie incluse ulterior în codul C++ ca șiruri de caractere și încărcate în interpretor. Am găsit ca soluție pentru acest lucru funcționalitatea PlatformIO de imagini ale sistemului de fișiere LittleFS cu fișierele aflate în directorul ''data'', unde am pus fișierele ''.js'' cu logica jocurilor. Un dezavantaj al acestei abordări este că încărcarea codului pe plăcuță se face în 2 pași (în funcție de ce parte de cod s-a actualizat): | ||
| * ''Upload'' pentru încărcarea codului C++ compilat | * ''Upload'' pentru încărcarea codului C++ compilat | ||
| Line 94: | Line 94: | ||
| * Snake | * Snake | ||
| + | * 4 vieți | ||
| + | * Controlează șarpele cu joystick-ul în direcția pe care vrei să o ia | ||
| + | * Se ignoră comenzile de înapoi | ||
| + | * Cu butonul acțiune se merge mai departe în direcția capului | ||
| + | * Șarpele se mișcă automat după ce jucătorul l-a mutat manual o dată | ||
| + | * Șarpele crește când mănâncă mâncarea disponibilă în nivel, moment în care se generează un nou punct cu mâncarea | ||
| + | * Șarpele moare când se lovește de margini sau de el însuși | ||
| * Drive | * Drive | ||
| + | * 4 vieți | ||
| + | * Controlezi o mașinuță ce trebuie să se ferească de zidurile de pe marginile drumului | ||
| + | * Stânga-dreapta | ||
| + | * Mașinuța merge înainte la un interval de timp sau la joystick înainte | ||
| + | * Zidurile se schimbă periodic | ||
| + | |||
| + | Meniul principal este, de asemenea implementat ca script JavaScript. | ||
| ==== Interfața JavaScript ==== | ==== Interfața JavaScript ==== | ||
| - | Jocurile trebuie să implementeze următoarele funcții, ce se apelează în cardul unor evenimente relevante în joc. | + | Jocurile au acces la 2 ecrane virtuale, cu celule indexate de la 0: |
| + | * Principal de 10x20 (pentru acțiunea jocului) | ||
| + | * Secundar de 4x4 (pentru afișarea unor detalii suplimentare, ex. numărul de vieți) | ||
| + | |||
| + | Ecranele au 3 culori: | ||
| + | * 0 = stins | ||
| + | * 1 = aprins (negru) | ||
| + | * 2 = parțial aprins (gri) | ||
| + | |||
| + | Există un sistem de tick-uri care se execută după fiecare ''TICK_TIME'' (500) milisecunde | ||
| + | |||
| + | Runtime-ul implementează următoarele funcții: | ||
| + | * ''brickVibrate(intensity: number, duration: number)'' - Motorul cu vibrații va vibra la intensitatea ''intensity'' (număr între 0 și 255; 255 = maxim, 180 = valoare intermediară bună) timp de ''duration'' milisecunde. | ||
| + | * ''brickMainDraw(x: number, y: number, color: number)'' - desenează pe ecranul principal la celula specificată (linia ''y'', coloana ''x'') culoarea specificată | ||
| + | * ''brickSecondaryDraw(x: number, y: number, color: number)'' - desenează pe ecranul principal la celula specificată (linia ''y'', coloana ''x'') culoarea specificată | ||
| + | * ''brickTickReset()'' - nu se va mai executa tick-ul următor, se va executa peste ''TICK_TIME'' milisecunde (dacă nu se mai apelează ''brickTickReset()'' încă o dată până atunci) | ||
| + | * ''brickGameOver(x: number, y: number, noRestart: boolean)'' - inițializează ecranul de game over cu „X”-ul în punctul specificat (linia ''y'', coloana ''x'') și vibrație maximă. După un timp se ve reporni jocul în același context (variabilele globale sunt păstrate, dar se va rula ''handleInit()'') dacă ''noRestart'' e ''false'', altfel se va reseta consola la meniul principal. | ||
| + | * ''brickLoad(gamePath: string)'' - încarcă jocul din calea specificată din sistemul de fișiere LittelFS încărcat pe plăcuță, resetând contextul JavaScript. Un API „intern”, nu e intenționată folosirea lui în jocuri, doar în meniul de start. | ||
| + | |||
| + | Jocurile trebuie să implementeze următoarele funcții, ce se apelează în cardul unor evenimente relevante în joc: | ||
| + | |||
| + | * ''handleInit()'' - se apelează inițializarea jocului la pornire sau după o pierdere de viață prin ''brickGameOver(x, y, false)''. Aici se inițializează variabilele ce indică starea vieții curente. Inițializarea numărului de vieți sau alte chestii ce se păstrează de-a lungul vieților se face direct în corpul scriptului. | ||
| + | * ''handleTick()'' - se apelează la fiecare tick - bun pentru aplicarea mișcărilor automate etc. | ||
| + | * ''handleAction()'' - se apelează la apăsarea butonului acțiune (cel mai din dreapta). | ||
| + | * ''handleUp()'' - se apelează la deplasarea în sus a joystick-ului. | ||
| + | * ''handleLeft()'' - se apelează la deplasarea în stânga a joystick-ului. | ||
| + | * ''handleRight()'' - se apelează la deplasarea în dreapta a joystick-ului. | ||
| + | * ''handleDown()'' - se apelează la deplasarea în jos a joystick-ului. | ||
| + | |||
| + | Aceste funcții nu trebuie să dureze mult, doar cât trebuie pentru a administra evenimentul în cauză. | ||
| + | Pentru a încuraja bunele practici, există un watchdog ce nu poate fi resetat de codul Javascript, doar de alte timere interne, care să reseteze consola dacă JavaScriptul durează prea mult. | ||
| ===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
| Line 116: | Line 160: | ||
| {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:hardwarebun1.jpg?400|}} | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:hardwarebun1.jpg?400|}} | ||
| {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:hardwarebun2.jpg?400|}} | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:hardwarebun2.jpg?400|}} | ||
| + | |||
| + | ==== Software ==== | ||
| + | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:20250528_165839.jpg?400|}} | ||
| + | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:20250528_165833.jpg?400|}} | ||
| + | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:20250528_165851.jpg?400|}} | ||
| + | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:20250528_165854.jpg?400|}} | ||
| + | {{:pm:prj2025:rnedelcu:ioan_alexandru.popa:20250528_165921.jpg?400|}} | ||
| ===== Concluzii ===== | ===== Concluzii ===== | ||