Su 200943147

Dependencies:   Gamepad N5110 mbed

Engine/Engine.cpp

Committer:
GS00
Date:
2017-05-04
Revision:
9:6ee4c806f3e9

File content as of revision 9:6ee4c806f3e9:

#ifndef ENGINE_H
#define ENGINE_H

#include "Engine.h"

Engine::Engine()
{
}

//initialise each variable and start the game
void Engine::Init(N5110 &lcd)
{
    _Shape.Init();
    Boundary();

    BottomCollision=0;
    LeftSideCollision=0;
    RightSideCollision=0;
    NEW=0;
    AddScore=0;
    Score=0;
    ScoreDisplay=0;
}

/** ReadInput
*
* Read the input from the microcontroller
*/
void Engine::ReadInput(Gamepad &pad)
{
    d = pad.get_direction();  //direction
}

/** Update
*
* A function contain all the function of the game
*/
void Engine::Update(N5110 &lcd,Gamepad &pad)
{
    _Shape.Rotate(pad);
    _Shape.Update(pad);
    CollisionCheck();
    Movement(pad);
    Dropping(pad);
    if(NEW==1) {
        NEW=0;
        NewBlock();
    }
    DeleteLine();
    GameOver(lcd,pad);
    Scores(lcd);
}

/** Pixel
*
* Print the array into screen
*/
void Engine::Pixel(N5110 &lcd)
{
    for(int i=0; i<84; i++) {
        for(int j=0; j<48; j++) {
            if(_Shape.ShapeArray[i][j]==1) {
                lcd.setPixel(i,j);               //Print the shape onto lcd
            }
            if(FillArray[i][j]==1) {
                lcd.setPixel(i,j);               //Print the boundary/game state onto lcd
            }
        }
    }
    lcd.refresh();                               //refresh the screen
    lcd.clear();
}

/** Boundary
*
* Set the game plane area
*/
void Engine::Boundary()
{
    for(int i=0; i<84; i++) {                 //boundary condiction
        for(int j=0; j<48; j++) {
            FillArray[0][j]=1;
            FillArray[29][j]=1;
        }
    }
}

/** CollisionCheck
*
* Chech if the moving block collide with the boundary or
* other block in the game. When it happen set a flag(e.g command)
* for the following function
*/
void Engine::CollisionCheck()
{
    for(int i=0; i<84; i++) {
        for(int j=0; j<48; j++) {
            if(_Shape.ShapeArray[i][j]==1) {         //searching for bottom collision
                if(FillArray[i][j+1]==1) {
                    BottomCollision=1;               //set the flag
                }
            }
            if(_Shape.ShapeArray[i][47]==1) {        //check if the shape block hit the bottom of the game
                BottomCollision=1;                   //set the flag
            }
        }
    }
    for(int i=0; i<84; i++) {
        for(int j=0; j<48; j++) {
            if(FillArray[i][j]==1) {                  //check if the shape hit the left side of the boundary
                if(_Shape.ShapeArray[i+1][j]==1) {    //by compare the shape array with boundary array
                    LeftSideCollision=1;              //set the flag
                }
            }
            if(FillArray[i+1][0]==1) {               //check if the shape hit the right side of the boundary
                if(_Shape.ShapeArray[i][j]==1) {     //by compare the shape array with boundary array
                    RightSideCollision=1;            //set the flag
                }
            }
        }
    }
    //printf("BottomCollision=%d\n",BottomCollision);
    //printf("LeftCollision=%d\n",LeftSideCollision);
    //printf("RightCollision=%d\n",RightSideCollision);
}

/** Movement
*
* The direction of horizontal movement is control by the joystick,
* it shift pixel by pixel depend on the joystick direction
*/
void Engine::Movement(Gamepad &pad)
{
    if(d == W) {
        if(LeftSideCollision==1) {         //if collision occured left movement stop
            _Shape.x=_Shape.x;             //stop movement
            LeftSideCollision=0;           //clear flag
        } else {                           //no collision, movement continue
            _Shape.x=_Shape.x-1;           // move to the left
        }

    } else if(d == E) {
        if(RightSideCollision==1) {        //if collision occured left movement stop
            _Shape.x=_Shape.x;             //stop movement
            RightSideCollision=0;          //clear flag
        } else {                           //no collision, movement continue
            _Shape.x=_Shape.x+1;           //move to the right
        }
    }
   // printf("x=%d\n",_Shape.x);
}

