//====================================================== // REACTION GAME MAIN ROUTINE //====================================================== /* This Game Can Be Called From * Stand Alone Mode / Bluetooth Connection * The primary mode is the standalone but * if the bluetooth is connected it has the priority * so it will take over the control of the device * * If you want to control the game via bluetooth * you need to call : game_reaction_bluetooth(JSON String) * If you want to use the stand alone mode * you need to call : game_reaction_standalone() * * the game returns a float point number which is * in seconds. so the athlete know how long he takes to react */ //------------------------------------------------------ // Request From Stand Alone Buttons //------------------------------------------------------ void game_reaction_standalone() { // Variables uint8_t minDelay = 1; uint8_t maxDelay = 3; uint8_t trials = 10; // Call the Game Play play_reaction(minDelay, maxDelay, trials); // Give Permision To Change Display DISPLAY_CHANGED = false; } //------------------------------------------------------ // Request From Bluetooth Via JSON //------------------------------------------------------ /* REACTION GAME SETTINGS PARAMETERS NOTE: * ------------------------------------------ * * FORMAT : * -------- * {"tr": 10, "mn": 1, "mx": 2} * * MEANNING : * ---------- * tr : trials pre counter * mn : minimum delay, between trials * mx : maximum delay, between trials * * THINGS THAT ENDS THE GAME : * --------------------------- * 1. BY COUNT DOWN "tr" REACH TO ZERO * 2. BY A COMMAND "FROM APP VIA BLUETOOTH" * * CALCULATING RESULTS : * --------------------- * Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec */ void game_reaction_bluetooth(String settings) { //------------------------------------------------------ // START OF READING THE SETTINGS //------------------------------------------------------ // Deserialize the JSON document DeserializationError error = deserializeJson(JSON, settings); // JSON ERROR if(error) { dualcomm(JSON_ERROR); return; } // PUBLIC VARIABLES uint8_t minDelay = JSON["mn"]; uint8_t maxDelay = JSON["mx"]; uint16_t trials = JSON["lm"]; // Fix Random Error maxDelay += 1; // Clearing Buffer JSON.clear(); // Play The Game play_reaction(minDelay, maxDelay, trials); // Give Permision To Change Display DISPLAY_CHANGED = false; } //------------------------------------------------------ // Play The Game //------------------------------------------------------ void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials) { // PUBLIC VARIABLES double totalRes = 0.0; // Fix Random Error maxDelay += 1; // Clearing Buffer JSON.clear(); //------------------------------------------------------ // PREPARE FOR GAME START //------------------------------------------------------ // DisJSON Welcome Message terminal(""); terminal("trials : " + String(trials) + " Strikes"); terminal("minDelay : " + String(minDelay) + " Seconds"); terminal("maxDelay : " + String(maxDelay) + " Seconds"); terminal("2 Seconds To Start Get Ready & Good Luck !!"); terminal(""); // Main Variables uint16_t sdelay = 0; uint16_t power = 0; uint16_t response = 0; unsigned long startTime = 0; unsigned long stopTime = 0; // Ready Signal //LED_SIGNAL_REACTION_START(); // Display On OLED GAME_REACTION_DISPLAY(0, 0); //------------------------- // PREPARE FOR GAME START //------------------------- // Processing Results for(int i=0; i Get Ready !!"); // Set Random Delay Time sdelay = random(minDelay, maxDelay); sdelay *= 1000; delay(sdelay); // Light Up Green //LED_SET_COLOR(0, 255, 0, 255); // Start Timer startTime = millis(); // Sensing Strike Power while(power < VTH) { // Reading The Strike power = PIEZO_MAP; // If Stop Command Came From Smart Phone if(isBluetooth) { String msg = Bluetooth.readStringUntil('\n'); flushBluetooth; msg.trim(); if(msg == CM_STOP) { dualcomm(GAME_OVER); // LightUp //LED_SIGNAL_END(); // RESET return; } else if(msg == CM_RESET) { //LED_SIGNAL_REACTION_RESET(); i = 0; sdelay = 0; power = 0; response = 0; startTime = millis(); stopTime = millis(); totalRes = 0; DISPLAY_CHANGED = false; GAME_REACTION_DISPLAY(i, response); //break; } } // Reset The Counter if(BTN_INCREASE.pressed()) { //LED_SIGNAL_REACTION_RESET(); i = 0; sdelay = 0; power = 0; response = 0; startTime = millis(); stopTime = millis(); totalRes = 0; DISPLAY_CHANGED = false; GAME_REACTION_DISPLAY(i, response); } // Will Exit The Game if(BTN_CENTER.pressed()) { dualcomm(GAME_OVER); DISPLAY_CHANGED = false; return; } } // Stop Timer stopTime = millis(); // Stop Light //LED_SET_COLOR(255, 0, 0, 255); // Calculating Response Time response = stopTime - startTime - 1; totalRes = totalRes + ((float)response/1000); // Create Json JSON String msg = reaction_JSON_json(i+1, power, response, sdelay); // Display On OLED GAME_REACTION_DISPLAY(i+1, response); // Print To Terminal dualcomm(msg); // Clear All sdelay = 0; power = 0; response = 0; } // Red Light Delay delay(500); // END GAME dualcomm(GAME_OVER); // Blink Red //LED_SIGNAL_CELEBRATION(); // Display Result GAME_REACTION_RESULT(trials, totalRes); // Return To Game Selector return; } //------------------------------------------------------ // REACTION JSON -> To Send Back To Mobile Device //------------------------------------------------------ String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay) { // Convert To Seconds Unit float re = response; re /= 1000; // Asignning Values JSON["ct"] = count; // Strike Number JSON["pw"] = power; // Strike Power In Analog Read JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec String output; serializeJson(JSON, output); JSON.clear(); return output; } //------------------------------------------------------ // REACTION GAME START LED SIGNAL //------------------------------------------------------ void LED_SIGNAL_REACTION_START() { // Cross fade the white signal to get ready //LED_CROSS_FADE(255, 255, 255, 3); // Set the LED strip color to red //LED_SET_COLOR(255, 0, 0, 255); } //------------------------------------------------------ // REACTION GAME RESET LED SIGNAL //------------------------------------------------------ void LED_SIGNAL_REACTION_RESET() { // Light Bright Blue //LED_BLINK(0, 0, 255, 2); // Wait For 1/4 Second //delay(250); // Fade Out The Blue //LED_SET_COLOR(0, 255, 0, 255); } //------------------------------------------------------ // OLED GAME PLAY REACTION //------------------------------------------------------ void GAME_REACTION_DISPLAY(uint16_t count, float reatime) { OLED_CLEAR(); drawTextCenter(128/2, 0, 2, "KICK : " + String(count)); drawTextCenter(128/2, 20, 3, "TIME : " + String(((float)reatime/1000), 2)); // Exit Button Command Only Via Stand Alone Mode if(BLUETOOTH_STATUS == false) { drawTextCenter(128/2, 50, 1, "<< EXIT >>"); } OLED_SHOW(); } //------------------------------------------------------ // OLED - GAME TIMEATTACK RESULT //------------------------------------------------------ void GAME_REACTION_RESULT(uint16_t trials, uint16_t total_reaction) { OLED_CLEAR(); float avgReaction = 0.0; avgReaction = (float)total_reaction/trials; drawTextCenter(128/2, 0, 2, "RESULT"); drawTextCenter(128/2, 20, 2, String(avgReaction, 3) + " s"); drawTextCenter(128/2, 50, 1, "<< EXIT >>"); OLED_SHOW(); // Waiting For Center Button To Move On while(1){ if(BTN_CENTER.pressed()) { break; } } }