My ELEC2645 joystick project Tetris Game NAME: JIANWEI CHEN SID: 200879849

Dependencies:   N5110 SDFileSystem mbed

main.cpp

Committer:
cjw851102
Date:
2016-05-01
Revision:
3:5494a0fb3a33
Parent:
2:f427089e2bfa
Child:
4:463abe5f5135

File content as of revision 3:5494a0fb3a33:

#include "mbed.h"
#include "Patterns.h"
#include "N5110.h"

#define DIRECTION_TOLERANCE 0.05

//VCC, SCE, RST, D/C, MOSI,SCLK, LED
N5110 lcd(PTE26,PTA0,PTC4,PTD0,PTD2,PTD1,PTC3);
AnalogIn yPot(PTB2);
AnalogIn xPot(PTB3);
DigitalIn button(PTB11);
Patterns patterns;

Ticker game;
void game_isr();
volatile int g_game_flag = 0;

void drawPattern(int type,int rotation,int x,int y,int fill); // draw pattern at (x,y), fill = 0 white, fill = 1 black

void left_collisionDetect();
int left_collision_flag = 0;

void right_collisionDetect();
int right_collision_flag = 0;

void bottom_collisionDetect();
int bottom_collision_flag = 0;

void top_collisionDetect();
int top_collision_flag = 0;

void rotation_collisionDetect();
int rotation_collision_flag = 0;

void fastmove_bottom_collisionDetect();
int fastmove_bottom_collision_flag = 0;

struct Position {
    float x;
    float y;
    int type;
    int rotation;
};
typedef struct Position position;

position pos;

void init_game();
int typeArray[100];
int rotationArray[100];

int pattern_buffer[6][6];
void get_pattern(int type, int rotatin);

void scan();
int buffer[84][48];

// create enumerated type (0,1,2,3 etc. for direction)
// could be extended for diagonals etc.
enum DirectionName {
    UP,
    DOWN,
    LEFT,
    RIGHT,
    CENTRE,
    UNKNOWN
};
// struct for Joystick
typedef struct JoyStick Joystick;
struct JoyStick {
    double x;    // current x value
    double x0;   // 'centred' x value
    double y;    // current y value
    double y0;   // 'centred' y value
    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
    DirectionName direction;  // current direction
};
// create struct variable
Joystick joystick;
void calibrateJoystick();
void updateJoystick();

void cancelLine();// if one line is filled, cancel it and add the score
int score=0;

void finishAnimation();

int xOld;
int typeCount = 0;
int nextTypeCount;

int main()
{
    wait(2.0);  // short delay for power to settle
    lcd.init();
    lcd.normalMode();      // normal colour mode
    lcd.setBrightness(1.0); // put LED backlight on 100%
    init_game();
    game.attach(&game_isr,0.2);
    lcd.refresh();
    calibrateJoystick();

    while (1) {

        if(g_game_flag==1) {
            g_game_flag = 0;
            pos.type = typeArray[typeCount];
            nextTypeCount=typeCount+1;
            if (nextTypeCount>99) {
                nextTypeCount=0;
            }
            drawPattern(typeArray[nextTypeCount],0,55,41,1);// draw next pattern
            if (pos.y >= -5) { // clear previous pattern
                drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0);
            }
            updateJoystick();
            top_collisionDetect();
            if (top_collision_flag == 1) {
                finishAnimation();
                lcd.clear();
                char scoreBuffer[14];
                sprintf(scoreBuffer,"%d",score);
                lcd.printString("SCORE IS: ",10,2);
                lcd.printString(scoreBuffer,35,3);
                lcd.refresh();
                break;
            }
            switch(joystick.direction) {
                case UP:
                    rotation_collisionDetect();
                    if(rotation_collision_flag == 0) {
                        pos.rotation++;
                        if (pos.rotation>3) {
                            pos.rotation=0;
                        }
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    } else {// if collision
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    }
                    break;
                case DOWN:
                    fastmove_bottom_collisionDetect();
                    if (fastmove_bottom_collision_flag == 0) {
                        pos.y +=4;
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    } else {
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    }
                    break;
                case RIGHT:
                    right_collisionDetect();
                    if( right_collision_flag == 0) {
                        pos.x +=2;
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    } else {
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                        right_collision_flag = 0;
                    }
                    break;
                case LEFT:
                    left_collisionDetect();
                    if( left_collision_flag == 0) {
                        pos.x -=2;
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    } else {
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                        left_collision_flag = 0;
                    }

                    break;
                case CENTRE:
                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    break;
                case  UNKNOWN:
                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    break;
            }

            xOld = pos.x;
            bottom_collisionDetect();
            if (bottom_collision_flag == 0) {
                pos.y++;
            } else {
                drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);// fix pattern
                cancelLine();
                pos.x = 10;
                pos.y = -6;
                pos.rotation=0;
                drawPattern(typeArray[nextTypeCount],pos.rotation,55,41,0);// clear the old next pattern
                typeCount ++;
                if (typeCount >99) {
                    typeCount = 0;
                }
            }

        }
        lcd.refresh();
    }

}

