Differences

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

Link to this comparison view

pm:prj2022:cristip:snake [2022/05/29 20:19]
adelin.stanca [Rezultate Obţinute]
pm:prj2022:cristip:snake [2022/05/30 23:36] (current)
adelin.stanca [Software Design]
Line 1: Line 1:
-====== Snake ======+====== Snake - Stanca Adelin-Nicolae 331CA ======
 Stanca Adelin-Nicolae 331CA Stanca Adelin-Nicolae 331CA
 ===== Introducere ===== ===== Introducere =====
  
-<note tip> 
 Prezentarea pe scurt a proiectului:​ Prezentarea pe scurt a proiectului:​
   * Proiectul consta in implementarea jocului Snake, pe LCD TFT 2.4 inch. Scopul jucatorului este sa isi mentina playerul cat mai mult timp in viata si sa acumuleze un scor cat mai mare, fara a se lovi de pereti si fara a se lovi de sine insusi   * Proiectul consta in implementarea jocului Snake, pe LCD TFT 2.4 inch. Scopul jucatorului este sa isi mentina playerul cat mai mult timp in viata si sa acumuleze un scor cat mai mare, fara a se lovi de pereti si fara a se lovi de sine insusi
   * Am ales acest proiect deoarce consider ca ma va ajuta sa aplic cunostintele invatate la laborator.   * Am ales acest proiect deoarce consider ca ma va ajuta sa aplic cunostintele invatate la laborator.
   * Ideea proiectului a venit din dorinta de a implementa un joc usor si cu un posibil final fericit pe un dispozitiv cu care se pot juca si copiii fara grija.   * Ideea proiectului a venit din dorinta de a implementa un joc usor si cu un posibil final fericit pe un dispozitiv cu care se pot juca si copiii fara grija.
-</​note>​ 
  
 ===== Descriere generală ===== ===== Descriere generală =====
  
-<note tip> 
 Jocul debuteaza in momentul in care este apasat de catre pen ecranul display-ului LCD TFT. La inceput este generat un punct random pe display, dupa care se va genera playerul care va urmari miscarea penului (sau ultima sa miscare). Scopul este de a atinge punctul random, moment in care se incrementeaza dimensiunea playerului si se genereaza un alt punct. Jocul se incheie in momentul in care jucatorul se loveste de sine insusi sau in momentul in care penul il dirijeaza catre un perete, moment in care se va afisa pe LCD scorul final, precum si scorul maxim. Pentru a reseta jocul, la 10 secunde de afisare a scorului, jocul se reinitializeaza,​ iar jucatorul trebuie doar sa atinga o data ecranul pentru a reincepe jocul. Jocul debuteaza in momentul in care este apasat de catre pen ecranul display-ului LCD TFT. La inceput este generat un punct random pe display, dupa care se va genera playerul care va urmari miscarea penului (sau ultima sa miscare). Scopul este de a atinge punctul random, moment in care se incrementeaza dimensiunea playerului si se genereaza un alt punct. Jocul se incheie in momentul in care jucatorul se loveste de sine insusi sau in momentul in care penul il dirijeaza catre un perete, moment in care se va afisa pe LCD scorul final, precum si scorul maxim. Pentru a reseta jocul, la 10 secunde de afisare a scorului, jocul se reinitializeaza,​ iar jucatorul trebuie doar sa atinga o data ecranul pentru a reincepe jocul.
  
-{{:​pm:​prj2022:​cristip:​schemabloc_adelin.png?600|}} +{{:​pm:​prj2022:​cristip:​schemabloc_adelin2.png?600|}}
-</​note>​+
  
 ===== Hardware Design ===== ===== Hardware Design =====
Line 98: Line 94:
 } }
 </​code>​ </​code>​
