Final Project - Bop It
Dependencies: mbed wave_player 4DGL-uLCD-SE SDFileSystem_1 MMA8452
main.cpp
- Committer:
- ocrank3
- Date:
- 2019-12-09
- Revision:
- 0:b04853f39afa
File content as of revision 0:b04853f39afa:
#include "mbed.h" #include "MMA8452.h" #include "wave_player.h" #include "SDFileSystem.h" #include <ctime> #include <iostream> #include <string> #include <vector> #include <algorithm> #include <sstream> #include "uLCD_4DGL.h" #define YELLOW 0xF1C40F /* Instantiate devices */ uLCD_4DGL uLCD(p13,p14,p11); DigitalIn bop(p21); AnalogIn twist(p19); AnalogIn slide(p20); SDFileSystem sd(p5, p6, p7, p8, "sd"); AnalogOut DACout(p18); wave_player player(&DACout); Serial pc(USBTX,USBRX); // setup for accelerometer RawSerial dev(p28,p27); MMA8452 accel(p9, p10, 100000); // use for accelerometer /* variables for reading in textfile */ char myString[256]; char delim[] = ":"; string nameOfPlayer = ""; /* game data */ enum states {name, diffLevel, randomNum, replay, play} state; double timeLimit = 3; // this is set by the difficulty level in seconds double decrement; bool gameDone = false; int score = 0; int seed = 0; double twistStart; double slideStart; double xStart, yStart, zStart, xCurr, yCurr, zCurr; struct Players{ string name; int score; }; /* Instantiate struct of players array */ vector<Players> playersVec; bool cmp(Players i , Players j) { return i.score > j.score; } /* prints "Welcome to Bop It!" on the uLCD */ void printWelcome() { uLCD.cls(); uLCD.text_width(2); //2X size text uLCD.text_height(2); uLCD.locate(0,2); uLCD.printf(" Welcome "); uLCD.locate(0,4); uLCD.printf(" To "); uLCD.locate(0,6); uLCD.printf(" Bop It! "); } /* prinf the command on the uLCD */ void printCommand(char *command, int color) { uLCD.cls(); uLCD.text_width(2); //2X size text uLCD.text_height(3); uLCD.locate(0, 2); uLCD.color(color); uLCD.printf(command); } /* reads the text file, puts in Vector, Sorts Vector opens file and reads until end */ void readTextFile() { FILE *fp = fopen("/sd/sdtest.txt", "r"); while (!feof(fp)) { fgets(myString, 256, fp); char *token = strtok(myString, delim); while (token != NULL) { string currName = token; token = strtok(NULL,delim); int currScore = atoi(token); token = strtok(NULL, delim); //Instatiates vector of currPlayer objects, Pushes into the Vector, and Sorts by Score as Pushing Players currPlayer = {currName, currScore}; playersVec.push_back(currPlayer); sort(playersVec.begin(), playersVec.end(), cmp); } } fclose(fp); } /* Reads the Vec of Player objects, takes in teh name from the phone user's name input, and reorders and rewrites to the text file */ void updateHighScore(string newName, int newScore) { Players addPlayer = {newName, newScore} ; playersVec.push_back(addPlayer); sort(playersVec.begin(), playersVec.end(), cmp); playersVec.erase(playersVec.begin() + 5); string outputString; dev.printf("\nHIGHSCORES:\n"); for (int i = 0; i < 5; i++) { dev.printf("%s : %d\n\r", playersVec[i].name, playersVec[i].score); char myNum[80]; sprintf(myNum, "%d", playersVec[i].score); outputString += ":"; outputString += playersVec[i].name; outputString += ":"; outputString += myNum; } pc.printf("%s", outputString); FILE *fp = fopen("/sd/sdtest.txt", "w"); fprintf(fp, "%s", outputString); fclose(fp); } /* Bluetooth interupt handler Records the user's inputs */ void dev_recv() { char currChar; if (state == name) { while(dev.readable()) { currChar = (char) dev.getc(); pc.printf("state = 0, currChar = @%c\n\r", currChar); if (currChar == '\n') { // end of user input state = diffLevel; dev.printf("ENTER DIFFICULTY LEVEL (1, 2, 3)"); pc.printf("ENTER DIFFICULTY LEVEL (1, 2, 3)"); return; } nameOfPlayer += currChar; } } else if (state == diffLevel) { currChar = (char) dev.getc(); pc.printf("state = 1, currChar = @%c\n\r", currChar); dev.getc(); // clear newline character switch (currChar) { case '1': decrement = 0.05; break; case '2': decrement = 0.1; break; case '3': decrement = 0.15; break; } state = randomNum; dev.printf("PLEASE ENTER A RANDOM NUMBER BETWEEN 0 AND 9\n"); } else if (state == randomNum) { currChar = (char) dev.getc(); dev.getc(); // clear newline character seed = (int) currChar - 48; // convert to int state = play; } else if (state == replay) { currChar = (char) dev.getc(); dev.getc(); // clear newline character switch(currChar) { case 'y': state = name; break; case 'n': dev.printf("Thanks for playing! Goodbye!\n"); exit(0); break; } } } /* Bluetooth handler */ void pc_recv() { while(pc.readable()) { dev.putc(pc.getc()); } } /* Plays a wavefile through the speaker */ void playFile(char * filename) { char result [50]; sprintf(result, "/sd/%s.wav", filename); FILE *fp = fopen(result, "r"); player.play(fp); fclose(fp); } /* Actions to be completed when the game is over - display high score - asks user if they want to play again */ void gameOver(bool wrong) { updateHighScore(nameOfPlayer, score); if (wrong) { playFile("gameoversound"); } playFile("gameover"); printCommand(" GAME\n OVER", RED); gameDone = true; } /* returns true if the potentiometer was twisted */ bool wasTwisted() { double currTwist = (double) twist; pc.printf("curr twist: %f\n", currTwist); return (abs(currTwist - (double)twistStart) > 0.4); } /* returns true if the pushbutton was hit */ bool wasBopped() { return !bop; // waiting for button press (active low) } /* returns true if the device was shaken */ bool wasShaken() { accel.readXYZGravity(&xCurr,&yCurr,&zCurr); return (abs(xCurr - xStart) > 0.3 || abs(yCurr - yStart) > 0.3 || abs(zCurr - zStart) > 0.3); } /* returns true if the potentiometer was slid */ bool wasSlid() { double currSlide = (double) slide; pc.printf("curr slide: %f\n", currSlide); return (abs((double)slide - slideStart) > 0.5); } /* prompts user with command (bopIt) and waits for them to complete it The game ends if they run out of time or they perform the wrong command */ void bopIt(){ printCommand(" BOP\n IT ", 0xFFA500); playFile("bopit"); std::clock_t start = clock(); while (!wasBopped()) { if (wasTwisted() || wasSlid()) { gameOver(true); return; } if (((clock() - start) / (double) CLOCKS_PER_SEC) > timeLimit) { gameOver(false); return; } } playFile("bopsound"); return; } /* prompts user with command (twistIt) and waits for them to complete it The game ends if they run out of time or they perform the wrong command */ void twistIt() { printCommand(" TWIST\n IT", WHITE); playFile("twistit"); std::clock_t start = clock(); while (!wasTwisted()) { if (wasSlid() || wasBopped()) { gameOver(true); return; } if (((clock() - start) / (double) CLOCKS_PER_SEC) > timeLimit) { gameOver(false); return; } } pc.printf("final twist: %f\n", (double)twist.read()); playFile("twistsound"); return; } /* prompts user with command (slideIt) and waits for them to complete it The game ends if they run out of time or they perform the wrong command */ void slideIt(){ printCommand(" SLIDE\n IT", YELLOW); playFile("slideit"); std::clock_t start = clock(); while (!wasSlid()) { if (wasTwisted() || wasBopped()) { gameOver(true); return; } if (((clock() - start) / (double) CLOCKS_PER_SEC) > timeLimit) { gameOver(false); return; } } playFile("slidesound"); return; } /* prompts user with command (shakeIt) and waits for them to complete it The game ends if they run out of time or they perform the wrong command */ void shakeIt(){ printCommand(" SHAKE\n IT", GREEN); playFile("shakeit"); std::clock_t start = clock(); while (!wasShaken()) { if (wasBopped() || wasTwisted() || wasSlid()) { gameOver(true); return; } if (((clock() - start) / (double) CLOCKS_PER_SEC) > timeLimit) { gameOver(false); return; } } playFile("shakesound"); return; } /* sets up game and loops through the game states */ int main() { playFile("welcome"); printWelcome(); state = name; readTextFile(); pc.baud(9600); dev.baud(9600); pc.attach(&pc_recv, Serial::RxIrq); dev.attach(&dev_recv, Serial::RxIrq); string directions = "Welcome to BOP IT! \n-If it says BOP-IT, press the button. \n-If it says SLIDE IT, slide the switch. \n-If it says SHAKE IT, shake the box. \n-If it says TWIST IT, twist the knob. "; dev.printf("%s\n\r", directions); dev.printf("ENTER YOUR NAME BELOW!"); bop.mode(PullUp); // enable pullup mode to use internal resistance while (state != play); srand(seed); int whichCommand; while(1) { if (gameDone) { gameDone = false; state = replay; score = 0; nameOfPlayer = ""; dev.printf("Start new game? y/n\n"); while (state == replay); // wait for user's response dev.printf("ENTER YOUR NAME BELOW!\n"); while (state != play); } // record initial readings twistStart = (double)twist; slideStart = (double)slide; accel.readXYZGravity(&xStart,&yStart,&zStart); // choose command whichCommand = rand() % 4; switch (whichCommand) { case 0: bopIt(); break; case 1: pc.printf("startTwist: %f\n", (double)twist); twistIt(); break; case 2: pc.printf("startSlide: %f\n", (double)slide); slideIt(); break; case 3: shakeIt(); break; } // don't let the alloted time go below 2 seconds if (timeLimit > 2) { timeLimit -= decrement; } wait(1); score++; } }