Game

Dependencies:   N5110 mbed

main.cpp

Committer:
2016us_eminasmajlovi
Date:
2018-05-17
Revision:
0:71cf58df0deb

File content as of revision 0:71cf58df0deb:

#include "mbed.h"
#include "N5110.h"
#include "Joystick.h"
#define dp23 P0_0
N5110 lcd(dp4,dp24,dp23,dp25,dp2,dp6,dp18);
DigitalIn button(dp9);
int score;
/** Flag to show left hand side conllision of pattern
@note flag = 0 - there is no collision on the left
@note flag = 1 - there is collision on the left
*/
int left_collision_flag = 0;

/** Flag to show right hand side conllision of pattern
@note flag = 0 - there is no collision
@note flag = 1 - there is collision
*/
int right_collision_flag = 0;

/** Flag to show bottom conllision of pattern
@note flag = 0 - there is no collision
@note flag = 1 - there is collision
*/
int bottom_collision_flag = 0;

/** Flag to show top conllision of pattern
@note flag = 0 - there is no collision
@note flag = 1 - there is collision
*/
int top_collision_flag = 0;

/** Flag to show if there is pixels set on the 4 pixels distance away from the bottom of pattern
@brief if flag = 0, user can pull joystick down to make pattern falling faster
@note flag = 0 - there is no collision
@note flag = 1 - there is collision
*/
int fastmove_bottom_collision_flag = 0;

/** Flag to show if allow patterns to rotate
@note flag = 0 - allow
@note flag = 1 - not allow
*/
int rotation_collision_flag = 0;
int pattern_buffer[12][12];
int xOld;
int igra = 0;
void Pocetak() {
    lcd.clear();
    lcd.printString("Tetris", 10, 0);
    lcd.printString("-START-", 10, 3);
    
}
void nacrtajOblik(int tip, int rotacija, int x, int y) {
    switch(tip) {
        case 0: //L
        if (rotacija == 0) {
            lcd.drawRect(x, y, 4, 4, 1);
            lcd.drawRect(x, y+4, 4, 4, 1);
            lcd.drawRect(x, y+8, 4, 4, 1);
            lcd.drawRect(x+4, y+8, 4, 4, 1);}
        else if (rotacija == 1) {
            lcd.drawRect(x+1, y+1, 3, 3, 1);
            lcd.drawRect(x+5, y+1, 3, 3, 1);
            lcd.drawRect(x+9, y+1, 3, 3, 1);
            lcd.drawRect(x+1, y+5, 3, 3, 1);}
        else if (rotacija == 2) {
            lcd.drawRect(x, y, 3, 3, 1);
            lcd.drawRect(x+4, y, 3, 3, 1);
            lcd.drawRect(x+4, y+4, 3, 3, 1);
            lcd.drawRect(x+4, y+8, 3, 3, 1);}
        else {
            lcd.drawRect(x+1, y+5, 3, 3, 1);
            lcd.drawRect(x+5, y+5, 3, 3, 1);
            lcd.drawRect(x+9, y+5, 3, 3, 1);
            lcd.drawRect(x+9, y+1, 3, 3, 1);}
        break;
        case 1: //O
            lcd.drawRect(x, y, 4, 4, 1);
            lcd.drawRect(x, y+4, 4, 4, 1);
            lcd.drawRect(x+4, y, 4, 4, 1);
            lcd.drawRect(x+4, y+4, 4, 4, 1);
        break;
    }
}         

void obrisiNextOblik() {
    lcd.drawRect(0,0,12,12,2);
    }
struct Position {
    float x;
    float y;
    int type;
    int rotation;
};
Position pos;


int stariTip;
void init_game() {
    //int random = rand()%2;
    nacrtajOblik(0, 1, 0, 0);
    //stariTip = random;
    lcd.drawRect(15, 0, 6, 48, 1);
    lcd.drawRect(58, 0, 6, 48, 1);
    lcd.printString("0", 66, 2);
    lcd.printString("N:", 0, 3);
    lcd.printString("S:", 66, 0);
    
}
bool buttonPressedInGame() {
    if(button == 0) return true;
    else return false;
    }
    
