Game Tetris on LPC 1114ETF with Banggood display and Joystick

Dependencies:   SPI_TFT_ILI9341 TFT_fonts mbed

Revision:
0:71c49df3f7cd
diff -r 000000000000 -r 71c49df3f7cd main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jun 18 20:04:05 2018 +0000
@@ -0,0 +1,497 @@
+#include "mbed.h"
+# include "SPI_TFT_ILI9341.h"
+# include "Arial12x12.h"
+# define dp23 P0_0
+#define GORE 0
+#define DOLJE 1
+#define LIJEVO 2
+#define DESNO 3
+#define CENTAR 4
+SPI_TFT_ILI9341 TFT ( dp2 , dp1 , dp6 , dp24 , dp23 , dp25 ,"TFT");
+// mosi , miso , sclk , cs , reset , dc
+AnalogIn vRx(dp11), vRy(dp10);
+DigitalIn sw(dp9);
+Timer swDbnc;
+int ocitajDzojstik()
+{
+    double XX = vRx, YY = vRy;
+    if(XX < 0.333) return LIJEVO;
+    else if(XX > 0.666) return DESNO;
+    else if(YY < 0.333) return GORE;
+    else if(YY > 0.666) return DOLJE;
+    else return CENTAR;
+}
+int cosakX = 80, cosakY = 20, size = 14;
+int matrix[10][20] = {};
+float dilej = 0.5;
+bool kraj = false;
+int highScore = 0, score = 0, lines = 0;
+short Xovi[7][4] = {2,1,0,3, 1,0,2,2, 1,0,2,0, 0,1,0,1, 1,0,2,1, 1,1,2,0, 1,0,1,2};
+short Yoni[7][4] = {0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,1,1, 0,0,0,1, 1,0,0,1, 1,0,0,1};
+int nizBoja[] =   {Blue, Red, Orange, Yellow, Green, Purple, Maroon};
+void strcpy(short a[], short b[])
+{
+    for(int i = 0; i < 4; i++)
+        a[i] = b[i];
+}
+int sljedeca = 0;
+class Figura{
+    public:
+    int PX, PY;
+    short X[4], Y[4];
+    int Boja;
+    Figura()
+    {
+        PX = 3;
+        PY = 0;
+        int rnd = sljedeca;
+        strcpy(X, Xovi[rnd]);
+        strcpy(Y, Yoni[rnd]);
+        Boja = nizBoja[rnd];
+        sljedeca = rand() % 7;
+    }
+    Figura(int n)
+    {
+        PX = 3;
+        PY = 0;
+        int rnd = n;
+        strcpy(X, Xovi[rnd]);
+        strcpy(Y, Yoni[rnd]);
+        Boja = nizBoja[rnd];
+    }
+        
+    
+    Figura(const Figura& f)
+    {
+        PX = f.PX;
+        PY = f.PY;
+        for(int i = 0; i < 4; i++)
+        { X[i] = f.X[i]; Y[i] = f.Y[i]; }
+        Boja = f.Boja;
+    }
+    
+};
+Figura f;
+bool checkOut(int PX, int PY, short* xx, short* yy)
+{
+    bool ok = true;
+    for(int i = 0; i < 4; i++)
+    {
+        int x = PX + xx[i], y = PY + yy[i];
+        if( x < 0 || x >=10 || y < 0 || y >= 20 || matrix[x][y] != 0)
+        {
+            ok = false;
+        }
+    }
+    return ok;
+}
+bool checkEnd(int PX, int PY, short* xx, short* yy)
+{
+     bool ok = true;
+     for (int i = 0; i < 4; i++)
+     {
+          int x = PX + xx[i], y = PY + yy[i];
+          if (y < 0 || y >= 20 || matrix[x][y] != 0)
+          {
+             ok = false;
+          }
+     }
+     return ok;
+}
+bool rotiraj(short xr[], short yr[])
+{
+    int px = f.X[0], py = f.Y[0];
+    for (int i = 0; i < 4; i++)
+    {
+        int x2 = (f.Y[i] + px - py);
+        int y2 = (px + py - f.X[i]);
+        xr[i] = x2;
+        yr[i] = y2;
+    }
+    if(checkOut(f.PX, f.PY, xr, yr) && checkEnd(f.PX, f.PY, xr, yr))
+    {
+       
+        return true;
+    }
+    else return false;
+}
+void prikaziScore(int score){
+    TFT.set_font((unsigned char*) Arial12x12);
+    TFT.fillrect(0,160,79,210,DarkGrey);
+    TFT.locate(15,170);
+    TFT.printf("Score:");
+    TFT.locate(15,190);
+    TFT.printf("%d",score);
+}
+
+void prikaziHighScore(int highScore){
+    TFT.set_font((unsigned char*) Arial12x12);
+    TFT.fillrect(0,220,79,270,DarkGrey);
+    TFT.locate(15,230);
+    TFT.printf("High");
+    TFT.locate(15, 250);
+    TFT.printf("score:");
+    TFT.locate(15,270);
+    TFT.printf("%d",highScore);
+}
+
+void prikaziBrojLinija(int brojLinija) {
+    TFT.set_font((unsigned char*) Arial12x12);
+    TFT.fillrect(0,100,79,150,DarkGrey);
+    TFT.locate(15,110);
+    TFT.printf("Lines:");
+    TFT.locate(15,130);
+    TFT.printf("%d",brojLinija);
+}
+
+void prikaziSljedecuFiguru(Figura figura)
+{
+    TFT.fillrect(15,20,65,60, White);
+    for(int i = 0; i < 4; i++)
+    {
+        int x = 20 + figura.X[i] * 10;
+        int y = 30 + figura.Y[i] * 10;
+        TFT.fillrect(x,y,x+10,y+10,figura.Boja);
+        TFT.rect(x,y,x+10,y+10,Black);
+    }
+}
+void prikaziMeni(int odabrano, int level) {
+    
+    TFT.fillrect(0,0,239,319,DarkGrey);
+    TFT.set_font((unsigned char*) Arial12x12);
+    TFT.locate(95,130);
+    TFT.printf("Play");
+    TFT.locate(70,160);
+    TFT.printf("Level: %d",level+1);
+    
+    if(odabrano==0) {
+        TFT.locate(70,130);
+        TFT.printf(">");
+    }
+    else {
+        TFT.locate(45,160);
+        TFT.printf(">");
+    }
+}
+void shrink()
+{
+  int puni = 0;
+  bool ima = false;
+  int cnt = 0;
+ for (int i = 19; i >= 0; i--)
+ {
+     int sum = 0;
+     for (int j = 9; j >= 0; j--)
+     {
+          if (matrix[j][i] != 0)
+                sum++;
+     }
+     if (sum != 10)
+     {
+           puni += (1 << i);
+     }
+     else { ima = true; cnt++; }
+ }
+    score += 100 * cnt * cnt;
+    lines += cnt;
+    if(score > highScore) highScore = score;
+    prikaziScore(score);
+    prikaziHighScore(highScore);
+    prikaziBrojLinija(lines);
+    prikaziSljedecuFiguru(Figura(sljedeca));
+ 
+ int pocetak = 19;
+ for(int i = 19; i >= 0; i--)
+    if((puni & (1 << i)) == 0 ) 
+        { pocetak = i; break; }
+ for(int i = 19; i >= 0; i--)
+ {
+    int k = -1;
+    for(int b = 19; b >= 0; b--)
+    {
+      if(((1 << b) & puni) > 0)
+      {
+         k = b;
+         puni -= (1 << b);
+         break;
+      }
+    }                
+    if (k == -1)
+       for (int j = 0; j < 10; j++)
+            matrix[j][i] = 0;
+    else
+       for (int j = 0; j < 10; j++)
+            matrix[j][i] = matrix[j][k];
+ }
+ if(ima)
+ {
+ for(int i = 0; i < 20; i++)
+ {
+     for(int j = 9; j >= 0; j--)
+     {
+         int xx = cosakX + j*size, yy = cosakY + i*size;
+         TFT.fillrect(xx, yy, xx + size, yy + size, White);
+         if(matrix[j][i])
+         {
+            TFT.fillrect(xx, yy, xx + size, yy + size, matrix[j][i]);
+         }
+     }
+ }
+ for(int i = 0; i < 20; i++)
+ {
+     for(int j = 9; j >= 0; j--)
+     {
+         int xx = cosakX + j*size, yy = cosakY + i*size;
+         if(matrix[j][i])
+         {
+             TFT.rect(xx, yy, xx + size, yy + size, Black);    
+         }
+     }
+ }
+ }
+}
+void refresh(int prev, Figura ff)
+{
+    for(int i = 0; i < 10; i++)
+        for(int j = prev - 1; j >= 0; j--)
+        {
+            if(matrix[i][j] ) continue;
+            bool ima = false;
+            for(int i = 0; i < 4; i++)
+            {
+                if(matrix[ff.PX + ff.X[i]][ff.PY + ff.Y[i]])
+                    ima = true;
+            }
+            int xx = cosakX + i*size, yy = cosakY + j*size;
+            TFT.fillrect(xx,yy,xx+size,yy+size,White);
+        }
+}
+void obrisiFiguru(Figura ff)
+{
+    for(int i = 0; i < 4; i++)
+    {
+        int x = cosakX + (ff.PX + ff.X[i]) * size, y = cosakY + (ff.PY + ff.Y[i]) * size;
+        TFT.fillrect(x, y, x + size, y + size, White);
+    }
+}
+void crtajFiguru(Figura ff)
+{
+    for(int i = 0; i < 4; i++)
+    {
+        int x = cosakX + (ff.PX + ff.X[i]) * size, y = cosakY + (ff.PY + ff.Y[i]) * size;
+        TFT.fillrect(x, y, x + size, y + size, ff.Boja);
+        TFT.rect(x, y, x + size, y + size, Black);
+    }
+}
+void pomjeriDesno()
+{
+    if(checkOut(f.PX + 1, f.PY, f.X, f.Y))
+    {
+        obrisiFiguru(f);
+        f.PX++; 
+        crtajFiguru(f);
+    }
+}
+void pomjeriLijevo()
+{
+    if(checkOut(f.PX - 1, f.PY, f.X, f.Y))
+    {
+        obrisiFiguru(f);
+        f.PX--; 
+        crtajFiguru(f);
+    }
+}
+void pomjeriGore()
+{
+    short xr[4], yr[4];
+    bool rotiro = rotiraj(xr, yr);
+    if(rotiro)
+    {
+        obrisiFiguru(f);
+        strcpy(f.X, xr);
+        strcpy(f.Y, yr);
+        crtajFiguru(f);
+    }
+}
+enum stanje {S1, S2};
+stanje trenutno = S2;
+Ticker tickerDolje;
+bool ende = false;
+int opt = 0;
+int lvl = 0;
+int BROJLEVELA = 3;
+int ocitaj;
+int prev = CENTAR;
+float vejtovi[] = {0.8, 0.5, 0.3};
+Timer tasterDebounce;
+void pomjeriDolje()
+{
+    if(checkOut(f.PX, f.PY + 1, f.X, f.Y))
+    {
+        obrisiFiguru(f);
+        f.PY++;
+        crtajFiguru(f);
+    }
+    else
+    {
+        for(int i = 0; i < 4; i++)
+            matrix[f.PX + f.X[i]][f.PY + f.Y[i]] = f.Boja;
+        shrink();
+        f = Figura();
+        score += 4;
+        if(score > highScore) highScore = score;
+        prikaziScore(score);
+        prikaziHighScore(highScore);
+        prikaziBrojLinija(lines);
+        prikaziSljedecuFiguru(Figura(sljedeca));
+        if(!checkOut(f.PX, f.PY, f.X, f.Y))
+        {
+            // kraj
+            crtajFiguru(f);
+            tickerDolje.detach();
+            TFT.cls();
+            TFT.locate(80, 150);
+            TFT.printf("GAME OVER");
+            wait(3);
+            trenutno = S2;
+               tickerDolje.detach();
+             TFT.cls();
+            opt = 0;
+            lvl = 0;
+             prikaziMeni(opt, lvl);
+             prev = CENTAR;
+          f = Figura();
+        }
+    }
+}
+
+void resetujMatricu()
+{
+    for(int i = 0; i < 10; i++)
+        for(int j = 0; j < 20; j++)
+            matrix[i][j] = 0;
+}
+
+
+int ocitajSW()
+{
+    if(tasterDebounce.read_ms() > 200)
+    {
+        tasterDebounce.reset();
+        return sw;
+    }
+    else return 1;
+}
+
+void S1_entry()
+{
+    score = 0;
+    lines = 0;
+    sljedeca = rand() % 7;
+    TFT.cls();
+    resetujMatricu();
+    TFT.fillrect(cosakX, cosakY, cosakX + 140, cosakY + 280, White);
+    
+    dilej = vejtovi[lvl];
+    prikaziScore(score);
+    prikaziHighScore(highScore);
+    prikaziBrojLinija(lines);
+    prikaziSljedecuFiguru(Figura(sljedeca));
+    tickerDolje.attach(&pomjeriDolje, dilej);  
+}
+
+void S1_do()
+{
+        if(swDbnc.read_ms() > 40*(3-lvl)) 
+            swDbnc.reset();
+        else return;
+           ocitaj = ocitajDzojstik();
+        if(ocitaj == prev) return;
+        if(ocitaj == LIJEVO)
+            pomjeriLijevo();
+        else if(ocitaj == DESNO)
+            pomjeriDesno();
+        else if(ocitaj == GORE)
+            pomjeriGore();
+        else if(ocitaj == DOLJE)
+            pomjeriDolje();
+        prev = ocitaj;
+}
+
+void S2_entry()
+{
+   tickerDolje.detach();
+   TFT.cls();
+   opt = 0;
+   lvl = 0;
+   prikaziMeni(opt, lvl);
+   prev = CENTAR;
+   f = Figura();
+}
+
+void S2_do()
+{
+       if(swDbnc.read_ms() > 40) 
+            swDbnc.reset();
+        else return;
+       ocitaj = ocitajDzojstik();
+       if(ocitaj == prev) return;
+       if(ocitaj == DOLJE) opt = (opt + 1) % 2;
+       else if(ocitaj == GORE) opt = (opt + 1) % 2;
+       else if(ocitaj == DESNO && opt == 1)
+            lvl = (lvl + 1) % BROJLEVELA;
+       else if(ocitaj == LIJEVO && opt == 1)
+            lvl = (lvl - 1 + BROJLEVELA) % BROJLEVELA;
+       prikaziMeni(opt, lvl);
+       prev = ocitaj;
+}
+
+void prelaz()
+{
+    int o = ocitajSW();
+    switch(trenutno)
+    {
+        case S1:
+            switch(o)
+            {
+                case 0:
+                    trenutno = S2;
+                    S2_entry();
+                break;
+                case 1:
+                    S1_do();
+                break;
+            }
+        break;
+        case S2:
+            switch(o)
+            {
+                case 0:
+                    trenutno = S1;
+                    S1_entry();
+                break;
+                case 1:
+                    S2_do();
+                break;
+            }
+        break;
+    }
+}
+
+void init()
+{
+    sw.mode(PullUp);
+    TFT.set_orientation(0);
+    TFT.background(DarkGrey);
+    TFT.foreground(White);
+    srand(highScore);
+    S2_entry();
+}
+
+int main() 
+{
+    init();
+    tasterDebounce.start();
+    swDbnc.start();
+    while(1) { prelaz(); }
+}