2018 US Projekt - Stack Attack (Grupa 9) Haris Salman Amir Muminović Glavni program.

Dependencies:   SPI_TFT_ILI9341 Sprites TFT_fonts mbed

main.cpp

Committer:
2018US_harissalman
Date:
2018-07-02
Revision:
1:5a73a95c3460
Parent:
0:88e77eadd8e1

File content as of revision 1:5a73a95c3460:

#include "mbed.h"
#include "stdio.h"
#include "string"
#include "vector"

#include "SPI_TFT_ILI9341.h"
#include "GraphicsDisplay.h"

#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial28x28.h"
#include "font_big.h"

#include "Sprites.h"

// Konstante: Velicina kutije, padding sa lijeva
#define BoxSize 30
#define LPAD 10

using std::vector;

//                      MOSI, MISO,  SCK,   CS, RESET,   DC, NAME
SPI_TFT_ILI9341 display(PTD2, PTD3, PTD1, PTE2, PTA20, PTD5, "display");
AnalogIn Jx(PTB1);
AnalogIn Jy(PTB2);
DigitalIn BTN(PTE5);
Timer deb;

// Master ticker za igru
Ticker gridTicker;

vector<vector<bool> > mapa;

double OffsetX, OffsetY;
bool paused(false);
bool gameover(false);
bool toggleDraw(true);

int generateRandom();
void gameOver();

class Claw {
    int position, target;
    bool hasBox;
    double moveTime; // Vrijeme neophodno da se ruka pomjeri sa jedne lokacije na drugu, u milisekundama
public:
    Claw() : position(0), target(generateRandom()), hasBox(true), moveTime(1000) {}

    void GiveBox() {
        if (position == 0 && !hasBox){
            hasBox = true;
            target = generateRandom();
        }
    }
    
    void MoveClaw() {
        GiveBox();
        if (target > position) position++;
        else if (target < position) position--;
        else if (target == position) BaciBox();
    }

    void BaciBox() {
        hasBox = false;
        if (mapa[5][position]){
            bool kraj(true);
            for(int i(0); i<5; i++) if(mapa[i][position]==0) kraj=false;
            if(kraj) gameOver();
        }
        mapa[5][position] = true; // Dodaj kutiju u 
        target = 0; // Pokupi novu na pocetku
    }

    void DrawClaw() {
        //                         x0         y0               sirina   visina   *bitmap
        if(!hasBox) display.Bitmap(position*BoxSize + LPAD, 0, BoxSize, BoxSize, claw);
        else display.Bitmap(position*BoxSize + LPAD, 0, BoxSize, BoxSize, clawBoxColor);
    }
    
    void drawBlank(){
        display.fillrect(position*BoxSize + LPAD, 0, position*BoxSize + BoxSize + LPAD, BoxSize, White);
    }
    
    void TickerFja(){
        drawBlank();
        MoveClaw();
        DrawClaw();    
    }
};

class Player{
    short int x, y;
public:
    Player() : x(5),y(0){}
    
    void PomjeriDesno(){
        if(x < 9){ //Ako moze jos ici desno
            if (mapa[y][x+1] == 0 && mapa[y+1][x+1] == 0){ //Ako desno nije kutija
                drawBlank(y,x); drawBlank(y+1,x);
                x++;
            }
            else{ // Ako jeste kutija
                if (x+1 < 9){ // Ako nije kutija na kraju
                    if (mapa[y][x+2] == 0 && mapa[y+1][x+1] == 0){ // Ako ima mjesta za pomjeranje kutije
                        drawBlank(y,x); drawBlank(y+1,x);
                        x++; //Update lokacije
                        mapa[y][x] = 0;    //Brisi kutiju
                        mapa[y][x+1] = 1; //Pomjeri kutiju na novu lokaciju
                    }
                }
            }
        }
    }
    
    void PomjeriLijevo(){
        if(x > 0){ //Ako moze jos ici lijevo
            if (mapa[y][x-1] == 0 && mapa[y+1][x-1] == 0){ // Ako lijevo nije kutija
                drawBlank(y,x); drawBlank(y+1,x);
                x--;
            } else { // Ako jeste kutija
                if (x-1 > 0){ //Ako nije kutija na kraju
                    if (mapa[y][x-2] == 0 && mapa[y+1][x-1] == 0){ // Ako ima mjesta za pomjeranje kutije
                        drawBlank(y,x); drawBlank(y+1,x);
                        x--; //Update lokacije
                        mapa[y][x] = 0;    //Brisi kutiju
                        mapa[y][x-1] = 1; //Pomjeri kutiju na novu lokaciju
                    }
                }
            }
        }
    }
    