void get_pattern(int tip, int rotacija){
    for(int i=pos.x; i<12; i++) {
        for(int j=pos.y; j<12; j++) {
            if(lcd.getPixel(i,j) == 0)
                pattern_buffer[i][j] = 0;
            else pattern_buffer[i][j] = 1;
            }
        }
    }
void left_collisionDetect()
{
    int left_boundary[12][12];
    get_pattern(pos.type,pos.rotation);

 
    for (int j=0; j<=11; j++) { //
        for (int i=0; i<=11; i++) {
            if (pattern_buffer[i][j]==1) {
                left_boundary[i][j]=1;
                for(int k=i+1; k<=11; k++) {
                    left_boundary[k][j] = 0;
                }
                break;
            } else {
                left_boundary[i][j]=0;
            }
        }
    }

    //check left collision
    int x = pos.x;
    int y = pos.y;
    if (x<21) { //for all the pattern, when x<0, pattern is on the most LHS of screen
        left_collision_flag = 1;
    } else { //check the pixel status away from left boundary for one pixel distance
        for(int i=x; i <= x+11; i++) { // (x,y) is the left top point of a 6*6 square
            for(int j=y; j <= y+11; j++) {
                if(left_boundary[i-x][j-y]==1) {
                    if(i == 0) { // pattern at most LHS of screen
                        left_collision_flag = 1;
                        break; // don't need to check the other pixels at same x, jump out of inner for loop
                    } else if (lcd.getPixel(i-1,j)) { //check one pixel away from left boundary
                        left_collision_flag = 1;
                        break;
                    } else {
                        left_collision_flag = 0;
                    }
                }
            }
            if (left_collision_flag == 1) {
                break;// jump out of inner for loop
            }
        }
    }
}


void right_collisionDetect()
{
    int right_boundary[12][12];
    get_pattern(pos.type,pos.rotation);

    for (int j=0; j<=11; j++) {
        for (int i=11; i>=0; i--) {
            if (pattern_buffer[i][j]==1) {
                right_boundary[i][j]=1;
                for(int k=i-1; k>=0; k--) {
                    right_boundary[k][j] = 0;
                }
                break;
            } else {
                right_boundary[i][j]=0;
            }
        }
    }

    //check right collision
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+11; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y; j <= y+11; j++) {
            if(right_boundary[i-x][j-y]==1) {
                if(j>=0) {
                    if(i >= 57) { // most RHS of gaming screen
                        right_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i+1,j)) {//check the pixel status away from right boundary for one pixel distance
                        right_collision_flag = 1;
                        break;
                    } else {
                        right_collision_flag = 0;
                    }
                }
            }
        }
        if (right_collision_flag == 1) {
            break;
        }
    }
}


void bottom_collisionDetect()
{
    int bot_boundary[12][12];
    get_pattern(pos.type,pos.rotation);

    for (int i=0; i<=11; i++) {
        for (int j=11; j>=0; j--) {
            if (pattern_buffer[i][j]==1) {
                bot_boundary[i][j]=1;
                for(int k=j-1; k>=0; k--) {
                    bot_boundary[i][k] = 0;
                }
                break;
            } else {
                bot_boundary[i][j]=0;
            }
        }
    }

    //check bottom collision
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+11; i++) { //check from left
        for(int j=y+11; j >= y; j--) { //check from bottom
            if (j>=-1) { //start check when pattern fall in the screen
                if(bot_boundary[i-x][j-y]==1) {
                    if(j >= 47) { // pattern at bottom
                        bottom_collision_flag = 1;
                        break; // jump out of inner for loop
                    } else if (lcd.getPixel(i,j+1)) {//check the pixel status away from bottom boundary for one pixel distance
                        bottom_collision_flag = 1;
                        break;
                    } else {
                        bottom_collision_flag = 0;
                    }
                }
            } else { //at bottom of screen
                bottom_collision_flag = 0;
            }
        }
        if( bottom_collision_flag == 1) {
            break; // jump out of inner for loop
        }
    }
}