-Odata ce jocul a pornit, trec in starea inGame in care se petrec urmatoarele 3 lucruri: verificarea coliziunilor,​ preluarea inputului si updatarea valorilor si a ecranului. Mai intai, pentru verificarea coliziunilor am verificat daca jucatorul atinge '​hrana',​ caz in care se genereaza o noua '​hrana' ​si se incrementeaza dimensiunea jucatorului. Apoi, verific coliziunea cu peretii si cu sine insusi. Codul pentru tratarea coliziunilor este urmatorul:+Odata ce jocul a pornit, trec in starea inGame in care se petrec urmatoarele 3 lucruri: verificarea coliziunilor,​ preluarea inputului si updatarea valorilor si a ecranului. Mai intai, pentru verificarea coliziunilor am verificat daca jucatorul atinge '​hrana',​ caz in care se genereaza o noua '​hrana'​se incrementeaza dimensiunea jucatorului ​si i se actualizeaza scorul. Daca '​hrana'​ ii este desenata cu verde, in cazul in care o prinde, punctajul sau se va dubla. Apoi, verific coliziunea cu peretii si cu sine insusi. Codul pentru tratarea coliziunilor este urmatorul:
 <code c> <code c>
 void handleColisions() { void handleColisions() {
Line 106: Line 102:
     //increase snakeSize     //increase snakeSize
     snakeSize++;​     snakeSize++;​
-    score += 10;+    ​if(score == 50) { 
 +      score = score * 2; 
 +    } else { 
 +      ​score += 10; 
 +    }
     //​regenerate food     //​regenerate food
     spawnSnakeFood();​     spawnSnakeFood();​
Line 126: Line 126:
 } }
 </​code>​ </​code>​