/** Dropping
*
* Create the falling of each block of shape
* if collision occurred as it receive the flag command
* it stop the block of shape from falling
*/
void Engine::Dropping(Gamepad &pad)
{
    if(BottomCollision==1) {                //if collision occured stop dropping
        BottomCollision=0;                  //clear flag
        _Shape.y=_Shape.y;                  //stop moving
        NEW=1;                              //Set a new flag
        AddScore=1;                         //Set a new flag
        pad.tone(400.0,0.1);                //sound feedback
    } else {
        _Shape.y=_Shape.y+1;                //continue dropping
    }
    //printf("y=%d\n",_Shape.y);
}

/** SaveBlock
*
* Save the block of shape into a array
*/
void Engine::SaveBlock()
{
    for(int i=0; i<84; i++) {
        for(int j=0; j<48; j++) {
            if(_Shape.ShapeArray[i][j]==1) {                 //when there is a one in the shape array save to the game array
                FillArray[i][j]=_Shape.ShapeArray[i][j];
            }
        }
    }
    for(int i=0; i<84; i++) {
        for(int j=0; j<48; j++) {
            _Shape.ShapeInit[i][j]=0;                         //clear both array for new block
            _Shape.ShapeArray[i][j]=0;
        }
    }
}

/** NewBlock
*
* Generate a new block when current block is in place
*/
void Engine::NewBlock()
{
    SaveBlock();                               //run this function
    _Shape.x= 0;                               //clear variable x
    _Shape.y= 0;                               //clear variable y
    _Shape.New=0;                              //clear flag
    _Shape.ShapePicker();                      //run this function
}

/** Gameover
*
* Check the state of the game
* When the game is over show on the lcd display
*/
void Engine::GameOver(N5110 &lcd,Gamepad &pad)
{
    for(int i=1; i<29; i++) {
        if(FillArray[i][2]==1) {
            for(int i=0; i<84; i++) {
                for(int j=0; j<48; j++) {
                    FillArray[i][j]=0;
                    _Shape.ShapeArray[i][j]=0;                //clear everything when game is over
                    _Shape.ShapeInit[i][j]=0;
                }
            }
            while(1) {
                lcd.printString("Game Over",2,2);             //print to screen
                lcd.refresh();                                //refresh the screen
                pad.leds_on();                                //led on
                wait(0.1);                                    //time delay
                pad.leds_off();                               //led off
                wait(0.1);                                    //time delay
                pad.tone(200.0,0.1);                          //sound feedback
            }
        }
    }
}

/** DeleteLine
*
* Delete the row when it is full
*/
void Engine::DeleteLine()
{
    int j;
    for(j=0; j<48; j++) {
        for(int i=1; i<29; i++) {
            if(FillArray[i][j]==1) {
                Pixels++;                             //count the pixel
            }
          //  printf("Pixels=%d\n",Pixels);
        }
        if(Pixels==28) {
            for(int i=1; i<29; i++) {
                FillArray[i][j]=0;                    //delete the specific line when it is full
            }
            for(int y=j-1; y>-1; y--) {
                for(int x=1; x<29; x++) {
                    FillArray[x][y+1]=FillArray[x][y]; //move a row down
                }
            }
            Pixels=0;                                  //clear the number of pixel
            Score=Score+7;                             //add a score of 7 when the line delete
          //  printf("Score=%d\n",Score);
        } else {
            Pixels=0;                                  //clear the number of pixel
        }
    }
}

/** Scores
*
* Each block has a score of one and show on the screen
*/
void Engine::Scores(N5110 &lcd)
{
    if(AddScore==1) {
        AddScore=0;
        CurrentScore=0;
        for(int i=1; i<29; i++) {
            for(int j=0; j<48; j++) {
                if(FillArray[i][j]==1) {
                    CurrentScore=CurrentScore+1;             //one block has a score of one
                }
            }
        }
    }
    ScoreDisplay=Score+CurrentScore/4;                       //score calculation system
  //  printf("ScoreDisplay=%d\n",ScoreDisplay);

    char buffer[14];                                         //create a buffer to store data
    sprintf(buffer,"%2d",ScoreDisplay);                      //print the buffer with relative variable
    lcd.printString("Tetris",45,1);
    lcd.printString("Score",50,3);                           
    lcd.printString(buffer,55,4);                            //print the score to the screen
}
#endif