v1.0

Dependencies:   LCDTFT TFT_fonts mbed

snake_main_game.cpp

Committer:
trapsis
Date:
2016-06-10
Revision:
0:5c5a85d917be

File content as of revision 0:5c5a85d917be:

//ssd0139 LCD display
#include "mbed.h"
#include "LCDTFT.h"
#include "Arial28x28.h"

PortOut MyPort(PortD ,0xFF); // define a port with only the lower 8 bits included - that'llbe PTD0-PTD7 making a single 8 bit port.
LCDTFT  MyLCD(PTB0,PTB1,PTB2,PTB3,PTC2,&MyPort);//LCDTFT(PinName PIN_RD,PinName PIN_WR,PinName PIN_RS,PinName PIN_CS,PinName PIN_RESET, PortOut *PORTLCD);
Serial pc(USBTX,USBRX); // terminal for debuggin purposes
bool GameRunning = 1; //establish if the game is running

void run();
void countdown();
void changeDirec();
void nextmove();
void initGrid();
void updateGrid();
void drawGrid();
void checkposition();
void gameover1();
void gameover2();
void PrettyPrint(char *message,const unsigned char *font,short xpos,short ypos,short bcol, short fcol);
void prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol);

int NowTime =7;
int StartTime=1;
//time variables over from Dan's program

const int gridWidth = 64;
const int gridHeight = 48;
char grid [48][64];
char snake [2][255];
//represent the grid as a 2 dimensional array

char newDirectSnake = 3;
char newDirectFood = 2;
char newFoodVel = 0;
//incoming values from the controller

int snakexpos = 20;
int snakeypos = 20;
char directSnake = 3;
char snakeSize = 3;
//establish values for the snake

int foodxpos = 2;
int foodypos = 20;
char foodvel = 1;
char directFood = 1;
//establish values for the food

char message [32];
//for printing purposes

int framecount = 0;
//number of iterations in the main loop



// next two functions need moving to the library.....
// ok - a simple sub to put in a character from the fonts defined in TFT_fonts
// c= charactetr to put
// font = pointer to font to use
// x,y locatoin of bottom lh of character, bcol = background color, fcol = foreground color
//prettyputc("m",Arial12x12,50,50,ColorBlack,ColorWhite);
void prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
{
    // Length,horz,vert,byte/vert
    int length,hor,vert,bpver; // number of bytes per character, horizontal pixels, vertical pixels and bytes per column
    //
    int x,y,i,j,k,ptr;
    short coltowrite;
    char byte,point;
    length=font[0];
    hor=font[1];
    vert=font[2];
    bpver=font[3];
    for(i=0; i<hor; i++) { // loop over columns
        for(j=0; j<vert; j++) {
            x=xpos+i;
            y=ypos+j; // NB assumes colums stored from bottom to top.... ?
            ptr=((c -32) * length+1) + 4+i*bpver+(j/8);  // pointer in font array to start of the character we want +1 to avoid the first byte that holds the char width
            byte=(char)font[ptr];
            k=j%8; // number of the pixel in this byte
            point=byte & (1<<k); // get the next bit
            if(point>0) {
                coltowrite=fcol;
            } else {
                coltowrite=bcol;
            }

            MyLCD.vLCDTFTPoint(x,y,coltowrite);

        }
    }

}




// ok now a function to use pretty putc to write strings whose bottom left corner are at xpo,ypos
// general idea is that the string is first formatted byb sprintf and the PrettyPrint is called
// bcol and fcol are the backgroun adn foreground colors
//NB max message length = 64 characters
void PrettyPrint(char *message,const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
{
    short x,y,messlength,i,ptr;
    messlength=strlen(message);
    if (messlength >64) messlength=64;  // avoid writing too large a string....
    x=xpos;
    for(i=0; i<messlength; i++) {
        // x=xpos+i*(font[1]*8/10); // font[1]=char width 80% to avoid gaps
        //pointer = &font[((c -32) * offset) + 4]; // start of char bitmap
        // w = pointer[0];                          // width of actual char
        ptr=((message[i] -32) * font[0]) + 4;

        y=ypos; // will have to add cod and more to deal with different screen orientations
        //prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
        prettyputc(message[i],font,x,y,bcol,fcol);
        x=x+font[ptr]+2;
    }

}


void run()
//the main game program
{
    while (1) {
        if (GameRunning == 1) {
           // countdown();
            initGrid();
            while (1) {
               
                
                checkposition();
                changeDirec();
                nextmove();
                updateGrid();
                drawGrid();
                framecount++;
            }
        }
    }

}


void countdown()
//countdown before game begins
{
    MyLCD.vLCDTFTInit(1);
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    sprintf(message,"Get Ready!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"3");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"2");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"1");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"Run!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

}

void initGrid()
//initialize the grid
{
    MyLCD.vLCDTFTInit(1);
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
            grid[x][y] = 0;
        }
    }
    //initialize the pixel grid as an array of zeros
    snake[0][0] = snakexpos;
    snake[1][0] = 20;
    snake[0][1] = 21;
    snake[1][1] = 20;
    snake[0][2] = 22;
    snake[1][2] = 20;

     for(int i=3; i<255; i++) {
        grid[snake[1][i]][snake[0][i]] = 0;
    }
    //initialize the snake as horizontal with respect to its initial size (1 = tile occupied by snake)

    grid[foodypos][foodxpos] = 2;
    //initialize the food (2 = tile occupied by food)
}