-O problema cu adevarat importanta este tratarea inputului de la touchscreen. Algoritmul folosit pentru a detecta schimbarea miscarii jucatorului este urmatorul: am impartit ecranul in "​stanga"​ si "​dreapta"​ jucatorului (in care se va muta in functie de unde a fost atins ecranul), acestea fiind date de directia si sensul sau de deplasare, presupunerea fiind ca daca doreste sa isi pastreze actuala deplasare, jucatorul nu va atinge ecranul. Aceasta abordare rezolva inclusiv problema intoarcerii in sensul invers, lucru interzis in Snake dar care se poate realiza printr-o atingere dubla a ecranului.+O problema cu adevarat importanta este tratarea inputului de la touchscreen. Algoritmul folosit pentru a detecta schimbarea miscarii jucatorului este urmatorul: am impartit ecranul in "​stanga"​ si "​dreapta"​ jucatorului (in care se va muta in functie de unde a fost atins ecranul), acestea fiind date de directia si sensul sau de deplasare, presupunerea fiind ca daca doreste sa isi pastreze actuala deplasare, jucatorul nu va atinge ecranul. Aceasta abordare rezolva inclusiv problema intoarcerii in sensul invers, lucru interzis in Snake dar care se poate realiza printr-o atingere dubla a ecranului. ​Codul este urmatorul:​ 
 +<code c> 
 +void handleInput() { 
 +  TSPoint p = ts.getPoint();​ 
 +  pinMode(XM, OUTPUT); 
 +  pinMode(YP, OUTPUT); 
 +  if ((p.z > 0) && (p.z < MAXPRESSURE)) { 
 +    p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());​ 
 +    p.y = 240 - map(p.y, TS_MINY, TS_MAXY, 0, tft.height());​ 
 +    if (snakeDir == UP) { 
 +      if (p.x > snake[0].X) { 
 +        snakeDir = RIGHT; 
 +      } else if (p.x < snake[0].X) { 
 +        snakeDir = LEFT; 
 +      } else if (p.y < snake[0].Y) { 
 +        snakeDir = UP; 
 +      } 
 +    } else if (snakeDir == DOWN) { 
 +      if (p.x > snake[0].X) { 
 +        snakeDir = RIGHT; 
 +      } else if (p.x < snake[0].X) { 
 +        snakeDir = LEFT; 
 +      } else if (p.y > snake[0].X) { 
 +        snakeDir = DOWN; 
 +      } 
 +    } else if (snakeDir == RIGHT) { 
 +      if (p.y > snake[0].Y) { 
 +        snakeDir = DOWN; 
 +      } else if (p.y < snake[0].Y) { 
 +        snakeDir = UP; 
 +      } else if (p.x > snake[0].X) { 
 +        snakeDir = RIGHT; 
 +      } 
 +    } else { 
 +      if (p.y > snake[0].Y) { 
 +        snakeDir = DOWN; 
 +      } else if (p.y < snake[0].Y) { 
 +        snakeDir = UP; 
 +      } 
 +      if (p.x < snake[0].X) { 
 +        snakeDir = LEFT; 
 +      } 
 +    } 
 +  } 
 +
 +</​code>​ 
 +Partea de updatare a valorilor se face practic prin mutarea pozitiei corpului i al snake-ului catre corpul i + 1, dupa care in functie de tipul de miscare efectuata, se modifica si pozitia primului element din array care este practic cea mai importanta, celelalte fiind doar pozitia din momente de timp trecuta. Tot aici golesc spatiul unde trebuie rescris scorul. Codul este urmatorul:​ 
 +<code c> 
 +void updateValues() { 
 +  //update all body parts of the snake excpet the head 
 +  for (int i = snakeSize - 1; i >= 0; i--) { 
 +    tft.fillRect(snake[i].X,​ snake[i].Y, gameItemSize,​ gameItemSize,​ color); 
 +  } 
 +  tft.fillRect(0,​ 0, 150, 20, color); 
 + 
 +  for (int i = snakeSize - 1; i > 0; i--) { 
 +    snake[i] = snake[i - 1]; 
 +  } 
 +  //Now update the head 
 +  //move left 
 +  if (snakeDir == 0) { 
 + 
 +    snake[0].X -= gameItemSize;​ 
 +  } 
 +  //move right 
 +  else if (snakeDir == 1) { 
 + 
 +    snake[0].X += gameItemSize;​ 
 +  } 
 + 
 +  //move down 
 +  else if (snakeDir == 2) { 
 + 
 +    snake[0].Y += gameItemSize;​ 
 +  } 
 + 
 +  //move up 
 +  else if (snakeDir == 3) { 
 + 
 +    snake[0].Y -= gameItemSize;​ 
 +  } 
 +
 + 
 +</​code> ​
 In starea de gameLost, se actualizeaza scorul maxim, se reseteaza principalele variabile globale si se trece din noua in pausedGame dupa o pauza de cateva secunde. Functia **loop** este doar o apelare a uneia dintre celelalte 4 functii principale in functie de valoare state-ului, la care se adauga si un delay care scade in functie de scorul atins, fapt ce genereaza o crestere constanta a dificultatii jocului. ​ In starea de gameLost, se actualizeaza scorul maxim, se reseteaza principalele variabile globale si se trece din noua in pausedGame dupa o pauza de cateva secunde. Functia **loop** este doar o apelare a uneia dintre celelalte 4 functii principale in functie de valoare state-ului, la care se adauga si un delay care scade in functie de scorul atins, fapt ce genereaza o crestere constanta a dificultatii jocului. ​
 == Dificultati intampinate == == Dificultati intampinate ==
-Majoritatea problemelor au fost generate de faptul ca nu am mai folosit pana acum acest tip de LCD. Exista cateva biblioteci speciale dedicate acestui LCD  (precum **SPFD5408** si **TouchScreen**) care au insa cateva probleme pe care a trebuit sa le rezolv inainte sa incep implementarea,​ cum ar fi faptul ca afisarea textului se facea in oglinda. A fost nevoie sa intru si sa modific fisierul SPFD5408_Adafruit_TFT_LCD.cpp care a fost o provocare destul de mare, dat fiind ca implementarea este una destul de greaoaie. De asemenea, biblioteca TouchScreen si ecranul foloseau sisteme diferite de coordonate pentru puncte (ecranul foloseste cadranul 4, iar TouchScreen foloseste cadranul 1). Aceasta problema mi-a dat multe batai de cap tocmai in etapa de preluarea a informatiei de la input, cand jucatorul meu decidea sa o ia in sensul opus celui indicat de mine. Problema s-a rezolvat prin maparea coordonatelor X si Y si schimbarea coordonatei Y in 240 - Y.+Majoritatea problemelor au fost generate de faptul ca nu am mai folosit pana acum acest tip de LCD. Exista cateva biblioteci speciale dedicate acestui LCD  (precum **SPFD5408** si **TouchScreen**) care au insa cateva probleme pe care a trebuit sa le rezolv inainte sa incep implementarea,​ cum ar fi faptul ca afisarea textului se facea in oglinda. A fost nevoie sa intru si sa modific fisierul SPFD5408_Adafruit_TFT_LCD.cpp care a fost o provocare destul de mare, dat fiind ca implementarea este una destul de greoaie. De asemenea, biblioteca TouchScreen si ecranul foloseau sisteme diferite de coordonate pentru puncte (ecranul foloseste cadranul 4, iar TouchScreen foloseste cadranul 1). Aceasta problema mi-a dat multe batai de cap tocmai in etapa de preluarea a informatiei de la input, cand jucatorul meu decidea sa o ia in sensul opus celui indicat de mine. Problema s-a rezolvat prin maparea coordonatelor X si Y si schimbarea coordonatei Y in 240 - Y. De asemenea, faptul ca este nevoie sa curat eu de fiecare data ecranul pentru a putea sa afisez versiunea curenta a jocului este un amanunt obositor deoarece duce la creare de cod repetitiv care putea fi evitat, insa nu am gasit alta solutie automata.
 == Mediu de dezvoltare == == Mediu de dezvoltare ==
 Am folosit Arduino IDE pentru scrierea si incarcarea codului pe Arduino. Problema principala a fost lipsa functionalitatilor specifice unui IDE, precum autocomplete. ​ Am folosit Arduino IDE pentru scrierea si incarcarea codului pe Arduino. Problema principala a fost lipsa functionalitatilor specifice unui IDE, precum autocomplete. ​
Line 145: Line 228:
  
 ===== Concluzii ===== ===== Concluzii =====
 +A fost o experienta interesanta sa combin diverse tipuri de cunostinte din timpul semestrului,​ precum si cateva dintre informatiile de la EGC din semestrul anterior. Ma bucur ca am reusit sa folosesc si cateva componente hardware si sa interactionez cu ele cu succes. De asemenea, am inteles cat de important este sa cunosti bine resursele hardware disponibile pentru a putea sa scrii un cod care sa se adapteze la cerintele pe care componentele fizice le cer si sa fie si compatibil.
 ===== Download ===== ===== Download =====
  
-<note warning>​ +{{:pm:​prj2022:​cristip:​snake.pdf|}} 
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectuluisurse, scheme, etcUn fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+ 
 +{{:​pm:​prj2022:​cristip:​snake.zip|}}
  
-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**. 
-</​note>​ 
  
 ===== Jurnal ===== ===== Jurnal =====
  
-<note tip> +  * 10.05.2022 - Alegerea temei pentru ​proiect 
-Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect ​progresul proiectului+  * 15.05.2022 - Milestone 1 
-</​note>​+  * 29.05.2022 - Milestone 2
  
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
  
-<​note>​ +  * Biblioteca SPFD5408 - https://​github.com/​JoaoLopesF/​SPFD5408 
-Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. +  * Tutorial introductiv TFT LCD 2.4 inch https://​youtu.be/​D3lv0eySz8A 
-</note>+  ​Documentatie ecran TFT LCD 2.4 inch - https://​electropeak.com/​2-4-tft-lcd-display-shield 
 +  ​Introducere utilizare ecran TFT LCD 2.4 inch - https://​create.arduino.cc/​projecthub/​electropeak/​arduino-2-4-touch-screen-lcd-shield-tutorial-fe6f05 
 +  * Reparare oglindire text pe LCD - https://​youtu.be/​_mJIf1BnlU8  
  
 <​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/prj2022/cristip/snake.1653844773.txt.gz · Last modified: 2022/05/29 20:19 by adelin.stanca
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