Dependencies: mbed wave_player mbed-rtos 4DGL-uLCD-SE SDFileSystem
main.cpp
- Committer:
- rushib1
- Date:
- 2020-04-27
- Revision:
- 4:c1da839b41b1
- Parent:
- 3:6e41a5ce16c2
- Child:
- 5:269d04e12a9e
File content as of revision 4:c1da839b41b1:
#include "mbed.h" #include "uLCD_4DGL.h" #include "rgb.h" #include "SDFileSystem.h" #include "wave_player.h" #include "rtos.h" #include <string> #include <iostream> #include <fstream> #include <algorithm> enum DIFF_LEVEL{NA=0, EASY=1, MED=2, HARD=3, SCORE=4}; enum SIGN{PLUS=0, MINUS=1, MULT=2}; struct Gen_Question{ int num1; int num2; int sign; int corr_ans; int ans[4]; }; struct Game_Difficulty{ bool is_selected; enum DIFF_LEVEL level; int ans_time; int max_num; int num_of_q; int score_mult; }; struct Game_Settings{ Game_Difficulty new_diff; int score; int live_left; int q_on; bool is_timeout; bool is_lose; }; Game_Settings new_game = {.q_on=1, .live_left = 3, .new_diff.is_selected=false, .is_timeout=true, .is_lose =false}; void print_high_score(); int* read_high_score(); /* ------------------CONSTS */ //const int EASY_TIME =20; //const int MED_TIME =15; //const int HARD_TIME =10; volatile bool homescreen = true; volatile bool boot_vid = true; /* ------------------I/O VARS */ SDFileSystem sd(p5, p6, p7, p8, "sd"); RawSerial bluemod(p28, p27); Serial pc(USBTX, USBRX); uLCD_4DGL uLCD(p9, p10, p11); DigitalIn pb(p12); /* ------------------LED VARS */ DigitalOut life[] = {(p16), (p19), (p20)}; RGBLed myRGBled(p21, p24, p23); DigitalOut onboard_led(LED1); /* ------------------AUDIO VARS */ FILE *wave_file; AnalogOut DACount(p18); wave_player waver(&DACount); /* ------------------GENERAL VARS */ volatile char bnum = '0'; Mutex lcd_mutex; Mutex blue_mutex; Thread thread1, thread2, thread3; void main_screen() { //pc.printf("MAIN_SCREEN\r\n"); uLCD.cls(); uLCD.text_height(1); uLCD.text_width(1); uLCD.color(0xF0F6F7); uLCD.locate(6, 1); uLCD.printf("MATH FUN"); uLCD.locate(1, 4); uLCD.printf("Difficulty"); uLCD.text_height(1); uLCD.text_width(1); uLCD.locate(3, 6); uLCD.color(GREEN); uLCD.printf("1) Easy"); uLCD.locate(3, 8); uLCD.color(0xFFFF00); uLCD.printf("2) Not as Easy"); uLCD.locate(3, 10); uLCD.color(RED); uLCD.printf("3) Very Uneasy"); uLCD.color(0x669DB2); uLCD.locate(1, 13); uLCD.printf("4) High Scores"); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); homescreen = false; } bool count_distinct(int arr[], int n) { int res = 1; // Pick all elements one by one for (int i = 1; i < n; i++) { int j = 0; for (j = 0; j < i; j++) if (arr[i] == arr[j]) break; // If not printed earlier, then print it if (i == j) res++; } if (res == 4) { return false; } else { return true; } } void gen_ans(Gen_Question *gen_new_q) { //rand()%(max-min + 1) + min; gen_new_q->num1 = rand() % (new_game.new_diff.max_num + 1 - 0) + 0; gen_new_q->num2 = rand() % (new_game.new_diff.max_num + 1 - 1) + 1; gen_new_q->sign = rand() % (3 + 1 - 1) + 1; switch (gen_new_q->sign) { case 1: gen_new_q->sign = '*'; gen_new_q->ans[0] = gen_new_q->num1 * gen_new_q->num2; gen_new_q->ans[1] = (gen_new_q->num1 + (rand() % (10 + 1 - 1) + 1)) * gen_new_q->num2; gen_new_q->ans[2] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (20 + 1 - 1) + 1); gen_new_q->ans[3] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (20 + 1 - 1) + 1); break; case 2: gen_new_q->sign = '+'; gen_new_q->ans[0] = gen_new_q->num1 + gen_new_q->num2; gen_new_q->ans[1] = (gen_new_q->num1 + (rand() % (10 + 1 - 1) + 1)) + gen_new_q->num2; gen_new_q->ans[2] = (gen_new_q->num1 + gen_new_q->num2) - (rand() % ((gen_new_q->num1 + gen_new_q->num2) + 1 - 1) + 1); gen_new_q->ans[3] = (gen_new_q->num1 * gen_new_q->num2) + (rand() % (10 + 1 - 1) + 1); break; case 3: gen_new_q->sign = '-'; while (gen_new_q->num1 == gen_new_q->num2) { gen_new_q->num1 = (rand() % ((gen_new_q->num1 + 2) - 1 + 1) + 1); } gen_new_q->ans[0] = gen_new_q->num1 - gen_new_q->num2; gen_new_q->ans[1] = (gen_new_q->num1 - gen_new_q->num2) * -1 + (rand() % (10 + 1 - 1) + 1); gen_new_q->ans[2] = gen_new_q->num1 + gen_new_q->num2 - (rand() % (10 + 1 - 1) + 1); gen_new_q->ans[3] = gen_new_q->num1 * gen_new_q->num2 - (rand() % (20 + 1 - 1) + 1); break; } } void game_questions(Gen_Question *gen_new_q) { gen_ans(gen_new_q); bool reroll = count_distinct(gen_new_q->ans, 4); while (reroll) { gen_ans(gen_new_q); reroll = count_distinct(gen_new_q->ans, 4); //pc.printf("reroll\r\n"); } gen_new_q->corr_ans = gen_new_q->ans[0]; //pc.printf("%i\r\n", gen_new_q->ans[0]); //pc.printf("%i\r\n", gen_new_q->corr_ans); random_shuffle(&(gen_new_q->ans[0]), &(gen_new_q->ans[3])); uLCD.cls(); uLCD.locate(2, 1); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(0xFC766A); uLCD.printf("Q%i",new_game.q_on); uLCD.text_height(1); uLCD.text_width(1); uLCD.locate(9, 1); uLCD.printf("TIME:"); uLCD.line(55, 0, 55, 27, 0xA89C94); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); uLCD.line(0, 27, 127, 27, 0xA89C94); uLCD.line(0, 50, 127, 50, 0xA89C94); uLCD.color(0x669DB2); uLCD.locate(2, 4); uLCD.text_height(2); uLCD.text_width(2); uLCD.printf("%i%c%i=", gen_new_q->num1, gen_new_q->sign, gen_new_q->num2); uLCD.text_height(1); uLCD.text_width(1); uLCD.color(0xFC766A); uLCD.locate(2, 7); uLCD.printf("1)"); uLCD.color(0x669DB2); uLCD.locate(8, 7); uLCD.printf("%i", gen_new_q->ans[0]); uLCD.color(0xFC766A); uLCD.locate(2, 9); uLCD.printf("2)"); uLCD.color(0x669DB2); uLCD.locate(8, 9); uLCD.printf("%i", gen_new_q->ans[1]); uLCD.color(0xFC766A); uLCD.locate(2, 11); uLCD.printf("3)"); uLCD.color(0x669DB2); uLCD.locate(8, 11); uLCD.printf("%i", gen_new_q->ans[2]); uLCD.color(0xFC766A); uLCD.locate(2, 13); uLCD.printf("4)"); uLCD.color(0x669DB2); uLCD.locate(8, 13); uLCD.printf("%i", gen_new_q->ans[3]); uLCD.line(0, 115, 127, 115, 0xA89C94); } void game_over() { uLCD.cls(); uLCD.locate(0, 7); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(0xFC776A); uLCD.printf("GAME OVER"); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); } void win_game() { uLCD.cls(); uLCD.locate(2, 7); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(GREEN); uLCD.printf("YOU WIN"); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); } void score_game() { uLCD.cls(); uLCD.locate(1, 3); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(GREEN); uLCD.printf("SCORE"); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); uLCD.text_height(1); uLCD.text_width(1); uLCD.locate(7, 7); uLCD.printf("%i",new_game.score); } void life_count_check() { life[0] = 0; life[1] = 0; life[2] = 0; for (int i = 0; i < new_game.live_left; i++) { life[i] = 1; } if (new_game.live_left == 0) { new_game.is_lose = true; } } void check_correct_ans(Gen_Question check_new_q) { if (new_game.is_timeout) { //pc.printf("TIMEOUT\r\n"); uLCD.cls(); uLCD.locate(5, 7); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(0xF0F6F7); uLCD.printf("TIME"); new_game.live_left--; //wait(2); } else { //pc.printf("%i\r\n", corr_ans); //pc.printf("%i\r\n", ans[(bnum-'0' -1)]); if (check_new_q.corr_ans == check_new_q.ans[(bnum - '0') - 1]) { uLCD.cls(); uLCD.locate(2, 7); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(GREEN); uLCD.printf("CORRECT"); new_game.score = new_game.score + new_game.new_diff.score_mult; //wait(2); //pc.printf("CORRECT\r\n"); } else { //pc.printf("INCORRECT\r\n"); uLCD.cls(); uLCD.locate(0, 7); uLCD.text_height(2); uLCD.text_width(2); uLCD.color(RED); uLCD.printf("INCORRECT"); new_game.live_left--; //wait(2); } } } bool get_bluetooth_button() { //pc.printf("BLUETOOTH\r\n"); bnum = '0'; //blue_mutex.lock(); if (bluemod.getc() == '!') { if (bluemod.getc() == 'B') { //button number bnum = bluemod.getc(); //button data char bhit = bluemod.getc(); if (bluemod.getc() == char(~('!' + 'B' + bnum + bhit))) { if (bhit == '1') { //pc.printf("%c\r\n", bnum); blue_mutex.unlock(); return false; } } } } //blue_mutex.unlock(); return true; } void get_button() { int timer = new_game.new_diff.ans_time; new_game.is_timeout = true; while (timer != 0) { uLCD.locate(15, 1); uLCD.color(0xF0F6F7); uLCD.printf("%i", timer); if (bluemod.readable()) { new_game.is_timeout = get_bluetooth_button(); if(new_game.is_timeout == false){ break; } } wait(1); uLCD.locate(15, 1); uLCD.color(BLACK); uLCD.printf("%i", timer); timer = timer - 1; } } void bluetooth_thread() { while (true) { if (bluemod.readable()) { bool n_timeout = get_bluetooth_button(); } else { Thread::yield(); } Thread::wait(100); } } void rgb_led_difficulty() { //pc.printf("%i\r\n",bnum - 48); new_game.new_diff.level = static_cast<DIFF_LEVEL>(bnum - 48); //pc.printf("%i\r\n",new_game.new_diff.level); if (new_game.new_diff.level == EASY) { myRGBled.write(0.0, 1.0, 0.0); //green new_game.new_diff.is_selected = true; new_game.new_diff.ans_time = 20; new_game.new_diff.max_num = 10; new_game.new_diff.num_of_q = 7; // 7 new_game.score = 50; new_game.new_diff.score_mult = 10; } else if (new_game.new_diff.level == MED) { myRGBled.write(1.0, 0.2, 0.0); //yellow = red + some green new_game.new_diff.is_selected = true; new_game.new_diff.ans_time = 15; new_game.new_diff.max_num = 15; new_game.new_diff.num_of_q = 10; new_game.score = 200; new_game.new_diff.score_mult = 50; } else if (new_game.new_diff.level == HARD) { myRGBled.write(1.0, 0.0, 0.0); //red new_game.new_diff.is_selected = true; new_game.new_diff.ans_time = 10; new_game.new_diff.max_num = 10; new_game.new_diff.num_of_q = 15; new_game.score = 300; new_game.new_diff.score_mult = 100; } else if (new_game.new_diff.level == SCORE) { myRGBled.write(0.5, 0.5, 0.5); new_game.new_diff.is_selected = true; print_high_score(); } } void wav_thread() { while (true) { //pc.printf("AUDIO\r\n"); wave_file = fopen("/sd/audio/intro.wav", "r"); waver.play(wave_file); fclose(wave_file); } } void boot_video_thread() { while (true) { //pc.printf("BootVID\r\n"); //PLAY VIDEO BOOT if (boot_vid) { //lcd_mutex.lock(); uLCD.media_init(); uLCD.set_sector_address(0x0, 0x0); uLCD.display_video(0, 0); boot_vid = false; //lcd_mutex.unlock(); } else { Thread::yield(); } } } void write_high_score(int* score_arr){ std::ofstream score_file; score_file.open("/sd/score/score.txt"); if (score_file.is_open()) { //score_file << "300\n200\n100\n"; score_file << score_arr[0] << "\n" << score_arr[1] << "\n" << score_arr[2] << "\n"; score_file.close(); } } int* read_high_score() { int* score_val = new int[3]; //printf("read_high_score\n\r"); std::ifstream infile("/sd/score/score.txt"); wait(0.2); if (infile.is_open()) { std::string line; int i = 0; while (std::getline(infile, line)) { // using printf() in all tests for consistency //printf("%s", line.c_str()); score_val[i] = atoi(line.c_str()); i++; } infile.close(); } pc.printf("%i \n\r", score_val[0]); pc.printf("%i \n\r", score_val[1]); pc.printf("%i \n\r", score_val[2]); return score_val; } void print_high_score(){ int* score_arr= read_high_score(); uLCD.cls(); uLCD.text_height(1); uLCD.text_width(1); uLCD.color(0xF0F6F7); uLCD.locate(4, 1); uLCD.printf("HIGH SCORES"); uLCD.locate(3, 6); uLCD.color(0xFC776A); uLCD.printf("1) %i", score_arr[0]); uLCD.locate(3, 8); uLCD.color(0x669DB2); uLCD.printf("2) %i", score_arr[1]); uLCD.locate(3, 10); uLCD.color(0xFC776A); uLCD.printf("3) %i", score_arr[2]); uLCD.rectangle(0, 0, 127, 127, 0xA89C94); delete[] score_arr; } void check_new_highscore(){ int* new_score_arr = read_high_score(); for (int i = 0; i < 3; i++) { if (new_score_arr[i]< new_game.score){ int j = 1; while(i<=j){ new_score_arr[j+1] = new_score_arr[j]; j--; } new_score_arr[i] = new_game.score; pc.printf("high score found"); write_high_score(new_score_arr); break; } } delete[] new_score_arr; } void reset_scores(){ mkdir("/sd/score", 0777); std::ofstream score_file; score_file.open("/sd/score/score.txt"); if (score_file.is_open()) { score_file << "0\n0\n0\n"; score_file.close(); } } void init() { // while(1){ // reset_scores(); // wait(2); // } uLCD.baudrate(3000000); srand(time(NULL)); life[0] = 1; life[1] = 1; life[2] = 1; //thread1.start(boot_video_thread); boot_vid = false; } int main() { init(); // pc.printf("MAIN_INIT\r\n\n"); thread2.start(wav_thread); while (true) { //pc.printf("MAIN_LOOP\r\n"); //ONCE VIDEO STOPS PLAYING if (boot_vid == false) { thread1.terminate(); //IF HOMESCREEN PRINTED ONCE DONT PRINT AGAIN if (homescreen) { main_screen(); } //pc.printf("MAIN_PRINT\r\n"); if (new_game.new_diff.is_selected == false) { thread3.start(bluetooth_thread); rgb_led_difficulty(); } else { thread3.terminate(); break; } } Thread::wait(100); } if(new_game.new_diff.level != SCORE){ while (new_game.q_on <= new_game.new_diff.num_of_q) { thread3.terminate(); Gen_Question new_q; game_questions(&new_q); get_button(); check_correct_ans(new_q); new_game.q_on++; wait(2.2); life_count_check(); if(new_game.is_lose == true){ game_over(); break; } } if(new_game.is_lose == false){ win_game(); } wait(2.5); new_game.score = new_game.score + new_game.live_left * 100; score_game(); wait(2); check_new_highscore(); wait(0.5); print_high_score(); } }