void init_game()
{
    pos.x = 10;
    pos.y = -6;
    pos.rotation=0;
    for(int i=0; i<=99; i++) {
        typeArray[i] = rand()%7;
        rotationArray[i] = rand()%5;
    }
    lcd.drawLine(30,0,30,47,1);
    lcd.printString("Level:",42,0);
    lcd.printString("easy",42,1);
    lcd.printString("Score:",42,2);
    lcd.printString("0",42,3);
    lcd.printString("Next:",42,4);

}

void get_pattern(int type, int rotation)
{
    for(int i=0; i<=5; i++) {
        for(int j=0; j<=5; j++) {
            pattern_buffer[i][j] = patterns.getPatterns(type,rotation,j,i);  // return pattern[type][rotation][y][x];
        }
    }
}

void scan()
{
    for (int i=0; i<=83; i++) {
        for (int j=0; j<=47; j++) {
            if(lcd.getPixel(i,j)) {
                buffer[i][j] = 1;
            } else {
                buffer[i][j] = 0;
            }
        }
    }
}


void drawPattern(int type,int rotation,int x,int y,int fill)
{
    get_pattern(type,rotation);
    for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y; j <= y+5; j++) {
            if (j>=0) {
                if(pattern_buffer[i-x][j-y]==1) {
                    if (fill==0) {
                        if (j<=47 && i>=0) {
                            lcd.clearPixel(i,j);
                        }
                    } else if (fill==1) {
                        if (j<=47 && i>=0) {
                            lcd.setPixel(i,j);
                        }
                    }
                }
            }
        }
    }
}

void left_collisionDetect()
{
    int left_boundary[6][6];
    get_pattern(pos.type,pos.rotation);

    // get the left boundary pattern
    for (int j=0; j<=5; j++) { //
        for (int i=0; i<=5; i++) {
            if (pattern_buffer[i][j]==1) {
                left_boundary[i][j]=1;
                for(int k=i+1; k<=5; 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<0) {
        left_collision_flag = 1;
    } else {
        for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
            for(int j=y; j <= y+5; j++) {
                if(left_boundary[i-x][j-y]==1) {
                    if(i == 0) {
                        left_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i-1,j)) {
                        left_collision_flag = 1;
                        break;
                    } else {
                        left_collision_flag = 0;
                    }
                }
            }
            if (left_collision_flag == 1) {
                break;
            }
        }
    }
}


void right_collisionDetect()
{
    int right_boundary[6][6];
    get_pattern(pos.type,pos.rotation);
    // get the left boundary pattern
    for (int j=0; j<=5; j++) {
        for (int i=5; 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 left collision
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y; j <= y+5; j++) {
            if(right_boundary[i-x][j-y]==1) {
                if(j>=0) {
                    if(i >= 29) {
                        right_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i+1,j)) {
                        right_collision_flag = 1;
                        break;
                    } else {
                        right_collision_flag = 0;
                    }
                }
            }
        }
        if (right_collision_flag == 1) {
            break;
        }

    }
}