void rotation_collisionDetect()
{
    int rotation = pos.rotation+1;
    if (rotation>3) {
        rotation=0;
    }
    get_pattern(pos.type,rotation);

    //check pixel status of upcoming rotation
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+11; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y; j <= y+11; j++) {
            if(pattern_buffer[i-x][j-y]==1) {
                if(i<0) { // out of LHS screen
                    rotation_collision_flag = 1;
                } else if(lcd.getPixel(i,j)) { // there is pixel set
                    rotation_collision_flag = 1;
                    break; //jump out of inner for loop
                } else {
                    rotation_collision_flag = 0;
                }
            }
        }
        if (rotation_collision_flag == 1) {
            break; //jump out of inner for loop
        }
    }
}
void top_collisionDetect() {
    if (pos.y==-12) { //pattern is about to fall
        bottom_collisionDetect();
        if (bottom_collision_flag == 1) { //if can't fall
            top_collision_flag = 1; // top collision
        } else {
            top_collision_flag = 0;
        }
    }
}

void fastmove_bottom_collisionDetect()
{
    int bot_boundary[12][12];
    get_pattern(pos.type,pos.rotation);

    // get the bottom boundary pattern
    for (int i=0; i<=11; i++) {
        for (int j=11; j>=0; j--) {
            if (pattern_buffer[i][j]==1) {
                bot_boundary[i][j]=1;
                for(int k=j-1; k>=0; k--) {
                    bot_boundary[i][k] = 0;
                }
                break;
            } else {
                bot_boundary[i][j]=0;
            }
        }
    }

    //check bottom collision for 4 pixel distance away from bottom boundary
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+11; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y+11; j >= y; j--) {
            if (j>=-1) {
                if(bot_boundary[i-x][j-y]==1) {
                    if(j >= 42) { // pattern is about to fall on the bottom
                        fastmove_bottom_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i,j+4)) {//check bottom collision for 4 pixel distance away from bottom boundary
                        fastmove_bottom_collision_flag = 1;
                        break;
                    } else {
                        fastmove_bottom_collision_flag = 0;
                    }
                }
            } else {
                fastmove_bottom_collision_flag = 0;
            }
        }
        if( fastmove_bottom_collision_flag == 1) {
            break;
        }
    }
}

void cancelLine()
{
    // int linePattern[30][2]; //the pixel setting for one line(30x2 square)
    int count; // count setting pixels two by two
    for(int j=1; j<=47; j+=4) {
        for(int i=22; i<=57; i+=4) {
            if (lcd.getPixel(i,j)==0) { // there is clear pixel
                count=0;
                break;
            } else if (lcd.getPixel(i,j)) {
                count++;
            }
        }
        if(count==9) { // one line is filled
            count=0; // reset the variable count
            lcd.drawRect(21,j,37,4,2); //clear the line
            score+=1;  // add the score
            //update the score
            char scoreBuffer[14];
            sprintf(scoreBuffer,"%d",score);
            lcd.printString(scoreBuffer,42,3);
            int xp, yp;
            for (int x=21; x<=56; x+=4) {
                for (int y=j; y>=0; y-=4) {
                    if (lcd.getPixel(x,y-4) == 0) {
                        xp = x; yp = y;
                        for(int k=xp; k <xp+4; k++) {
                            for(int l=yp; l<yp+4; l++){
                                lcd.clearPixel(k, l); }}
                        }
                    else {
                        lcd.drawRect(x, y, 3, 3, 1);
                        
                    }
                }
            }
        }
    }
}
void brisiStariDio(int x, int y) {
    for(int i=x; i<x+12; i++) {
        for(int j=y; j<y+12; j++) {
            if(pattern_buffer[i-x][j-y] == 0) 
                lcd.clearPixel(i, j);
            }
            }
            lcd.refresh();
}
        

