//Reaction-Tester Game. SteveC - Jan2024
#include <Adafruit_ILI9341.h>
#define TFT_DC 2
#define TFT_CS 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
const char* Whi = "WHITE "; /// The Texts!!
const char* Red = " RED ";
const char* Blu = " BLUE ";
const char* Yel = "YELLOW";
const char* Grn = "GREEN ";
//The Colors!!
const uint16_t ColorArr[] = {ILI9341_WHITE, ILI9341_RED, ILI9341_BLUE, ILI9341_YELLOW, ILI9341_GREEN};
bool ButtonPushed = false; //set while button is pushed
bool WaitForIt = false; //set to pause a bit to allow player to read hit/miss result
bool ScoreShow = false; //flag to prevent cont. repaint during color-flash
int Button = 5; //the Pin-Number of the button used.
int TextNo = 8; //Number of text displayed - 8 for "Ready" message
int ColorNo = 0; //Number of Color the text is displayed in
int Hits; //counts the number of Hits (correct pushes)
int Miss; //counts the number of Misses (and incorrect pushes)
int Fix = 0; //ensures we don't wait too long for a match!
int FixMax = 5; //Force a match after this many mismatches (prevent boredom!!)
long StartTime = 0; //set to millis() value when we start timing
long DelayTime = 0; // how many millis have elapsed since start
long DispTime = 0; // random delay to next tft - gradually gets faster!
long TimeToBeat = 9999; //remembers fastest reaction time during game
long ReadTime = 2000; //time allowed to read result(longer at end)
long score = 0; //keep the score! (sum of HitSpeeds!)
long speed = 2000; //how fast the colors come(gets faster by 5% every hit)
void setup() {
pinMode(Button, INPUT_PULLUP);
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(2);
}
void showScore(){ //prints the Score-Line to the top of the screen
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(0,0);
tft.fillRect(0, 0, 280, 15, 0x0); //wipe out old score text
tft.print("Score:");
tft.print(score); //score at top left
tft.setCursor(150,0);
tft.print("Miss:");
tft.print(Miss); //misses (Lives?) at top right
tft.setCursor (80, 60); //near middle of screen??
tft.fillRect(0, 60, 280, 100, 0x0); //wipe out old text
}
void loop() {
// read the input pin:
ButtonPushed = !digitalRead(Button); //invert so a push is a 1
if (!WaitForIt){ //Display random Text/Color every sec while waiting for push
if (!ButtonPushed){ //still waiting for button....
if((millis()-StartTime)>DispTime){ //time to display a new combo?..
if (!ScoreShow){ //flag ensures we don't waste time displaying unchanged score.
showScore();
ScoreShow = true;
}
if (Miss > 4) { //display Game Over until next button push if done
tft.setCursor (80, 60);
tft.print(" Game");
tft.println(" Over!");
tft.println("");
tft.print("Hits=");
tft.print(Hits);
tft.print(" Min="); //display fastest reaction time in ms
tft.print(TimeToBeat);
tft.print("ms");
}
else if (TextNo==8){ //new set started
tft.print("Ready...");
TextNo = 6;
}
else if (TextNo == ColorNo){ //check if we missed the last one!!
Miss++; //we lose a life!
showScore();
ScoreShow = false;
tft.setTextSize(4);
tft.print("Miss!!!");
TextNo = 8; //show [Ready...] before next set of colors
Fix = 0; // reset the count to next forced hit
if(Miss>4){ //all lives lost!
ReadTime = 3000; //longer after last miss!!
}
WaitForIt = true; //wait for miss to be read
StartTime = millis();
}
else { //we need to display a new combo..
TextNo = random(0,5); //choose a random text
if(Fix++ > FixMax){ //we haven't had a match for a while
ColorNo = TextNo; //so make this one a match!
}
else {
ColorNo = random(0,5); //choose a random color
}
//display the random text in the random color
tft.fillRect(80, 60, 140, 30, 0x0); //wipe out old text
tft.setCursor (80, 60); //near middle of screen??
tft.setTextSize(4);
tft.setTextColor(ColorArr[ColorNo]);
if (TextNo==0){
tft.print(Whi);
}
else if(TextNo==1){
tft.print(Red);
}
else if(TextNo==2){
tft.print(Blu);
}
else if(TextNo==3){
tft.print(Yel);
}
else {
tft.print(Grn);
}
}
StartTime = millis();
DispTime = random(speed-200,speed); //new display time slightly random (starts around 2 sec and speeds up!)
}
}
else { // button is pushed
DelayTime = millis() - StartTime;
ScoreShow = false;
if (Miss > 4) { //start new game
showScore();
tft.println("Resetting-");
score = 0;
TimeToBeat = 9999;
speed = 2000;
Hits = 0;
Miss = 0;
}
else if (TextNo==ColorNo){ //we have a good hit!
score = score + (60000/DelayTime); //score for hit based on speed (in clicks per minute)
showScore();
tft.print("You Took.. ");
tft.print(DelayTime);
tft.println("ms");
if (DelayTime<TimeToBeat){
tft.println();
tft.print(" BEST ");
tft.println("..so far!!");
tft.println();
TimeToBeat = DelayTime;
}
else { //not the best!
tft.println();
tft.print("Fastest is ");
tft.print(TimeToBeat);
tft.println("ms");
tft.println();
}
Hits++;
Fix = 0;
speed = speed - (speed/20); //speed up changes by 5% after every hit
FixMax = random(5, 7); //match will happen before 7 cycles
}
else { //Bad Push - not equal!
Miss++; //lose a life!
showScore();
tft.println(" Too Quick!");
tft.println();
tft.println("Colors did not match!");
tft.println();
if(Miss > 4){
ReadTime = 3000; //longer after last miss!!
}
}
tft.print("Hits=");
tft.print(Hits);
tft.print(" Miss=");
tft.println(Miss);
TextNo = 8; //show [Ready...] before next set of colors
WaitForIt = true;
StartTime = millis();
}
}
else if (ButtonPushed){ //wait for button released!
StartTime = millis();
}
else { //wait 2s (after button release!) for result to be read...
if ((millis()-StartTime) > ReadTime){
WaitForIt = false;
ReadTime = 2000; //reset to normal
}
}
}Loading
esp32-devkit-c-v4
esp32-devkit-c-v4