ELEC2645 Joseph Allison 200860349

Dependencies:   N5110 Tetris mbed

main.cpp

Committer:
el14ja
Date:
2016-04-07
Revision:
2:61caca4dd3f0
Parent:
1:2b9ba34131ca
Child:
3:8c5362716f4c

File content as of revision 2:61caca4dd3f0:

/* ELEC2645 Project
week 19 - Created functions to work set pixels of the game area
        - Added the shapes and all their orientations
        - Created functions to place and remove shapes
        -added interupts and tickers for block moved and rotaion

week 20 - 7system function

week 21 - starting to imple,ent collision detection

easter - colliosn detection
       - piece placement
       - scoring
       - levels and game speed changing
*/



#include "main.h"

double currentgamespeed = 0.8;

int main()
{

    pc.baud(115200);
    srand(floor(ain.read()*10000));

    //buzzer.write(0.5); *****

    left.mode(PullDown);
    right.mode(PullDown);
    spin.mode(PullDown);
    down.mode(PullDown);

    lcd.init();
    gameSetup();
    newShapeBag();//create bag of shapes to use
    nextpiece = nextshape[1];
    gameInfo(0,1,nextpiece);


    left.rise(&left_isr);
    right.rise(&right_isr);
    spin.rise(&spin_isr);
    down.rise(&down_isr);

    //musicticker.attach(&music_isr,0.25); ***** stopped the music

    setTicker(gamespeed);
    /*****
    *******GAMESPEED*******!!!!!!!
    */
    while (true) {

        if(g_newpiece) {
            g_newpiece = 0;
            newpiece();
        }

        if(g_right) {
            g_right = 0;
            g_righttimeout = 0;
            righttimeout.attach(&righttimeout_isr,0.15);
            
                tetris.movePieceRight();
            
        }

        if(g_left) {
            g_left = 0;
            g_lefttimeout = 0;
            lefttimeout.attach(&lefttimeout_isr,0.15);
    
                tetris.movePieceLeft();
            
        }
    //ANTI-DOUBLE PRESS*******
        if (g_timer_flag) {
            g_timer_flag = 0;

            if(movePossible(pieceposition[0],pieceposition[1]+1,orientation)) { //returns false if peicne cant move down

                tetris.movePieceDown();

            } else { //piece placed

                pieceToGameArray();
                g_newpiece = 1;

                if(harddropping) {
                    harddropping = 0;
                    ticker.detach();
                    setTicker(gamespeed);
                }
                checkCompleteLine();
               

            }
        }

        if(g_spin) {
            g_spin = 0;
            g_spintimeout = 0;
            spintimeout.attach(&spintimeout_isr,0.15);
            //check if peice can spin
            
                tetris.spinPiece();
            
        }

        if(g_down) {
            g_down = 0;
            g_downtimeout = 0;
            downtimeout.attach(&downtimeout_isr,0.15);
            ticker.detach();
            setTicker(0.001);
            harddropping = 1;
        }

        if(g_music) {
            g_music = 0;
            buzzer.period_us(musisnotes[musiccounter]);
            musiccounter++;

            if(musiccounter > 63) {
                musiccounter = 0;
            }

        }

        sleep();

  }
}
//****
void gameSetup()
{

    //drawRect(int x0,int y0,int width,int height,int fill)
    lcd.printString("Level:",0,0);
    lcd.printString("Score:",0,2);
    lcd.printString("0",0,1);
    lcd.printString("Next",0,4);


    //creats the game boarder
    lcd.drawRect(40,0,33,47,0);
    lcd.drawRect(41,1,31,46,0);
    lcd.refresh();

//fill gamearea add the walls

    for(int i = 0; i<12; i++) {
        for(int j = 0; j<16; j++) {
            gamearea[i][j] = 1;
        }
    }

    for(int i = 1; i<11; i++) {
        for(int j = 0; j<15; j++) {
            gamearea[i][j] = 0;
        }
    }
}
//**
void gamePixel(int x, int y)//***
{

    lcd.drawRect(42+(3*x),2+(3*y),2,2,1);
    lcd.refresh();
}
//**
void clearGamePixel(int x, int y)//***
{

    for(int i =0; i<3; i++) {
        for(int j =0; j<3; j++) {
            lcd.clearPixel(42+(x*3)+i,2+(3*y)+j);

        }
    }
    lcd.refresh();

}