void Tetris() {
    bool kraj = false;
    while(1) {
        if (igra == 0) igra = 1;
        kraj = buttonPressedInGame(); //check if user press button and get the decision
            if(kraj) { // exit game
                break; //jump out of while loop
            }
            lcd.printString("OK", 0, 4);
            pos.type = 1;  //get the pattern type
            obrisiNextOblik();
            nacrtajOblik(pos.type,0,1,1);
            //wait_ms(1000);// draw next pattern on the left hand side of screen
            if (pos.y >= -11) { // when pattern start falling, clear previous pattern
                obrisiNextOblik();
            }
            lcd.printString("OK", 0, 5);
            updateJoystick(); //get the joystick direction
            
            top_collisionDetect(); // check if current pattern touch the top
            if (top_collision_flag == 1) { // if touch the top, finish the game
                
               //finishAnimation(); //finish animation
                lcd.clear();
                
                char scoreBuffer[14];
                sprintf(scoreBuffer,"%d",score);
                lcd.printString("SCORE IS: ",10,2);
                lcd.printString(scoreBuffer,35,4);
                lcd.refresh();
                wait(3.0);
                lcd.clear();
                //state=0; // back to the main menu
                break;
            }
            
            //move patterns according to joystick direction
            switch(joystick.direction) {
                case UP: // rotation
                    rotation_collision_flag = 0;
                    rotation_collisionDetect(); // check if allow rotation
                    if(rotation_collision_flag == 0) { // allow rotation
                        pos.rotation++;
                        if (pos.rotation>3) {
                            pos.rotation=0;
                        }
                        
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    } else {// not allow rotation
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    }
                    break;
                case DOWN: // faster moving down
                    fastmove_bottom_collision_flag = 0;
                    fastmove_bottom_collisionDetect();
                    if (fastmove_bottom_collision_flag == 0) {// allow faster move
                        
                        pos.y +=8; 
                        // move pattern down by 4 pixels distance
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    } else {
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    }
                    break;
                case RIGHT: // move right
                    right_collision_flag = 0;
                    right_collisionDetect(); // detect right collision
                    if( right_collision_flag == 0) { // allow move right
                        
                        pos.x +=4;
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    } else { // not allow move right
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                        right_collision_flag = 0;
                    }
                    break;
                case LEFT: //move left
                    left_collision_flag = 0;
                    left_collisionDetect(); // detect left collision
                    if( left_collision_flag == 0) {// allow move left
                        
                        pos.x -=4;
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                    } else { // not allow move left
                        nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y);
                        left_collision_flag = 0;
                    }

                    break;
            }
            
            xOld = pos.x; //store previous pattern x co-codinate
            
            bottom_collisionDetect(); // bottom collision detect
            if (bottom_collision_flag == 0) { // no collision
                //brisiStariDio(pos.x, pos.y);
                pos.y+=4;
                 // keep moving pattern down
                wait_ms(1000);
            } else { // bottom collision
                nacrtajOblik(pos.type,pos.rotation,pos.x,pos.y); // fix pattern
                cancelLine(); // check filled lines and add score
                pos.x = 35; // new pattern will fall from the centre
                pos.y = -12;
                pos.rotation=0;
                nacrtajOblik(pos.type, pos.rotation, pos.x, pos.y);
                obrisiNextOblik();
           }
           brisiStariDio(pos.x, pos.y);
            lcd.refresh();
        }
        sleep(); // go to sleep mode unless ticker interupt
    }
    
    
int main() {
    while(1) {
        lcd.init(); // initialise lcd
        lcd.normalMode();      // normal colour mode
        lcd.setBrightness(1.0); // put LED backlight on 100%
        button.mode(PullUp);
        Pocetak();
        wait_ms(1000);
        lcd.clear();
        init_game();
        Tetris(); 
    }  
}