    void PomjeriGore(){
        // Provjeri da ima od sta ispod sebe da odskoci, kao i ako je dosao do vrha
        if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){
            drawBlank(y,x);
            y++;
        }
    }

    void PomjeriGoreDesno(){
        if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){
            if (x < 9 && y < 6){ //Ima prostora za skok
                if (mapa[y+1][x+1] == 0){ // Pomjeri igraca ako nema kutije
                    drawBlank(y,x); drawBlank(y+1,x);
                    x++;
                    y++;
                }
                else { // Ako ima kutije, pomakni kutiju
                    if (x < 8){ // Ako nije boundary
                        if (mapa[y+1][x+2] == 0) {// Ako se moze pomaci desno
                            drawBlank(y,x); drawBlank(y+1,x);
                            x++;
                            y++;
                            mapa[y][x] = 0; // Nema tu kutije
                            mapa[y][x+1] = 1; // Sad je pomaknuta desno
                        }
                    }
                }
            }
        }
    }
    
    void PomjeriGoreLijevo(){
        if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){
            if (x > 0 && y < 6){ //Ima prostora za skok
                if (mapa[y+1][x-1] == 0){ // Pomjeri igraca ako nema kutije
                    drawBlank(y,x); drawBlank(y+1,x);
                    x--;
                    y++;
                }
                else { // Ako ima kutije, pomakni kutiju
                    if (x - 2 > 0){ // Ako nije boundary
                        if (mapa[y+1][x-2] == 0) {// Ako se moze pomaci desno
                            drawBlank(y,x); drawBlank(y+1,x);
                            x--;
                            y++;
                            mapa[y][x] = 0; // Nema tu kutije
                            mapa[y][x-1] = 1; // Sad je pomaknuta desno
                        }
                    }
                }
            }
        } 
    }
    
    void DaLiJeZiv(){   
        if (mapa[y+1][x]) gameOver();
    }
    
    int GetX(){ return x; }
    int GetY(){ return y; }
    void SetX(int Ox){ x = Ox; }
    void SetY(int Oy){ y = Oy; }
    
    void drawPlayer(){
        //             x0                     y0            širina   visina         *bitmap
        display.Bitmap(x*BoxSize + LPAD + 1, (5-y)*BoxSize, BoxSize, 2*BoxSize + 1, charColor);
    }
    
    void drawBlank(int row, int column){
        display.fillrect(row*BoxSize + LPAD + 1, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize - 1, White);
    }
};

// Vraca random broj od 0 do 99 jer FRDM nema sat za random seed
int generateRandom(){
    int random(int((Jx+Jy+1) * (rand()%100))%10);
    if(random < 0) random *= -1;
    return random;
}

class Grid{
    Player p;
    Claw c;
    int score;
public:
    Grid(){ setupMap(); }
    
    Player& Igrac(){ return p; }
    
    void setupMap(){
        p.SetX(5);
        p.SetY(0);
        score = 0;
        mapa.resize(0);
        vector<bool> novi(10, false);
        for (int i(0); i < 6; i++) mapa.push_back(novi);
        
        mapa[0][0] = mapa[0][1] = mapa[0][7] = true;
    }
    
    int GetScore(){ return score; }
    
    void gravity(){
        if(p.GetY()>0 && !mapa[p.GetY()-1][p.GetX()]) p.SetY(p.GetY()-1);    
    }
    
    void masterTicker(){
        /*if(BTN){
            gridTicker.detach();
            pause();
            gridTicker.attach(this, &Grid::masterTicker, 1);
        }*/
        c.TickerFja();
        readJoystick();
        p.drawPlayer();
        drawMap();
    }
    
