Differences

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

Link to this comparison view

pm:prj2022:avaduva:chickeninvaders [2022/06/02 02:24]
diana.vespan
pm:prj2022:avaduva:chickeninvaders [2022/06/02 03:10] (current)
diana.vespan [Hardware Design]
Line 29: Line 29:
  
 {{ :​pm:​prj2022:​avaduva:​schematinkercadchickeninvaders.png?​nolink |}} {{ :​pm:​prj2022:​avaduva:​schematinkercadchickeninvaders.png?​nolink |}}
 +Nu am găsit un soft ce conține toate componentele proiectului meu, asa că am folosit Paint și am încercat să fac schema circuitului cât mai vizibilă.
  
  
Line 48: Line 49:
   * void Fill_Round_Rectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t radius) – desenează pe ecran un dreptunghi ce are colțurile puțin rotunjite   * void Fill_Round_Rectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t radius) – desenează pe ecran un dreptunghi ce are colțurile puțin rotunjite
  
-Funcțiile //​Fill_Circle//,​ //​Fill_Triangle//​ și //​Fill_Roung_Rectangle//​ au fost folosite pentru crearea graficii jocului(glonț,​ pasăre, navă), pe când cele destinate scrierii au servit la programarea paginii de start a jocului și a paginilor afișate în caz de victorie și înfrângere.// +Funcțiile //​Fill_Circle//,​ //​Fill_Triangle//​ și //​Fill_Roung_Rectangle//​ au fost folosite pentru crearea graficii jocului(glonț,​ pasăre, navă), pe când cele destinate scrierii au servit la programarea paginii de start a jocului și a paginilor afișate în caz de victorie și înfrângere.\\ 
-Descrierea funcțiilor implementate se poate găsi în README, la fel și codul aplicației.//+ 
 +Descrierea funcțiilor implementate
 +  * //void start_Page()//​ 
 + 
 +Această funcție crează pagina de start a jocului, pagină ce este afișată o singură 
 +data pe durata întregii sesiuni de joc. Pagina de start se poate părăsi numai dacă se apasă pe butonul de start.(butonul din mijloc) 
 + 
 +  * //void Win_Screen() și void Lose_Screen()//​ 
 + 
 +De fiecare data când un jucător câștigă/​pierde,​ se va crea una dintre paginile de mai sus. Ele pot apărea de mai multe ori în decursul unei sesiuniexistând posibilitatea de a juca din nou dacă este apăsat butonul de start. 
 + 
 +  * //void Draw_Chicken(int i, int j, int r)// 
 + 
 +Cu ajutorul acestei funcții se poate desena o singură pasăre alcătuită dintr-un cerc galben(cap),​ două cercuri negre(ochi) și un triunghi rosu(cioc). 
 + 
 +  * //void Draw_Chickens()//​ 
 + 
 +Se utilizează pentru a desena păsări pe aproape toată lățimea ecranului și jumătate din lungimea acestuia. Fiecare pasăre este asociată unei singure poziții dintr-o matrice. Această funcție desenează numai păsările ce nu au fost eliminate de către jucător, verificându-se de fiecare data valoarea corespunzătoare fiecărei poziții. În cazul în care valoarea este 1, atunci se desenează o pasăre pe locul respectiv. În caz contrar, se va lăsa un spațiu liber de dimensiunile unei păsări. Se apeleaza funcția //​Draw_Chicken//​. 
 + 
 +  * //void Draw_Fire(int id_fire)//​ 
 + 
 +Este folosită pentru desenarea unui glonț. Culoarea acestuia nu este setată în funcție, deci se poate folosi si pentru a șterge un glonț deja existent. 
 + 
 +  * //int Killed_Chicken(int id_fire)//​ 
 + 
 +Se parcurge partea ocupată de păsări exact ca în funcția //​Draw_Chickens//,​ numai că, de data aceasta se verifică dacă poziția actuală este ocupată de un inamic și dacă glonțul respectiv a reușit să-l lovească pe acesta, caz în care se decrementează numărul de păsări și se modifică valoarea din matrice aflată pe poziția inamicului ce tocmai a fost eliminat. Returnează 1 dacă pasărea a fost eliminată, iar 0 în caz contrar. 
 + 
 +  * //void Delete_Fire(int id_fire)//​ 
 + 
 +Este bazată pe același principiu ca //​Draw_Fire//,​ dar în acest caz culorile sunt deja prestabilite și se redesenează și nava spațială(glonțul porneste din vârful navei, iar aceasta se deteriorează). Se apelează funcția //​Draw_Ship//​. 
 + 
 +  * //void Draw_Ship(int shx, int shy)// 
 + 
 +Se folosește pentru a se desena nava spațială formată dintr-un dreptunghi cu colțurile rotunjite și un triunghi pe post de tun. Coordonatele se calculează pe baza poziției vârfului triunghiului. 
 + 
 +  * //void Move_Ship()//​ 
 + 
 +Are ca scop mutarea navei dintr-o parte în alta în funcție de direcția în care jucătorul decide să mute nava. Se face o desenare deasupra navei originale cu o navă de aceleași dimensiuni, dar de culoarea ecranului, după care se desenează ​la câțiva pixeli distantă o nouă navă. 
 + 
 +  * //void Launch_Fire(int id_fire)//​ 
 + 
 +Funcția se folosește pentru a simula mișcarea glonțului. Aceasta este realizată prin ștergerea și desenarea repetată de glonțuri(cercuri) cu aceeași coordonată x, dar de coordonate y diferite(y scade). Se efectuează mișcarea până când glonțul „iese” din ecran, caz în care buzzer-ul emite un sunet specific(sunt atâtea bip-uri câte vieți au mai rămas jucătorului),​ numărul de vieți scade și LED-ul roșu se aprinde, sau până când funcția //​Killed_Chicken//​ este 1, situație în care se aprinde LED-ul albastru și se aude un bip mai scurt. Funcția este făcută în așa fel încât să fie posibilă mutatea navei la acțiunea butoanelor. 
 + 
 +  * //void beep(unsigned char delayms)//​ 
 + 
 +Utilizată pentru sunetul emis de modulul buzzer. 
 + 
 +  * //void setup()// 
 + 
 +Se declară rolul LED-urilor, modulului buzzer ​și al butoanelor și se afișează pagina de start. 
 + 
 +  * //void loop()// 
 + 
 +În primul rând, ne asigurăm că LED-urile nu sunt aprinse. Citim stările butoanelor și, în funcție de acestea și alți factori decidem ce acțiune dorim să executăm. 
 + 
 +    - Se apasă butonul din mijloc și jocul încă nu a început(ne aflăm pe pagina de start): Desenăm toate păsările, dăm valori inițiale poziției navei, calculăm numărul de păsări afișate. 
 +    - Se apasă butonul din mijloc și jocul a început(ne aflăm pe pagina principală):​ Lansăm un glonț. Nu pot fi lansate două glonțuri consecutive. 
 +    - Se apasă butonul din stânga și jocul a început: Mutăm nava la stânga. 
 +    - Se apasă butonul din dreapta și jocul a început: Mutăm nava la dreapta. 
 +    - Suntem în timpul jocului și nu mai există păsări pe ecran și mai avem vieți: Se resetează matricea și numărul de găini pentru a pregăti următoarea rundă și se afișează pagina creată de //Win_Screen//​. 
 +    - Suntem în timpul jocului și mai sunt păsări pe ecran, dar nu mai avem vieți: Aceleași acțiuni ca la punctul precedent, dar se afișează pagina create de //​Lost_Screen//​. 
 + 
 + 
 +==== Cod ==== 
 + 
 +<​code>​ 
 +#include <​LCDWIKI_GUI.h>​ 
 +#include <​LCDWIKI_SPI.h>​ 
 + 
 +#define MODEL ST7735S128 
 +#define CS   A5 
 +#define CD   A3 
 +#define RST  A4 
 +#define SDA  A2 
 +#define SCK  A1 
 +#define LED  A0 
 +#define STANGA 10 
 +#define MIJLOC 9 
 +#define DREAPTA 8 
 +#define BAD 12 
 +#define GOOD 13 
 +#define BUZZER 11 
 +int start = 0; 
 +int stare_stanga = 0; 
 +int stare_mijloc = 0; 
 +int stare_dreapta = 0; 
 +int chickens = 0; 
 +int killed = 0; 
 +int chicken_matrix[4][8] = 
 +{ {1, 1, 1, 1, 1, 1, 1, 1}, 
 +  {1, 1, 1, 1, 1, 1, 1, 1}, 
 +  {1, 1, 1, 1, 1, 1, 1, 1}, 
 +  {1, 1, 1, 1, 1, 1, 1, 1}, 
 +}; 
 +int shooterX = 0; 
 +int shooterY = 0; 
 +int fireX[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
 +int fireY[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
 +int fires = -1; 
 +int dir = 0; 
 +int moveX = 4; 
 +int moveY = 0; 
 +int lives = 3; 
 + 
 +LCDWIKI_SPI mylcd(MODEL,​ CS, CD, -1, SDA, RST, SCK, LED); //​model,​cs,​dc,​sdo,​sda,​reset,​sck,​led 
 + 
 +#define BLACK   ​0x0000 
 +#define BLUE    0x20B4 
 +#define RED     ​0xF800 
 +#define GREEN   ​0x07E0 
 +#define CYAN    0x07FF 
 +#define MAGENTA 0xBD96 
 +#define YELLOW ​ 0xFFE0 
 +#define WHITE   ​0xFFFF 
 + 
 +void Draw_Chicken(int i, int j, int r) 
 +
 +  mylcd.Set_Draw_color(YELLOW);​ 
 +  mylcd.Fill_Circle(i,​ j, r); 
 +  mylcd.Set_Draw_color(BLACK);​ 
 +  mylcd.Fill_Circle(i + 2, j - 2, 1); 
 +  mylcd.Fill_Circle(i - 2, j - 2, 1); 
 +  mylcd.Set_Draw_color(RED);​ 
 +  mylcd.Fill_Triangle(i + 2, j + 2, i, j, i - 2, j + 2); 
 +
 +void Draw_Chickens() 
 +
 + 
 +  mylcd.Set_Draw_color(YELLOW);​ 
 +  int r = 6, i, j, ii = 0, jj = 0; 
 +  for (i = 2 * r - 1; i < mylcd.Get_Display_Width();​ i += 2 * r + 3) 
 +  { 
 +    for (j = 2 * r - 3; j < mylcd.Get_Display_Height() / 2; j += 2 * r + 3) 
 +    { 
 +      Serial.print(chicken_matrix[jj][ii]);​ 
 + 
 +      if (chicken_matrix[jj][ii] == 0) 
 +      { 
 +        mylcd.Set_Draw_color(BLUE);​ 
 +        mylcd.Fill_Circle(i,​ j, r); 
 +      } 
 + 
 +      else 
 +      { 
 +        Draw_Chicken(i,​ j, r); 
 +      } 
 +      // 
 + 
 +      Serial.print(jj);​ 
 +      jj = jj + 1; 
 +    } 
 +    ii = ii + 1; 
 +    jj = 0; 
 +    Serial.println(ii);​ 
 + 
 +  } 
 + 
 +
 + 
 +void Draw_Fire(int id_fire) 
 +
 +  mylcd.Set_Draw_color(RED);​ 
 +  mylcd.Fill_Circle(fireX[id_fire],​ fireY[id_fire],​ 2); 
 +
 + 
 +int Killed_Chicken(int id_fire) 
 +
 +  int r = 6, i, j, ii = 0, jj = 0; 
 +  for (i = 2 * r - 1; i < mylcd.Get_Display_Width();​ i += 2 * r + 3) 
 +  { 
 +    for (j = 2 * r - 3; j < mylcd.Get_Display_Height() / 2; j += 2 * r + 3) 
 +    { 
 +      if (chicken_matrix[jj][ii] == 1 && fireY[id_fire] <= j && fireX[id_fire] >= i - 6 && fireX[id_fire] <= i + 6) 
 +      { 
 +        chicken_matrix[jj][ii] = 0; 
 +        chickens--;​ 
 +        return 1; 
 +      } 
 +       
 +      jj = jj + 1; 
 +    } 
 +     
 +    ii = ii + 1; 
 +    jj = 0; 
 +  } 
 +   
 +  return 0; 
 +
 + 
 +void Throw_Egg() 
 +
 +  //if 
 +
 + 
 +void Delete_Fire(int id_fire) 
 +
 +  mylcd.Set_Draw_color(BLUE);​ 
 +  mylcd.Fill_Circle(fireX[id_fire],​ fireY[id_fire],​ 2); 
 +  mylcd.Set_Draw_color(MAGENTA);​ 
 +  Draw_Ship(shooterX,​ shooterY);​ 
 +
 + 
 +void Draw_Ship(int shx, int shy) 
 +
 + 
 +  mylcd.Fill_Round_Rectangle(shx - 17, shy + 7, shx + 17, shy + 14, 4); 
 +  mylcd.Fill_Triangle(shx - 7, shy + 7 , shx, shy, shx + 7, shy + 7); 
 +
 + 
 +void Move_Ship() 
 +
 +  if (dir == 1 && shooterX + 10 + moveX <= mylcd.Get_Width()) 
 +  { 
 +    mylcd.Set_Draw_color(BLUE);​ 
 +    Draw_Ship(shooterX,​ shooterY);​ 
 +    mylcd.Set_Draw_color(MAGENTA);​ 
 +    Draw_Ship(shooterX + moveX, shooterY);​ 
 +    delay(100);​ 
 +    shooterX = shooterX + moveX; 
 +  } 
 + 
 +  else if (dir == -1 && shooterX - 10 - moveX >= 0) 
 +  { 
 +    mylcd.Set_Draw_color(BLUE);​ 
 +    Draw_Ship(shooterX,​ shooterY);​ 
 +    mylcd.Set_Draw_color(MAGENTA);​ 
 +    Draw_Ship(shooterX - moveX, shooterY);​ 
 +    delay(100);​ 
 +    shooterX = shooterX - moveX; 
 +  } 
 + 
 +  else 
 +  { 
 +    return; 
 +  } 
 +
 + 
 +void Launch_Fire(int id_fire) 
 +
 +  fireX[fires] = shooterX; 
 +  fireY[fires] = shooterY; 
 + 
 +  while (fireY[fires] != 0) 
 +  { 
 +    stare_stanga = digitalRead(STANGA);​ 
 +    stare_dreapta = digitalRead(DREAPTA);​ 
 + 
 +    if (stare_stanga == HIGH && start == 1) 
 +    { 
 +      dir = -1; 
 +      Move_Ship();​ 
 +    } 
 + 
 +    if (stare_dreapta == HIGH && start == 1) 
 +    { 
 +      dir = 1; 
 +      Move_Ship();​ 
 +    } 
 + 
 +    Draw_Fire(fires);​ 
 +    killed = Killed_Chicken(fires);​ 
 +    if (killed == 1) 
 +    { 
 +      digitalWrite(GOOD,​ HIGH); 
 +      beep(50);  
 +      Delete_Fire(fires);​ 
 +      break; 
 +    } 
 + 
 +    Delete_Fire(fires);​ 
 +    fireX[fires] = fireX[fires];​ 
 +    fireY[fires] = fireY[fires] - 2; 
 +    if (fireY[fires] <= 0) 
 +    { 
 +      digitalWrite(BAD,​ HIGH); 
 +      lives--; 
 +      if(lives==2){ 
 +        beep(100);​ 
 +        delay(10);​ 
 +        beep(100);  
 +      } 
 +      if(lives==1){ 
 +        beep(100);​ 
 +      } 
 +      if(lives==0){ 
 +        beep(200);​ 
 +        beep(200);​ 
 +      } 
 +    } 
 +  } 
 + 
 +  Draw_Chickens();​ 
 +
 + 
 +void Win_Screen() 
 +
 +  mylcd.Fill_Screen(GREEN);​ 
 +  mylcd.Set_Text_colour(BLACK);​ 
 +  mylcd.Set_Text_Back_colour(GREEN);​ 
 +  mylcd.Set_Text_Size(2);​ 
 +  mylcd.Print_String("​CONGRATS! <​3",​ 14, 54); 
 +  mylcd.Set_Text_Size(1);​ 
 +  mylcd.Print_String("​Wanna play again?",​ 7, 74); 
 +  mylcd.Print_String("​Press the middle button",​ 0, 84); 
 +
 + 
 +void Lose_Screen() 
 +
 +  mylcd.Fill_Screen(RED);​ 
 +  mylcd.Set_Text_colour(BLACK);​ 
 +  mylcd.Set_Text_Back_colour(RED);​ 
 +  mylcd.Set_Text_Size(2);​ 
 +  mylcd.Print_String("​BAD LUCK", 14, 54); 
 +  mylcd.Set_Text_Size(1);​ 
 +  mylcd.Print_String("​Wanna try again?",​ 7, 74); 
 +  mylcd.Print_String("​Press the middle button",​ 0, 84); 
 +
 + 
 +void start_Page() 
 +
 +  mylcd.Fill_Screen(RED);​ 
 +  mylcd.Set_Text_colour(BLACK);​ 
 +  mylcd.Set_Text_Back_colour(RED);​ 
 +  mylcd.Set_Text_Size(3);​ 
 +  mylcd.Print_String("​START",​ 14, 54); 
 +  mylcd.Set_Text_Size(1);​ 
 +  mylcd.Print_String("​Press the middle button",​ 0, 84); 
 +
 + 
 +void beep(unsigned char delayms) 
 +{  
 +  analogWrite(BUZZER,​ 20);  
 +  delay(delayms);​ 
 +  analogWrite(BUZZER ,0);  
 +  delay(delayms);​  
 +
 +   
 +void setup() 
 +
 +  pinMode(STANGA,​ INPUT); 
 +  pinMode(MIJLOC,​ INPUT); 
 +  pinMode(DREAPTA,​ INPUT); 
 +  pinMode(BAD,​ OUTPUT); 
 +  pinMode(GOOD,​ OUTPUT); 
 +  pinMode(BUZZER,​ OUTPUT); 
 +  Serial.begin (9600); 
 +  mylcd.Init_LCD();​ 
 +  start_Page();​ 
 +
 + 
 +void loop() 
 +
 +  digitalWrite(GOOD,​ LOW); 
 +  digitalWrite(BAD,​ LOW); 
 + 
 +  stare_mijloc = digitalRead(MIJLOC);​ 
 +  stare_stanga = digitalRead(STANGA);​ 
 +  stare_dreapta = digitalRead(DREAPTA);​ 
 + 
 +  if (stare_mijloc == HIGH && start == 0) 
 +  { 
 +    start = 1; 
 +    mylcd.Fill_Screen(BLUE);​ 
 +    Draw_Chickens();​ 
 +    chickens = 4 * 8; 
 +    shooterX = mylcd.Get_Width() / 2; 
 +    shooterY = mylcd.Get_Height() - 14; 
 +    mylcd.Set_Draw_color(MAGENTA);​ 
 +    Draw_Ship(shooterX,​ shooterY);​ 
 +    delay(1000);​ 
 +    return; 
 +  } 
 + 
 +  if (stare_mijloc == HIGH && start == 1) 
 +  { 
 +    fires++; 
 +    Launch_Fire(fires);​ 
 +    fires--; 
 +  } 
 + 
 +  if (stare_stanga == HIGH && start == 1) 
 +  { 
 +    dir = -1; 
 +    Move_Ship();​ 
 +  } 
 + 
 +  if (stare_dreapta == HIGH && start == 1) 
 +  { 
 +    dir = 1; 
 +    Move_Ship();​ 
 +  } 
 + 
 +  if (chickens == 0 && start == 1 && lives > 0) 
 +  { 
 +    for(int i=0; i<10; i++) 
 +    { 
 +      beep(50); 
 +      delay(20);​ 
 +    } 
 +    start = 0; 
 +    for (int i = 0; i < 4; i++) 
 +      for (int j = 0; j < 8; j++) 
 +        chicken_matrix[i][j] = 1; 
 +    chickens = 4 * 8; 
 +    lives = 3; 
 +    delay(1000);​ 
 +    Win_Screen();​ 
 +  } 
 + 
 +  if (chickens != 0 && start == 1 && lives == 0) 
 +  { 
 +    start = 0; 
 +    for (int i = 0; i < 4; i++) 
 +      for (int j = 0; j < 8; j++) 
 +        chicken_matrix[i][j] = 1; 
 +    chickens = 4 * 8; 
 +    lives = 3; 
 +    delay(1000);​ 
 +    Lose_Screen();​ 
 +  } 
 +
 +</​code>​ 
 + 
  
  
  
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
 +
 +Circuit
 +
 +{{ :​pm:​prj2022:​avaduva:​circuitfizicchickeninvaders.png?​nolink&​500 |}}
  
 Pagină de start + Începutul jocului Pagină de start + Începutul jocului
Line 70: Line 498:
  
 ===== Concluzii ===== ===== Concluzii =====
 +
 +  *Am aprofundat logica din spatele modului de conectare al componentelor
 +  *Plănuiesc pe viitor să mai lucrez la acest joc deoarece nu am reușit să implementez absolut tot ce îmi doream.
 +  *A fost destul de dificil să găsesc o bibliotecă ce este compatibilă cu ecranul meu. Din cauza acestui fapt, nu am găsit foarte multe informații ​  utile în privința bibliotecii.
 +  *În ciuda acestui „ghinion”,​ nu regret deloc că am ales această temă, acest joc fiind probabil unul dintre preferatele mele. A fost interesant să lucrez cu ceva cu totul nou pentru mine.
 +
  
 ===== Download ===== ===== Download =====
  
-<note warning>​ +În arhiva de mai jos sunt incluse codul sursă, un README, ​scheme șpoze cu proiectul. 
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ sursescheme, etc. Un fişier ​README, ​un ChangeLog, un script de compilare şcopiere automată pe uC crează întotdeauna o impresie bună ;-).+ 
 +{{:​pm:​prj2022:​avaduva:​chicken_invaders_vespan_diana-gabriela.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 =====
Line 87: Line 520:
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
  
-<​note>​ +[[http://​www.lcdwiki.com/​1.44inch_Arduino_SPI_Module_ST7735S_SKU:​MAR1441#​How_to_use_on_Arduino]]\\ 
-Listă cu documente, datasheet-uri,​ resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**+[[https://​www.instructables.com/​Arduino-YL-44-Buzzer-module/​]]\\ 
-</note>+LCDWIKI GUI lib Manual\\ 
 +LCDWIKI SPI lib Manual\\
  
 <​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/avaduva/chickeninvaders.1654125893.txt.gz · Last modified: 2022/06/02 02:24 by diana.vespan
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