void bottom_collisionDetect()
{
    int bot_boundary[6][6];
    get_pattern(pos.type,pos.rotation);
    // get the left boundary pattern
    for (int i=0; i<=5; i++) {
        for (int j=5; 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 left collision
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y+5; j >= y; j--) {
            if (j>=-1) {
                if(bot_boundary[i-x][j-y]==1) {
                    if(j >= 47) {
                        bottom_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i,j+1)) {
                        bottom_collision_flag = 1;
                        break;
                    } else {
                        bottom_collision_flag = 0;
                    }
                }
            } else {
                bottom_collision_flag = 0;
            }
        }
        if( bottom_collision_flag == 1) {
            break;
        }
    }
}

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

    //check
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y; j <= y+5; j++) {
            if(pattern_buffer[i-x][j-y]==1) {
                if(i<0) {
                    rotation_collision_flag = 1;
                } else if(lcd.getPixel(i,j)) {
                    rotation_collision_flag = 1;
                    break;
                } else {
                    rotation_collision_flag = 0;
                }
            }
        }
        if (rotation_collision_flag == 1) {
            break;
        }
    }
}

void top_collisionDetect()
{
    if (pos.y==-6) {
        bottom_collisionDetect();
        if (bottom_collision_flag == 1) {
            top_collision_flag = 1;
        } else {
            top_collision_flag = 0;
        }
    }
}

void fastmove_bottom_collisionDetect()
{
    int bot_boundary[6][6];
    get_pattern(pos.type,pos.rotation);
    // get the left boundary pattern
    for (int i=0; i<=5; i++) {
        for (int j=5; 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 left collision
    int x = pos.x;
    int y = pos.y;
    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
        for(int j=y+5; j >= y; j--) {
            if (j>=-1) {
                if(bot_boundary[i-x][j-y]==1) {
                    if(j >= 42) {
                        fastmove_bottom_collision_flag = 1;
                        break;
                    } else if (lcd.getPixel(i,j+4)) {
                        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 game_isr()
{
    g_game_flag = 1;
}

// read default positions of the joystick to calibrate later readings
void calibrateJoystick()
{
    button.mode(PullDown);
    // must not move during calibration
    joystick.x0 = xPot;  // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
    joystick.y0 = yPot;
}

void updateJoystick()
{
    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
    joystick.x = xPot - joystick.x0;
    joystick.y = yPot - joystick.y0;
    // read button state
    joystick.button = button;

    // calculate direction depending on x,y values
    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = CENTRE;
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = UP;
    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = RIGHT;
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }

}

void cancelLine()
{
    // int linePattern[30][2]; //the pixel setting for one line(30x2 square)
    int count;
    for(int j=0; j<=46; j+=2) {
        for(int i=0; i<=29; i++) {
            if (lcd.getPixel(i,j)==0||lcd.getPixel(i,j+1)==0) {
                count=0;
                break;
            } else if (lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)) {
                count++;
            }
        }
        if(count==30) { // one line is filled
            count=0;
            lcd.drawRect(0,j,29,1,2); //clear the line
            score+=10;  // add the score
            //print the score
            char scoreBuffer[14];
            sprintf(scoreBuffer,"%d",score);
            lcd.printString(scoreBuffer,42,3);
            scan();
            // move the patterns upon the line down for 2 pixels' hight
            for (int x=0; x<=29; x++) {
                for (int y=j; y>=0; y--) {
                    if (buffer[x][y]) {
                        lcd.clearPixel(x,y);
                        lcd.setPixel(x,y+2);
                    }
                }
            }
        }
    }
}

void finishAnimation()
{
    for (int j=47; j>=0; j--) {
        lcd.drawRect(0,j,29,1,1);
        wait(0.05);
        lcd.refresh();
    }
}