Game Tetris on LPC 1114ETF with Banggood display and Joystick

Dependencies:   SPI_TFT_ILI9341 TFT_fonts mbed

main.cpp

Committer:
2018US_HarisSoljic
Date:
2018-06-18
Revision:
0:71c49df3f7cd

File content as of revision 0:71c49df3f7cd:

#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(); }
}