Tetris na Arduino Uno

Typ_projektu
Arduino
Krótki opis projektu

Projekt gry Tetris na Arduino Uno to implementacja klasycznej gry Tetris przy użyciu mikrokontrolera Arduino Uno. Gra będzie wyświetlana na małym ekranie LCD i będzie sterowana za pomocą przycisków takich jak przyciski nawigacyjne. Gracz będzie mógł poruszać i obracać klockami, starając się ułożyć je w pełne rzędy, które znikną, gdy zostaną ułożone w całość. Celem projektu będzie zaprogramowanie mechaniki gry Tetris oraz obsługa interakcji z graczem przy użyciu ograniczonych zasobów mikrokontrolera Arduino Uno.

" "

Niezbędne elementy

 

1. Arduino UNO

2.Płytka do sterowania ( ESP8266)

3. Wyświetlacz LED 128x64

4. Przewód łączący Arduino z komputerem

5.Para rąk 

Opis projektu

Tworzenie gry Tetris na platformie Arduino Uno stanowi fascynujące wyzwanie, zwłaszcza ze względu na ograniczone zasoby tego mikrokontrolera oraz konieczność efektywnego zarządzania pamięcią i zasobami obliczeniowymi. Jednym z największych i najbardziej pracochłonnych problemów jest stworzenie pola do gry, czyli obszar, na którym klocki Tetrisa będą się poruszać i układać.

Pierwszym krokiem jest zdefiniowanie struktury danych reprezentującej pole do gry. 

Następnym krokiem jest implementacja funkcji odpowiedzialnej za rysowanie pola do gry na wybranym wyświetlaczu. Tutaj należy uwzględnić zarówno fizyczną wielkość wyświetlacza, jak i sposób reprezentacji stanu pola na ekranie. Może to wymagać przeliczenia współrzędnych wirtualnych na fizyczne piksele na ekranie.

Kolejnym wyzwaniem jest obsługa poruszania się klocków po polu gry oraz ich kolizji z innymi klockami lub granicami pola. Tutaj konieczne jest uwzględnienie reguł gry Tetris oraz odpowiednie zarządzanie stanem pola, tak aby klocki mogły się swobodnie poruszać, obracać i układać w rzędy.

Ważne jest także zapewnienie płynności działania gry przy ograniczonych zasobach mikrokontrolera. Może to wymagać optymalizacji kodu oraz wykorzystania odpowiednich algorytmów do zarządzania czasem i pamięcią.

Podsumowując, choć napisanie pola do gry Tetris na Arduino Uno może być trudnym i pracochłonnym zadaniem ze względu na ograniczone zasoby mikrokontrolera, odpowiednia analiza wymagań, optymalizacja kodu oraz kreatywne podejście do rozwiązywania problemów mogą prowadzić do efektywnej implementacji tej klasycznej gry na platformie sprzętowej.

https://youtube.com/shorts/S6YJNoQ42QI?si=71ITuJl1kbLnFaAt

