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

Dependencies:   N5110 SDFileSystem mbed

main.cpp

Committer:
cjw851102
Date:
2016-04-25
Revision:
1:2a758565f691
Parent:
0:12a1972fa0d0
Child:
2:f427089e2bfa

File content as of revision 1:2a758565f691:

#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;

int left_boundary[6][6];

void bottom_collisionDetect();
int bottom_yMax = 47;
int 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 {
    float x;    // current x value
    float x0;   // 'centred' x value
    float y;    // current y value
    float 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();

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.4);
    lcd.refresh();

    int xOld;
    calibrateJoystick();

    int typeCount = 10;
    int rotationCount = 5;

    while (1) {

        if(g_game_flag==1) {
            g_game_flag = 0;
            pos.type = typeArray[typeCount];
            pos.rotation = rotationArray[rotationCount];
            if (pos.y >= -6) { // clear previous pattern
                drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0);
            }
            updateJoystick();

            switch(joystick.direction) {
                case UP:
                    pos.x +=2;
                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    break;
                case DOWN:
                    pos.y +=4;
                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                    break;
                case RIGHT:
                    right_collisionDetect();
                    /*
                    for (int i=0; i<=5; i++) {
                        for (int j=0; j<=5; j++) {
                            if(right_boundary[i][j] ==1) {
                                lcd.setPixel(i,j);
                            }
                        }
                    }
                    */
                    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);
                    }
                    break;
                case LEFT:
                    left_collisionDetect();
                    if( left_collision_flag == 0) {
                        pos.x -=2;
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                        //   lcd.printString("0",42,5);
                    } else {
                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
                        //  lcd.printString("1",42,5);
                    }
                    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;
            if (pos.y<42) {
                pos.y++;
            } else {
                pos.y=42;
            }
        }

        lcd.refresh();
    }

}

void init_game()
{
    pos.x = 10;
    pos.y = -6;

    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("100",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 && i <= 29) {
                            lcd.clearPixel(i,j);
                        }
                    } else if (fill==1) {
                        if (j<=47 && i>=0 && i <= 29) {
                            lcd.setPixel(i,j);
                        }
                    }
                }
            }
        }
    }
}

void left_collisionDetect()
{
    scan();
    get_pattern(pos.type,pos.rotation);
    // int left_boundary[6][6];
    // 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 (buffer[i-1][j]) {
                        left_collision_flag = 1;
                        break;
                    } else {
                        left_collision_flag = 0;
                    }
                }
                if (left_collision_flag == 1) {
                    break;
                }
            }
        }
    }
}


void right_collisionDetect()
{
    scan();
    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 (buffer[i+1][j] == 1) {
                        right_collision_flag = 1;
                        break;
                    } else {
                        right_collision_flag = 0;
                    }
                }
            }
            if (right_collision_flag == 1) {
                break;
            }
        }

    }
}

void bottom_collisionDetect()
{
    scan();
    get_pattern(pos.type,pos.rotation);
    int bot_boundary[6][6];
    // 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=i-1; k>=0; k--) {
                    bot_boundary[i][k] = 0;
                }
            } 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; j <= y+5; j++) {
            if(bot_boundary[i-x][j-y]==1) {
                if(j == 47) {
                    bottom_collision_flag = 1;
                    bottom_yMax = 47;
                } else if (buffer[i][j+1] == 1) {
                    right_collision_flag = 1;
                    if(j< bottom_yMax) {
                        bottom_yMax = j;
                    }
                } else {
                    right_collision_flag = 0;
                }
            }
        }

    }
}

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;
    }

}