void clearGame() //**
{

    for(int i = 0; i<30; i++) {

        for(int j = 0; j<45; j++) {

            lcd.clearPixel(42+i,2+j);
        }
    }
    lcd.refresh();
}

void gameInfo(int score,int level,int next)
{

    //outputs the level
    char buffer[6];
    int length = sprintf(buffer,"%d",level);
    if(length <=6) {
        lcd.printString("      ",0,1);
        lcd.printString(buffer,0,1);
    }
    //outputs the score
    length = sprintf(buffer,"%d",score);
    if(length <=6) {
        lcd.printString("      ",0,3);
        lcd.printString(buffer,0,3);
    }

    for(int i = 0; i <4; i++) { //clears the next piece shape before the new one is displayed
        for(int j = 0; j <2; j++) {
            clearGamePixel(-6+i,12+j);
        }
    }
    piecePlace(-6,12,shapes[next][0]) ;
}

void piecePlace(int x,int y,int shape)//***
{


    int count = 0;
    for(int i = 0; i<4; i++) {
        for(int j = 0; j<4; j++) {

            int bit = shape & (1<<count);

            if (bit) {
                gamePixel(j+x,i+y);
            }
            count++;
        }
    }
}

void pieceClear(int x,int y,int shape)//***
{
    int count = 0;
    for(int i = 0; i<4; i++) {
        for(int j = 0; j<4; j++) {

            int bit = shape & (1<<count);

            if (bit) {
                clearGamePixel(j+x,i+y);
            }
            count++;
        }
    }
}

bool movePossible(int xpos, int ypos, int orientation)//**
{

    if (orientation > 3) {
        orientation = 0;
    }
    int count = 0;

    for(int y = 0; y < 4; y++) {
        for(int x = 0; x < 4; x++) {

            int bit = shapes[currentshape][orientation] & (1<<count); //find the bit of each pixel

            count ++;

            if ((bit !=0) && (gamearea[xpos+x+1][ypos+y]!=0)) {
                return false;
            }
        }
    }

    return true;
}

void newpiece() //**
{
    orientation = 0; //set the orientation back to zero
    pieceposition[0] = 4; //sets the position back to the top
    pieceposition[1] = 0;

    //clearGame();
    //setGameArea();

    currentshape = nextshape[shapebagcounter];
    piecePlace(pieceposition[0],pieceposition[1],currentshape);//places the new piece


    if(shapebagcounter > 5) { //when counter becomes 6
        newShapeBag(); //a new bag is created
        shapebagcounter = 0;
        nextpiece = nextshape[0];
    } else {
        nextpiece = nextshape[shapebagcounter+1];
        shapebagcounter++; //incrimenst the counter
    }
    for(int j = 0; j<16; j++) {
        for(int i = 0; i<12; i++) {
            pc.printf("%d ",gamearea[i][j]);
        }
        pc.printf("\n");
    }
    gameInfo(score,level,nextpiece);
}

void newShapeBag() //**
{

    bool match = false;
    int newrandomnumber;

    nextshape[0] = rand()%7; //creates first random number

    for(int i = 1; i < 7; i++) {

        do {
            newrandomnumber = rand()%7;

            match = false; //set to false to end the do while if no match is found

            for(int j = 0; j < i; j++) {

                if (newrandomnumber == nextshape[j]) { //checks to see if number has already been chosen
                    match = true;// continue do while if a match is found
                    break; //end the for loop that is checking for a match
                }
            }
        } while(match);

        nextshape[i] = newrandomnumber; //set new found number into the newshape array
    }
}