Zdjęcia
kod programu
#include <Wire.h>


  #include <Adafruit_GFX.h>


  #include <Adafruit_SSD1306.h>


  #define WIDTH 64 // OLED display width, in pixels


  #define HEIGHT 128 // OLED display height, in pixels


  Adafruit_SSD1306 display(128, 64, &Wire, -1);


  static const unsigned char PROGMEM mantex_logo [] = {


  0x00, 0x00, 0x18, 0x06, 0x01, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3c, 0x0f, 0x03, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x3f, 0x80, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x78, 0x7f, 0xff, 0xff, 0xe1, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf8, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xff, 0xff, 0xf8, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xff, 0x0f, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xfc, 0x01, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xf0, 0x00, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xf0, 0x00, 0x7f, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x01, 0xf1, 0xe0, 0x70, 0x3f, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xe1, 0xf8, 0x3f, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xe1, 0xff, 0xff, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xe1, 0xff, 0xff, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xc1, 0xff, 0xff, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xe1, 0xe0, 0x07, 0xfc, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xe1, 0xe0, 0x01, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xe1, 0xe0, 0x00, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xe0, 0xe3, 0xf8, 0x7c, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xe0, 0x63, 0xfc, 0x7c, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x3f, 0xf1, 0xf0, 0x23, 0xfc, 0x3c, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xf8, 0x23, 0xfc, 0x3c, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0x63, 0xfc, 0x3c, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xe3, 0xfc, 0x3c, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xe3, 0xfc, 0x7c, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xe3, 0xf8, 0x7c, 0xf8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xff, 0xe1, 0xf0, 0x7c, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xff, 0xe0, 0x00, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xff, 0xe0, 0x03, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0xff, 0xf1, 0xff, 0xe0, 0x1f, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x7f, 0xf1, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf1, 0xff, 0xff, 0xff, 0xf8, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0xf0, 0xff, 0xff, 0xff, 0xf8, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x78, 0x7f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x7c, 0x1f, 0xff, 0xff, 0xc1, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x3c, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x3f, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x1f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3e, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3c, 0x0f, 0x83, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x3c, 0x0f, 0x01, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 


    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff


  };


  const char pieces_S_l[2][2][4] = {{


                                      {0, 0, 1, 1}, {0, 1, 1, 2}


                                    },


                                    {


                                      {0, 1, 1, 2}, {1, 1, 0, 0}


                                    }};


  const char pieces_S_r[2][2][4]{{


                                    {1, 1, 0, 0}, {0, 1, 1, 2}


                                  },


                                  {


                                    {0, 1, 1, 2}, {0, 0, 1, 1}


                                  }};                            


  const char pieces_L_l[4][2][4] = {{


                                    {0, 0, 0, 1}, {0, 1, 2, 2}


                                  },


                                  {


                                    {0, 1, 2, 2}, {1, 1, 1, 0}


                                  },


                                  {


                                    {0, 1, 1, 1}, {0, 0, 1, 2}


                                  },


                                  {


                                    {0, 0, 1, 2}, {1, 0, 0, 0}


                                  }};


  const char pieces_Sq[1][2][4] = {{


                                    {0, 1, 0, 1}, {0, 0, 1, 1}


                                  }};


  const char pieces_T[4][2][4] = {{


                                    {0, 0, 1, 0},{0, 1, 1, 2}


                                  },


                                  {


                                    {0, 1, 1, 2},{1, 0, 1, 1}


                                  },


                                  {


                                    {1, 0, 1, 1},{0, 1, 1, 2}


                                  },


                                  {


                                    {0, 1, 1, 2},{0, 0, 1, 0}


                                  }};


  const char pieces_l[2][2][4] = {{


                                    {0, 1, 2, 3}, {0, 0, 0, 0}


                                  },


                                  {


                                    {0, 0, 0, 0}, {0, 1, 2, 3}


                                  }};


  const short MARGIN_TOP = 19;


  const short MARGIN_LEFT = 3;


  const short SIZE = 5;


  const short TYPES = 6;
  

  int click[] = { 1047 };


  int click_duration[] = { 100 };


  int erase[] = { 2093 };


  int erase_duration[] = { 100 };


  word currentType, nextType, rotation;


  short pieceX, pieceY;


  short piece[2][4];


  int interval = 20, score;


  long timer, delayer;


  boolean grid[10][18];


  boolean b1, b2, b3;


  int left=9;


  int right=7;


  int change=10;


  int speed=8;


  void checkLines(){


    boolean full;


    for(short y = 17; y >= 0; y--){


      full = true;


      for(short x = 0; x < 10; x++){


        full = full && grid[x][y];


      }


      if(full){


        breakLine(y);


        y++;


      }


    }


  }


  void breakLine(short line){
    
     delay(100);


    for(short y = line; y >= 0; y--){


      for(short x = 0; x < 10; x++){


        grid[x][y] = grid[x][y-1];


      }


    }


    for(short x = 0; x < 10; x++){


      grid[x][0] = 0;


    }


    display.invertDisplay(true);


    delay(50);


    display.invertDisplay(false);


    score += 10;


  }


  void refresh(){


      display.clearDisplay();


      drawLayout();


      drawGrid();


      drawPiece(currentType, 0, pieceX, pieceY);


      display.display();


  }


  void drawGrid(){


    for(short x = 0; x < 10; x++)


      for(short y = 0; y < 18; y++)


        if(grid[x][y])


          display.fillRect(MARGIN_LEFT + (SIZE + 1)*x, MARGIN_TOP + (SIZE + 1)*y, SIZE, SIZE, WHITE);


  }


  boolean nextHorizontalCollision(short piece[2][4], int amount){


    for(short i = 0; i < 4; i++){


      short newX = pieceX + piece[0][i] + amount;


      if(newX > 9 || newX < 0 || grid[newX][pieceY + piece[1][i]])


        return true;


    }


    return false;


  }


  boolean nextCollision(){


    for(short i = 0; i < 4; i++){


      short y = pieceY + piece[1][i] + 1;


      short x = pieceX + piece[0][i];


      if(y > 17 || grid[x][y])


        return true;


    }


    return false;


  }


  void generate(){


    currentType = nextType;


    nextType = random(TYPES);


    if(currentType != 5)


      pieceX = random(9);


    else


      pieceX = random(7);


    pieceY = 0;


    rotation = 0;


    copyPiece(piece, currentType, rotation);


  }


  void drawPiece(short type, short rotation, short x, short y){


    for(short i = 0; i < 4; i++)


      display.fillRect(MARGIN_LEFT + (SIZE + 1)*(x + piece[0][i]), MARGIN_TOP + (SIZE + 1)*(y + piece[1][i]), SIZE, SIZE, WHITE);


  }


  void drawNextPiece(){


    short nPiece[2][4];


    copyPiece(nPiece, nextType, 0);


    for(short i = 0; i < 4; i++)


      display.fillRect(50 + 3*nPiece[0][i], 4 + 3*nPiece[1][i], 2, 2, WHITE);


  }


  void copyPiece(short piece[2][4], short type, short rotation){


    switch(type){


    case 0: //L_l


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_L_l[rotation][0][i];


        piece[1][i] = pieces_L_l[rotation][1][i];


      }


      break;


    case 1: //S_l


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_S_l[rotation][0][i];


        piece[1][i] = pieces_S_l[rotation][1][i];


      }


      break;


    case 2: //S_r


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_S_r[rotation][0][i];


        piece[1][i] = pieces_S_r[rotation][1][i];


      }


      break;


    case 3: //Sq


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_Sq[0][0][i];


        piece[1][i] = pieces_Sq[0][1][i];


      }


      break;


      case 4: //T


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_T[rotation][0][i];


        piece[1][i] = pieces_T[rotation][1][i];


      }


      break;


      case 5: //l


      for(short i = 0; i < 4; i++){


        piece[0][i] = pieces_l[rotation][0][i];


        piece[1][i] = pieces_l[rotation][1][i];


      }


      break;


    }


  }


  short getMaxRotation(short type){


    if(type == 1 || type == 2 || type == 5)


      return 2;


    else if(type == 0 || type == 4)


      return 4;


    else if(type == 3)


      return 1;


    else 


      return 0;


  }


  boolean canRotate(short rotation){


    short piece[2][4];


    copyPiece(piece, currentType, rotation);


    return !nextHorizontalCollision(piece, 0);


  }


  void drawLayout(){


    display.drawLine(0, 15, WIDTH, 15, WHITE);


    display.drawRect(0, 0, WIDTH, HEIGHT, WHITE);


    drawNextPiece();


    char text[6];


    itoa(score, text, 10);


    drawText(text, getNumberLength(score), 7, 4);


  }


  short getNumberLength(int n){


    short counter = 1;


    while(n >= 10){


      n /= 10;


      counter++;


    }


    return counter;


  }


  void drawText(char text[], short length, int x, int y){


    display.setTextSize(1);      // Normal 1:1 pixel scale


    display.setTextColor(WHITE); // Draw white text


    display.setCursor(x, y);     // Start at top-left corner


    display.cp437(true);         // Use full 256 char 'Code Page 437' font


    for(short i = 0; i < length; i++)


      display.write(text[i]);


  }


  void setup() {


    pinMode(left, INPUT_PULLUP);


    pinMode(right, INPUT_PULLUP);


    pinMode(change, INPUT_PULLUP);


    pinMode(speed, INPUT_PULLUP);


    Serial.begin(9600);


    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally


    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64


      Serial.println(F("SSD1306 allocation failed"));


      for(;;); // Don't proceed, loop forever


    }


    display.setRotation(1);


    display.clearDisplay();


    display.drawBitmap(3, 23, mantex_logo, 64, 82,  WHITE);


    display.display();


    delay(2000);


    display.clearDisplay();


    drawLayout(); 


    display.display();    


    randomSeed(analogRead(0));


    nextType = random(TYPES);


    generate();


    timer = millis();


  }


  void loop() {


    if(millis() - timer > interval){


      checkLines();


      refresh();


      if(nextCollision()){


        for(short i = 0; i < 4; i++)


          grid[pieceX + piece[0][i]][pieceY + piece[1][i]] = 1;


        generate();


      }else


        pieceY++;  


      timer = millis();


    }


    if(!digitalRead(left)){


      delay(100);


      if(b1){


        if(!nextHorizontalCollision(piece, -1)){


          pieceX--;


          refresh();


        }


        b1 = false;


      }


    }else{ 


      b1 = true;


    }


    if(!digitalRead(right)){


      delay(100);


      if(b2){


        if(!nextHorizontalCollision(piece, 1)){


          pieceX++;


          refresh();


        }


        b2 = false;


      }


    }else{ 


      b2 = true;


    }


    if(!digitalRead(speed)){


      interval = 20;


    }else{


      interval = 400;


      }


    if(!digitalRead(change)){



      delay(100);


      if(b3){


        if(rotation == getMaxRotation(currentType) - 1 && canRotate(0)){


          rotation = 0;


        }else if(canRotate(rotation + 1)){


          rotation++;


        }     


        copyPiece(piece, currentType, rotation);


        refresh(); 


        b3 = false;


        delayer = millis();


      }


    } else if(millis() - delayer > 50){ 


      b3 = true;


    }


  }
Youtube
Tagi
arduino tetris gra projekt arduino_uno