void updateGrid()
//update the grid with positions
{
    if (grid[snakexpos][snakeypos] == 1)
    gameover2();
        else
        {
            
        for(int a=snakeSize-2; a>=0; a--) {

         snake[0][a+1] = snake [0][a];
         snake[1][a+1] = snake [1][a];
        }
        
        snake[0][0] = snakexpos;
        snake[1][0] = snakeypos;
    }

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
            grid[x][y] = 0;
        }
    }

    for(int i=0; i<snakeSize; i++) {
        grid[snake[1][i]][snake[0][i]] = 1;

    }
    //update the snake, if the tile was previously occupied, snake has hit itself = gameover2

    if (grid[foodypos][foodxpos] == 1) {
        gameover1();
    }

    else {
        grid[foodypos][foodxpos] = 2;
    }
    //update the food, if the tile was previously occupied, food has hit snake = gameover1
}


void drawGrid()
//draw the grid
{

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
          /*  if (grid[x][y] == 0) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorBlack);
            }
            */
            if (grid[x][y] == 1) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorBlue);
            }
            if (grid[x][y] == 2) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorWhite);
            }
        }
    }

     wait (0.1); //the game is 10fps (up for discussion we'll see how this goes)
}

void changeDirec()
//changing direction, the command will have to come from the controller program
//assume 0 for up, 1 for right, 2 for down, 3 for left
{
    foodvel = newFoodVel;
    directFood  =  newDirectFood;
    //assign new direction and speed to food

    if ((newDirectSnake + directSnake)%2 == 0 && newDirectSnake != directSnake)
    gameover2();
    //the snake loses if it tries to double up on itself

    else
    directSnake =  newDirectSnake;
    //assign new direction to snake
}

void nextmove()
//move the snake and the food by incrementing their coordinates (for the food increment by velocity)
{
    if (framecount%5 == 0){
        snakeSize++;
        }
    // every 5 iterations, the snake grows
   
    
    MyLCD.vLCDTFTRectangle(5*foodxpos,5*foodypos,5*foodxpos+5,5*foodypos+5,1,ColorBlack);
    MyLCD.vLCDTFTRectangle(5*snake[0][snakeSize-1],5*snake[1][snakeSize-1],5*snake[0][snakeSize-1]+5,5*snake[1][snakeSize-1]+5,1,ColorBlack);

    
    if (directFood == 0) {
        foodypos -= foodvel;
    }
    if (directFood == 1) {
        foodxpos += foodvel;
    }
    if (directFood == 2) {
        foodypos += foodvel;
    }
    if (directFood == 3) {
        foodxpos -= foodvel;
    }
    // check the direction of food and increment position according to velocity

    if (directSnake == 0) {
        snakeypos -= 1;
    }
    if (directSnake == 1) {
        snakexpos += 1;
    }
    if (directSnake == 2) {
        snakeypos += 1;
    }
    if (directSnake == 3) {
        snakexpos -= 1;
    }

}

void checkposition()
//check position to see if either player is out of bounds
{
    if (snakeypos > gridHeight || snakeypos < 0)
        gameover2();

    if (snakexpos > gridWidth || snakexpos < 0)
        gameover2();

    if (foodypos > gridHeight || foodypos < 0)
        gameover1();

    if (foodxpos > gridWidth || foodxpos < 0)
        gameover1();

    //end the game with the appropriate game over screen if either player is out of bounds
}


void gameover1()
//print game over message and display final score
{
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    sprintf(message,"You are snake food!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);

    sprintf(message,"Survival Time:");
    PrettyPrint(message,Arial28x28,10,100,ColorBlack,ColorLime);
    wait (1000);

    GameRunning = 0;
}

void gameover2()
//an alternate ending is that the snake has made a mistake and that the food wins
{
    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"The snake is dead!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait (1000);

    GameRunning = 0;
}


int main()
{
    run();
}