void checkCompleteLine() //**
{

    int rowscomplete[4] = {0,0,0,0}; //max of 4 rows can be completed with a single block
    int rowscompletecounter = 0; //counter to place complete row in the array
    int sum = 0;
    bool rowtoremove = false;
    for(int y = 0; y <15; y++) { //searches through all the rows

        for(int x = 1; x<11; x++) {
            if(gamearea[x][y] == 1) {
                sum++; //counts how many filled cells
            }
        }
        if(sum == 10) { //if all 10 cells are full
            //pc.printf("%d complete \n",y);
            rowscomplete[rowscompletecounter] = y; //sets it as a completed row
            rowscompletecounter++;
            rowtoremove = true;
        }
        sum = 0;
    }
  

    if(rowtoremove) {//runs if a row is complete
        int prevlevel = level;
        level = int((completedlines/10)+1);

        if (prevlevel != level) {
            gamespeed = 0.8606*exp(-0.073*level);

            ticker.detach();
            setTicker(gamespeed);
        }
        removeCompleteLines(rowscomplete);
    }
    completedlines += rowscompletecounter;
    if(rowscompletecounter == 1) {
        score += 100;
    } else if(rowscompletecounter == 2) {
        score += 250;
    } else if(rowscompletecounter == 3) {
        score += 500;
    } else if(rowscompletecounter == 4) {
        score += 1000;
    }
}

void removeCompleteLines(int rowscomplete[4]) //**
{
    for(int i = 0; i<4; i++) { //loops throught the max 4 lines that have been completed
        if(rowscomplete[i] >0) {

            for(int j = 1; j<11; j++) { //delete complete row
                gamearea[j][rowscomplete[i]] = 0;
            }

            for(int j = rowscomplete[i]; j>0; j--) { //runs through all the rows to copy, j starts at deleted row
                for(int k = 1; k<11; k++) { //runs through all the numbers in the row
                    gamearea[k][j] = gamearea[k][j-1];
                }
            }
            for(int j = 1; j<11; j++) { //add zeros into the top line
                gamearea[j][0] = 0;
            }

        }
    }
     setGameArea();
}

void pieceToGameArray() 
{
    int count = 0;
    for(int y = 0; y<4; y++) {
        for(int x = 0; x<4; x++) {
            int bit = shapes[currentshape][orientation] & (1<<count);

            if (bit) {
                gamearea[pieceposition[0]+x+1][pieceposition[1]+y]=1;
            }
            count++;
        }
    }

}

void setGameArea()
{
    clearGame();//clears the area
    for(int x = 1; x<11; x++) {
        for(int y = 0; y<15; y++) {
            if(gamearea[x][y] == 1) {
                gamePixel(x-1,y); //x-1 because the gamearea array has 1's around the outside
            }
        }
    }
}

void setTicker(float time)
{
    ticker.detach();
    ticker.attach(&moveDownTicker, time);
}

void moveDownTicker()
{
    g_timer_flag = 1;
}
void left_isr()
{
    if(g_lefttimeout) {
        g_left = 1;
    }
}
void right_isr()
{
    if(g_righttimeout) {
        g_right = 1;
    }
}
void spin_isr()
{
    if(g_spintimeout) {
        g_spin = 1;
    }
}

void down_isr()
{
    if(g_downtimeout) {
        g_down = 1;
    }
}

void music_isr()
{
    g_music = 1;
}

void lefttimeout_isr()
{
    g_lefttimeout = 1;
}
void righttimeout_isr()
{
    g_righttimeout = 1;
}
void spintimeout_isr()
{
    g_spintimeout = 1;
}
void downtimeout_isr()
{
    g_downtimeout = 1;
}

/*
void movePieceRight()
{
    if(movePossible(pieceposition[0]-1,pieceposition[1],orientation)) {
    movePiece(1, 0,0);
    }
}
void movePieceLeft()
{
    if(movePossible(pieceposition[0]+1,pieceposition[1],orientation)) {
    movePiece(-1, 0,0);
    }
}
void spinPiece()
{
    if(movePossible(pieceposition[0],pieceposition[1],orientation+1)) {
            
    movePiece(0, 0,1);
    }
}

void movePieceDown()
{
    movePiece(0, 1,0);
}

void movePiece(int x, int y,int spin){
    pieceClear(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]);
    pieceposition[0]= pieceposition[0] - x;
    pieceposition[1]= pieceposition[1] + y;
    orientation = orientation + spin;
    if (orientation > 3){
        orientation = 0;
        }
    piecePlace(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]);
    }
    
*/