    void drawMap(){
        drawBorders();
        displayScore();
        
        // Crtanje mape ovisno o matrici prisustva
        for(int i(0); i<6; i++){
            for(int j(0); j<10; j++){
                if(mapa[i][j]) drawBox(j, 6-i);
                else if((i==p.GetY() || i==p.GetY()+1) && j==p.GetX()) continue;
                else drawBlank(j, 6-i);
            }
        }
        calculatePoints();
        if(toggleDraw = !toggleDraw) refreshMapa();
        p.DaLiJeZiv();
    }
    
    void refreshMapa(){
        // Kad padaju kutije, treba se pozivati svaku sekundu
        // Gravitacija igrača
        gravity();
        for(int i(1); i<6; i++){
            for(int j(0); j<10; j++){
                if (mapa[i][j] && !mapa[i-1][j]){
                    mapa[i][j] = false;
                    mapa[i-1][j] = true;
                }
            }
        }
    }
    
    void calculatePoints(){
        bool rowFull(true);
        // Vidi kakvo je stanje
        for (int i(0); i < 10; i++){
            if (mapa[0][i] == 0) rowFull = false;
        }
        // Ako je red pun, briši sve i dodaj bodove
        if (rowFull){
            for (int i(0); i < 10; i++) mapa[0][i] = 0;
            score += 100;
            displayScore();
        }
    }
    
    void drawBox(int row, int column){
        display.rect(row*BoxSize + LPAD, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize, Black);
        display.line(row*BoxSize + LPAD, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize, Black);
        display.line(row*BoxSize + BoxSize + LPAD, column*BoxSize, row*BoxSize + LPAD, column*BoxSize + BoxSize, Black);
    }
    
    void drawBlank(int row, int column){
        display.fillrect(row*BoxSize + LPAD + 1, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize - 1, White);
    }
    
    // Nacrtaj granice igre
    void drawBorders(){
        display.line(LPAD - 1, 0, LPAD - 1, 211, Black);      // Lijeva granica
        display.line(311, 0, 311, 210, Black);                // Desna granica
        display.line(LPAD - 1, 211, 311, 211, Black);         // Donja granica
    }
    
    void displayScore(){
        display.locate(166, 219);
        display.printf("SCORE:%6d", score);
    }

    void readJoystick(){
        // Debouncing džojstika
        if(deb.read_ms()<0.4) return;
        deb.reset();
        
        int x = Jx*3.3 - 0.4;  // 0 = Lijevo, 1 = Ništa, 2 = Desno
        int y = Jy*3.3 - 0.4;  // 0 = Dole,   1 = Ništa, 2 = Gore
        
        if(x == 0){
            if(y == 0) p.PomjeriGoreLijevo();
            else p.PomjeriLijevo();
        } else if(x == 2){
            if(y == 0) p.PomjeriGoreDesno();
            else p.PomjeriDesno();
        } else if(y == 0) p.PomjeriGore();
    }
};

Grid g;

// Iskljuceno radi problema sa InterruptIn
void pause(){
    // Resetuje igru ako je trenutno kraj
    if(gameover){
        gameover = false;
        display.cls();
        g.setupMap();
        return;
    }
    
    if(deb.read_ms()>1000){
        // Toggle trenutno stanje pauze
        paused = !paused;
        
        if(paused){
            display.locate(LPAD, 219);
            display.printf("PAUZA");
            while(paused);
        } else {
            // Obriši tekst za pauzu, nastavi igru
            display.fillrect(LPAD, 219, 70, 231, White);
        }
    }
    deb.reset();
}

void gameOver(){
    gridTicker.detach();
    gameover = true;
    display.cls();
    
    display.locate(58, 100);
    display.set_font((unsigned char*) Arial28x28);
    display.printf("GAME OVER");
    display.set_font((unsigned char*) Arial12x12);
    display.locate(100, 140);
    display.printf("SCORE:%6d", g.GetScore());
    //display.locate(70, 180);
    //display.printf("Press Joystick to restart...");
    
    while(1){
        if(gameover) wait(0.1);
        else break;
    }
}

// -------------------------------------------------------------------------- //

int main() {
    display.claim(stdout);
    display.set_orientation(1);
    display.background(White);
    display.foreground(Black);
    display.cls();
    display.set_font((unsigned char*) Arial12x12);
    
    deb.start();
    gridTicker.attach(&g, &Grid::masterTicker, 0.25);

    while(1) {
        wait(1);
    }
}