Game

Dependencies:   N5110 mbed

Revision:
0:71cf58df0deb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu May 17 13:04:23 2018 +0000
@@ -0,0 +1,530 @@
+#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(); 
+    }  
+}   
+    
+