ELEC2645 Joseph Allison 200860349
Dependencies: N5110 Tetris mbed
main.cpp
- Committer:
- el14ja
- Date:
- 2016-05-05
- Revision:
- 6:9cb8171ca6df
- Parent:
- 4:7160c74529f7
- Child:
- 7:dfb290c7958c
File content as of revision 6:9cb8171ca6df:
/* 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 implement collision detection easter - colliosn detection - piece placement - scoring - levels and game speed changing - Game Complete week 24 - All bugs removed */ #include "main.h" int main() { srand(floor(ain.read()*10000)); //Gets a random seed so the the random number generator creates a different set of random numbers each time the game is played lcd.init(); //initilises the screen setupInterruptInputs(); newShapeBag();//create bag of shapes to use nextpiece = nextshape[1]; //initially sets the next piece tetris.gameInfo(0,1,nextpiece); musicticker.attach(&music_isr,0.125); //sets the speed that the music plays setTicker(gamespeed); //sets the speed that the block falls while (true) { gameMenu(); if(musicplaying) { //checks to see if the music is playing buzzer.write(0.5); } else { buzzer.write(0); } score = 0; //sets all game varibles to default values level = 1; completedlines = 0; //resests the game screen setGameAreaArray(); tetris.clearGame(); tetris.gameSetup(); tetris.gameInfo(score,level,nextpiece); while(gameplaying) { //loops throught the gane function whilst the game is running checkGameFlags(); sleep(); } gameOverScreen(); //when the game is over the game over screen is played //sets the game and game menu to run the next time ot come to them gameplaying = true; gamemenu = true; } } void gameMenu() { int pointer = 0; //sets the pointer to its inital place lcd.clear(); lcd.refresh(); while(gamemenu) { //sets the menu text lcd.printString("PLAY",15,1); lcd.printString("MUSIC",15,3); lcd.printString("HELP",15,5); //checks the state fo the music to set the on/off label if(musicplaying) { lcd.printString(" ",50,3); lcd.printString("ON",50,3); } else { lcd.printString("OFF",50,3); } lcd.refresh(); //checks the down button to move the pointer down if(g_down) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; if(pointer < 2) { //the max pos is 2 so the point doesnt move any lower pointer++; } } //checks the spin button to move the pointer up if(g_spin) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; if(pointer >0) { //0 is the lower pointer pos pointer--; } } //selects option 0 if the pointer is there and left is pressed //selects main menu if(g_left && pointer == 0) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; gamemenu = false; } //selects option 1 if the pointer is there and left is pressed //turns music on if(g_left && pointer == 1) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; if(!musicplaying) { musicplaying = true; } else { musicplaying = false; } lcd.refresh(); } //selects option 2 if the pointer is there and left is pressed //selects the help screen if(g_left && pointer == 2) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; helpScreen(); } for(int i = 0; i<4; i++) { //clear the points before the new one is places for(int j = 10; j < 50; j++) { lcd.clearPixel(70+i,j); } } lcd.drawRect(70,10+ (pointer *16),3,3,0); //draws pointer on the screen lcd.refresh(); sleep(); } //set all the flags to zero before the game starts } void gameOverScreen() { bool gameoverscreen = true; lcd.clear(); lcd.printString("GAME OVER",15,1); //prints the score on the screen char buffer[14]; int length = sprintf(buffer,"Score = %d",score); if(length <=14) { lcd.printString(buffer,0,3); lcd.refresh(); } while (gameoverscreen) { //waits for any button to be pressed to leave the game over screen if(g_left || g_right || g_spin || g_down) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; gameoverscreen = false; lcd.clear(); } sleep(); } } void helpScreen() { // help screen 1 bool helpScreen = true; lcd.clear(); //prints screen text lcd.printString("Move pieces",0,0); lcd.printString("with the D-pad",0,1); lcd.printString("to create rows",0,2); lcd.printString("Press any",0,4); lcd.printString("button",0,5); lcd.refresh(); //waits for any button to be pressed while (helpScreen) { if(g_left || g_right || g_spin || g_down) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; helpScreen = false; lcd.clear(); } sleep(); } // help screen 2 helpScreen = true; lcd.clear(); //prints screen text and images lcd.drawCircle(42,5,4,0); lcd.drawCircle(31,16,4,0); lcd.drawCircle(53,16,4,0); lcd.drawCircle(42,26,4,0); lcd.printString("Spin",5,0); lcd.printString("Left",2,2); lcd.printString("Right",55,0); lcd.printString("Drop",60,3); lcd.drawLine(29,4,42,5,1); //spin lcd.drawLine(53,5,53,16,1); //right lcd.drawLine(25,19,31,16,1); //left lcd.drawLine(58,27,42,26,1); //drop lcd.printString("Press any",0,4); lcd.printString("button",0,5); lcd.refresh(); //waits for any button to be pressed while (helpScreen) { if(g_left || g_right || g_spin || g_down) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; helpScreen = false; lcd.clear(); } sleep(); } // help screen 3 helpScreen = true; lcd.clear(); //prints screen text lcd.printString("Press left and",0,0); lcd.printString("right together",0,1); lcd.printString("to pause the",0,2); lcd.printString("game",0,3); lcd.printString("Press any",0,4); lcd.printString("button",0,5); lcd.refresh(); //waits for any button to be pressed while (helpScreen) { if(g_left || g_right || g_spin || g_down) { g_left = 0; g_right = 0; g_spin = 0; g_down = 0; helpScreen = false; lcd.clear(); } sleep(); } } void checkGameFlags() { if(g_pausemenu) { //if both left and right havent been pressed within 0.1s both flags are reset to 0 g_pausemenu = 0; pauseright = 0; pauseleft = 0; } //checks if both left and right have been pressed at the same time if(pauseright && pauseleft) { pauseright = 0; pauseleft = 0; lcd.clear(); lcd.printString("PAUSE",27,2); lcd.refresh(); buzzer.write(0.0); //silences music while on the pause menu while(1) { //waits in a loop til the both left and right are pressed if(pauseright && pauseleft) { pauseright = 0; pauseleft = 0; break; } sleep(); } //sets all flags to 0 incase they are pressed during the pause screen g_left = 0; g_right = 0; g_spin = 0; g_down = 0; if(musicplaying) { //trubs music back on buzzer.write(0.5); } else { buzzer.write(0); } //resets the game area setGameArea(); tetris.piecePlace(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]); } //checks if a new piece need placing in the game if(g_newpiece) { g_newpiece = 0; newpiece(); } //checks if the right button has been pressed if(g_right) { g_right = 0; movePieceRight(); } //checks if the left button has been pressed if(g_left) { g_left = 0; movePieceLeft(); } //checks the game time to see if the piece needs moving down if (g_timer_flag) { g_timer_flag = 0; //checks if there is a place for the piece to move down to, if not the piece is placed if(movePossible(pieceposition[0],pieceposition[1]+1,orientation)) { //returns false if piece cant move down movePieceDown(); } else { //piece placed g_newpiece = 1; //a new piece is needed as the last one is placed pieceToGameArray(); //adds the placed piece to the game area if(harddropping) {//if piece has been placed after a hard drop the game speed is set back to normal harddropping = 0; setTicker(gamespeed); } //if a piece has been placed, it needs to be check to see if a full line is complete checkCompleteLine(); setGameArea(); } } if(g_spin) { g_spin = 0; spinPiece(); } if(g_down) { g_down = 0; //when hard dropping the drop ticker is spead up setTicker(0.001); harddropping = 1; } if(g_music) { g_music = 0; buzzer.period_us(musisnotes[musiccounter]); //play the note in the musicnotes musiccounter++; //incriments the music counter if(musiccounter > 63) { musiccounter = 0; } } } void setupInterruptInputs(){ //internal resistors set to pull down so that when the button is pressed the voltage is read as high left.mode(PullDown); right.mode(PullDown); spin.mode(PullDown); down.mode(PullDown); //sets the the interrupts to be called when the button is pressed down left.rise(&left_isr); right.rise(&right_isr); spin.rise(&spin_isr); down.rise(&down_isr); } void setGameAreaArray() { //fill gamearea add the walls //sets 1's around the bottoms and sides for(int i = 0; i<12; i++) { for(int j = 0; j<16; j++) { gamearea[i][j] = 1; } } //fills the middle with 0's for(int i = 1; i<11; i++) { for(int j = 0; j<15; j++) { gamearea[i][j] = 0; } } } bool movePossible(int xpos, int ypos, int orientation) { if (orientation > 3) { orientation = 0; } int count = 0; //counter to count through all 16 bits 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)) { //compares each pixel of the piece witht he game array to check for collisions 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]; //gets the next shape to place on the screen tetris.piecePlace(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]);//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 } tetris.gameInfo(score,level,nextpiece); if(!movePossible(pieceposition[0],pieceposition[1]+1,orientation)) {//if a piece is placed and imidiatly cant move the game is over gameplaying = false; } } void newShapeBag() { bool match = false; int newrandomnumber; nextshape[0] = rand()%7; //creates first random number for(int i = 1; i < 7; i++){ //loops to find all 7 numbers 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; } completedlines += rowscompletecounter; //adds the new completed rows to the row total 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); //the game speed is set depending on the level setTicker(gamespeed); } removeCompleteLines(rowscomplete); } //increases the score depending on the number of rows complete 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; } } } } void pieceToGameArray() { int count = 0; //looks through the 16 bits of the shape for(int y = 0; y<4; y++) { for(int x = 0; x<4; x++) { int bit = shapes[currentshape][orientation] & (1<<count); //finds the bits of each shape if (bit) { gamearea[pieceposition[0]+x+1][pieceposition[1]+y]=1; //sets the shape in the game area array } count++; } } } void setGameArea() { tetris.clearGame();//clears the area for(int x = 1; x<11; x++) { //loops through the whole game array for(int y = 0; y<15; y++) { if(gamearea[x][y] == 1) { tetris.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 left_isr() { if(g_lefttimeout) { g_left = 1; g_lefttimeout = 0; pauseleft = 1; lefttimeout.attach(&lefttimeout_isr,0.15); //sets the timeout so the button cant be pressed in quick sucsession pausemenu.attach(&pausemenu_isr,0.09); //sets timeout for the detection of both left and right pressed at the same time } } void right_isr() { if(g_righttimeout) { g_right = 1; g_righttimeout = 0; pauseright = 1; righttimeout.attach(&righttimeout_isr,0.15);//sets the timeout so the button cant be pressed in quick sucsession pausemenu.attach(&pausemenu_isr,0.09); //sets timeout for the detection of both left and right pressed at the same time } } void spin_isr() { if(g_spintimeout) { g_spin = 1; g_spintimeout = 0; spintimeout.attach(&spintimeout_isr,0.15);//sets the timeout so the button cant be pressed in quick sucsession } } void down_isr() { if(g_downtimeout) { g_down = 1; g_downtimeout = 0; downtimeout.attach(&downtimeout_isr,0.4);//sets the timeout so the button cant be pressed in quick sucsession } } //ISR's and flag setting void moveDownTicker() { g_timer_flag = 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 pausemenu_isr() { g_pausemenu = 1; } //each move position it checks if the piece can be moved there and then moves them 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) { tetris.pieceClear(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]); //clears the piece before the piece is moved //changes the piece position or orientation pieceposition[0]= pieceposition[0] - x; pieceposition[1]= pieceposition[1] + y; orientation = orientation + spin; if (orientation > 3) { orientation = 0; } tetris.piecePlace(pieceposition[0],pieceposition[1],shapes[currentshape][orientation]); //resets the piece }