I simplified the library "ILI9225_TFT" provided by Arman Safikhani to better suit my needs in implementing a simple sliding puzzle game.
Diff: States.h
- Revision:
- 3:251e4d020501
diff -r cc93245bb6d0 -r 251e4d020501 States.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/States.h Fri Apr 27 07:33:56 2018 +0000 @@ -0,0 +1,193 @@ +#include "Fonts.h" + +//STATE 0 +//GLCD Displays the start screen - encouraging the player to start the game +//by displaying the message "PRESS SELECT TO START". +// +//Player must press the SELECT button to trigger the next STATE. +void greetingScreen() { + tft.clear(); + tft.setFont(Terminal12x16); + tft.drawText(60, 40, "PRESS", COLOR_RED); + tft.drawText(54, 65, "SELECT", COLOR_RED); + tft.drawText(77, 90, "TO", COLOR_RED); + tft.drawText(60, 115, "START", COLOR_RED); + + while(1) { + if(getPlayerInput(wirelessInput_Freq) == 6) //SELECT -> 6 + return; + } +} + +//STATE 1 +//GLCD encourages player to take a picture of something by displaying the +//message "SELECT TO TAKE PICTURE". +// +//Player must press the SELECT button to take a picture and trigger the next +//STATE. +void takePicture() { + tft.clear(); + tft.setFont(Terminal12x16); + tft.drawText(54, 40, "SELECT", COLOR_RED); + tft.drawText(77, 65, "TO", COLOR_RED); + tft.drawText(65, 90, "TAKE", COLOR_RED); + tft.drawText(50, 115, "PICTURE", COLOR_RED); + + while(1) { + if(getPlayerInput(wirelessInput_Freq) == 6) { //SELECT -> 6 + for(int index = 0; index < 19200; index++) + handlePixel(index, getNextPixel()); + return; + } + } +} + +//STATE 2 +//GLCD will display the picture taken in STATE 1 @ the bottom of the screen. +// +//Player input is ignored during this STATE. +void previewPicture() { + tft.clear(); + updatePuzzle(); +} + +//STATE 3 +//GLCD will display the message "SELECT > ACCEPT" atop "OR" atop +//"CANCEL > RETAKE" at the top of the screen. +// +//Player may press SELECT to continue (STATE 4) w| picture or CANCEL to retake +//the picture (STATE 1). +bool confirmPicture() { + tft.fillRectangle(0, 0, 175, 91, COLOR_BLACK); + tft.setFont(Terminal12x16); + tft.drawText(4, 8, "SELECT > ACCEPT", COLOR_RED); + tft.drawText(77, 33, "OR", COLOR_RED); + tft.drawText(4, 58, "CANCEL > RETAKE", COLOR_RED); + //printElementsInPicture(); + + while(1) { + if(getPlayerInput(wirelessInput_Freq) == 6) //SELECT -> 6 + return true; //Confirm the picture by returning true + else if(getPlayerInput(wirelessInput_Freq) == 7) //CANCEL -> 7 + return false; //Retake the picture by returning false + } +} + +//STATE 4 +//GLCD will display the message "LOADING" and keeps it there until the +//LPC1769 has finished shuffling the pieces in the background. When it is done, +//it will black out the screen, populate the 4x4 grid with the puzzle pieces, +//and start the player off at index 0 of the puzzle grid. +//Remark: 2 out of 16 of the puzzle pieces will be missing. There were 3 reasons +//that led us to this design choice: +//1) We had to remove, at the very least, 1 puzzle piece to make a classic +//sliding puzzle game. +//2) We desired that the sizeof(picture) << 32kB but we still wanted a colored +//image (i.e., 16 bit aray element) so we needed to get rid of 2 pieces to reach +//our goal. +//3) If puzzle piece positions for a classic sliding puzzle game are generated +//completely randomly then they are only solvable 50% of the time based off +//whether there is an even amount of permutations. There are applicable methods +//for only generating solvable puzzles but another (and easier) solution is to +//just remove a second puzzle piece. +// +//The player's button presses are ignored during this time. +void shufflePuzzle() { + tft.clear(); + tft.setFont(Terminal12x16); + tft.drawText(47, 40, "LOADING", COLOR_RED); + + shuffleGridIndices(); + + tft.clear(); + updatePuzzle(); + cursorIndex = 0; + highlightGridIndex(cursorIndex, false); +} + +//STATE 5 +//We wait for the player to press SELECT. If the player presses SELECT we must +//verify 2 characteristics about the target piece before we may trigger STATE 6: +//1) Target puzzle piece is NOT one of the 2 missing puzzle pieces. +//2) Target puzzle piece is NOT locked on all 4 sides. +// +//At this point, the player is able to use the UP, DOWN, LEFT, and RIGHT buttons +//to move around their cursor until they find a piece that they want to swap +//for another piece. While their cursor is hovering over the target piece, they +//would press SELECT to "grab it". The cursor is green in this state. +uint8_t selectionMode() { + highlightGridIndex(cursorIndex, false); + //printElementsInPicture(); + while(1) { + if(getPlayerInput(wirelessInput_Freq) == 6) { //SELECT -> 6 + if(selectionMode_indexVerified(cursorIndex)) //& index verified + return cursorIndex; + } + else if(getPlayerInput(wirelessInput_Freq) == 2 //UP -> 2 + && cursorIndex - 4 > -1) + highlightGridIndex(cursorIndex - 4, false); + else if(getPlayerInput(wirelessInput_Freq) == 3 //DOWN -> 3 + && cursorIndex + 4 < 16) + highlightGridIndex(cursorIndex + 4, false); + else if(getPlayerInput(wirelessInput_Freq) == 4 //LEFT -> 4 + && ((cursorIndex%4) - 1) > -1) + highlightGridIndex(cursorIndex - 1, false); + else if(getPlayerInput(wirelessInput_Freq) == 5 //RIGHT -> 5 + && ((cursorIndex%4) + 1) < 4) + highlightGridIndex(cursorIndex + 1, false); + } +} + +//STATE 6 +//If player presses UP, DOWN, LEFT, or RIGHT, we verify that target index is an +//empty space before making the move and triggering STATE 5. A piece may only be +//moved 1 index position and it may only be moved to 1 of the 2 missing puzzle +//piece indices. +// +//Only UP, DOWN, LEFT, RIGHT, and CANCEL are monitored during this state. +//Pressing CANCEL, at any time, would restore us back to STATE 5 and no swapping +//would occur. The cursor is red in this state. +void selectedMode(uint8_t selectedIndex) { + highlightGridIndex(selectedIndex, true); + + while(1) { + if(getPlayerInput(wirelessInput_Freq) == 7) //CANCEL -> 7 + return; + if(getPlayerInput(wirelessInput_Freq) == 2 //UP -> 2 + && selectedIndex - 4 > -1) { + if(puzzState[selectedIndex - 4] > 13) { //Empty space above? + swap(&puzzState[selectedIndex], &puzzState[selectedIndex - 4]); + updatePuzzle(); + cursorIndex = selectedIndex - 4; + return; + } + } + if(getPlayerInput(wirelessInput_Freq) == 3 //DOWN -> 3 + && selectedIndex + 4 < 16) { + if(puzzState[selectedIndex + 4] > 13) { //Empty space below? + swap(&puzzState[selectedIndex], &puzzState[selectedIndex + 4]); + updatePuzzle(); + cursorIndex = selectedIndex + 4; + return; + } + } + if(getPlayerInput(wirelessInput_Freq) == 4 //LEFT -> 4 + && ((selectedIndex%4) - 1) > -1) { + if(puzzState[selectedIndex - 1] > 13) { //Empty space to the left? + swap(&puzzState[selectedIndex], &puzzState[selectedIndex - 1]); + updatePuzzle(); + cursorIndex = selectedIndex - 1; + return; + } + } + if(getPlayerInput(wirelessInput_Freq) == 5 //RIGHT -> 5 + && ((selectedIndex%4) + 1) < 4) { + if(puzzState[selectedIndex + 1] > 13) { //Empty space to the right? + swap(&puzzState[selectedIndex], &puzzState[selectedIndex + 1]); + updatePuzzle(); + cursorIndex = selectedIndex + 1; + return; + } + } + } +} \ No newline at end of file