Timeout for a reaction time game

Hi,
I’m making this reaction time game, which starts at the press of a pushbutton, a light turns on at a random time and you have to press it to measure your reaction time and begin the game again. The problem is that I want the game to finish either if the button is pressed early (which is already implemented), OR if a maximum time has elapsed since the light turned on.

My problem is that with my basic programming knowledge I cannot figure out how can I do that. I tried ifs here and there, do’s whiles, and everything but nothing.

Any strategies or links to resources of how can I do this?

EDIT: the key is to do something with startTime at line 88

Here’s the code:

/* REACTION TIME (with 2 leds) v2.1 beta
    Luis Andrés Gonzalez
   Reaction time original version from http://www.instructables.com/id/Arduino-Reaction-Time-Tester/?ALLSTEPS
   Send data to processing via the Serial Port original from By Elaine Laguerta http://url/of/online/tutorial.cc
*/
const int switchPin = 6;  // pin where the button will be connected
const int ledPin1 = 2 ;   // Left LED
const int ledPin2 = 8 ;   // Middle LED
const int ledPin3 = 12;   // Right LED

// declare some variables:
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean gameStarted = false;  // true if game has started
boolean timerFlag = false;    // true if timer is running
long startTime;
long endTime;
int randomSeconds;
long beginTime;
float elapsedTime;
int maxTimer = 10 * 1000;


void setup() {
  // Setup button and LEDs:
  pinMode(switchPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  // Begin serial communication
  Serial.begin(9600);
}

void loop() {
  // Check https://www.arduino.cc/en/Tutorial/StateChangeDetection to understand the following code.

  // read the pushbutton input pin in the current loop:
  currentButton = buttonPressed(lastButton);

  // if there's a change from low to high (comparing last and current loop) then the following is true
  if (currentButton == HIGH && lastButton == LOW) {   // outer IF

    if (gameStarted == false) {                       // middle IF. starts the game
      gameStarted = true;
      randomSeconds = random(3, 8) * 1000; // generates a random number of seconds between 3 and 8
      Blink(1);
      Serial.println("9090"); // signal code for start sound
      beginTime = millis();

    } else {
      
        if ((millis() - beginTime) >= randomSeconds ) {
          Stop();          
          gameStarted = false;
          timerFlag = false;
        } else if ((millis() - beginTime) < randomSeconds) {
          gameStarted = false;
          timerFlag = false;
          Serial.println("1010"); // signal code for early response
          Blink(3);
        }
      }
  }                             // end outer if
  // save the current state as the last state,
  //for next time through the loop
  lastButton = currentButton;

  // If true, starts the response time timer and lights up the LED
  if (gameStarted == true && (millis() - beginTime) >= randomSeconds && timerFlag == false) {
    timerFlag = true;
    Start();
  }
  
}


boolean buttonPressed(boolean last) {       //button debouncing function
  boolean current = digitalRead(switchPin);
  if (last != current) {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void Start() {
  startTime = millis();
  Light(ledPin1, "on");
}

void Stop() {
  if ( (millis() - beginTime) <= maxTimer ) {
    endTime = millis();
    elapsedTime = (endTime - startTime) + 5;
    float elapsedSeconds = elapsedTime / 1000;
    Serial.println(elapsedSeconds);
  }
  else Serial.println("Timed out");
  Light(ledPin1, "off");

}

void Blink(int repetitions) {
  for (int i = 0; i < repetitions; i++) {
    digitalWrite(ledPin2, HIGH);
    delay(100);
    digitalWrite(ledPin2, LOW);
    delay(100);
  }
}

void Light(int lednumber, String onOff) {
  if (onOff == "on") {
    digitalWrite(lednumber, HIGH);
  } else if (onOff == "off") {
    digitalWrite(lednumber, LOW);
  }

}

try to approach the problem with a little more order.

try the state machine approach

/* Reaction Time Game

Flashes blue  "ready lite" waiting for you to press buttton to start the game
Waits random interval to breifly illuminate green led
If you press button while green, green led blinks
Early or late, red led blinks
Press button again to return to ready state and start over!!!
*/

#define TIMEOUT_MILLISECONDS  500UL  // not too tough; make smaller for a bigger challenge

const char* const stateText[] = { "Stand By", "Active Game", "Early Press", "Good Press!!!", "Late Press"};

enum GameState{
  STAND_BY,
  ACTIVE_GAME,
  EARLY_PRESS,
  GOOD_PRESS,
  LATE_PRESS,
};

GameState gameState = STAND_BY;
GameState lastState;

byte buttonPin = 5;
byte redLed = 6;
byte greenLed = 13;
byte blueLed = 8;

unsigned long lastMillis = 0;
unsigned long randomTimerDelay = 0;

void setup() 
{
  Serial.begin(112500);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(redLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);
  randomSeed(analogRead(A4));
  Serial.println(stateText[gameState]);
}

void loop() 
{
  bool pressed = checkButton();
  if(gameState == STAND_BY)
  {
    fastFlash(blueLed);
    if(pressed)
    {
      digitalWrite(blueLed, LOW);
      randomTimerDelay = 1000 + random(5000);  // random anticipation time between 1 and 6 seconds
      gameState = ACTIVE_GAME;
    }
  }
  else if(gameState == ACTIVE_GAME)
  {
    unsigned long elapsedMillis = millis() - lastMillis;
    if (elapsedMillis >= randomTimerDelay && !digitalRead(greenLed))
    {
      digitalWrite(greenLed, HIGH);
      Serial.println(F("Lite On!!"));
    }
    else if (elapsedMillis > randomTimerDelay + TIMEOUT_MILLISECONDS)
    {
      Serial.println(F("TimeOut!!"));
      digitalWrite(greenLed, LOW);
      gameState = LATE_PRESS;
    }
    if(pressed)
    {
      if (digitalRead(greenLed))
      {
        gameState = GOOD_PRESS;
      }
      else
      {
        gameState = EARLY_PRESS;
      }
    }
  }
  else if(gameState == EARLY_PRESS)
  {
    if(pressed)
    {
      digitalWrite(redLed, LOW);
      gameState = STAND_BY;
    }
    else
    {
      fastFlash(redLed);
    }
  }
  else if(gameState == GOOD_PRESS)
  {
    if(pressed)
    {
      digitalWrite(greenLed, LOW);
      gameState = STAND_BY;
    }
    else
    {
      fastFlash(greenLed);
    }
  }
  else if (gameState == LATE_PRESS)
  {
    if(pressed)
    {
      digitalWrite(redLed, LOW);
      gameState = STAND_BY;
    }
    else
    {
      fastFlash(redLed);
    }
  }
  if (lastState != gameState)
  {
    Serial.println(stateText[gameState]);
    lastState = gameState;
  } 
}

bool checkButton()
{
  static byte lastButtonState = 1;
  byte buttonState = digitalRead(buttonPin);
  if(buttonState == 0 && lastButtonState == 1 && millis() - lastMillis > 75UL) // <<<<<<< adjust 75 down as far as possible
  {
    Serial.println(F("!"));
    lastMillis = millis();
    return true;
  }
  lastButtonState = buttonState;
  return false;
}

void fastFlash(int pin)
{
  static unsigned long lastFlashMillis = 0;
  if(millis() - lastFlashMillis > 200UL)
  {
    digitalWrite(pin, !digitalRead(pin));
    lastFlashMillis = millis();
  }
}

Thanks BulldogLowell, I’m going to keep an eye for that approach. In the meantime I got some kind of solution but not complete. This code does the trick:

if ((millis() - beginTime) > (randomSeconds + maxTimer))

The problem right now is that right after it times out, it loops back again into a new game (which supposedly starts only by a button press). Any ideas?

/* REACTION TIME (with 2 leds) v2.1 beta
    Luis Andrés Gonzalez
   Reaction time original version from http://www.instructables.com/id/Arduino-Reaction-Time-Tester/?ALLSTEPS
   Send data to processing via the Serial Port original from By Elaine Laguerta http://url/of/online/tutorial.cc
*/
const int switchPin = 6;  // pin where the button will be connected
const int ledPin1 = 2 ;   // Left LED
const int ledPin2 = 8 ;   // Middle LED
const int ledPin3 = 12;   // Right LED

// declare some variables:
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean gameStarted = false;  // true if game has started
boolean timerFlag = false;    // true if timer is running
long startTime;
long endTime;
int randomSeconds;
long beginTime;
float elapsedTime;
int maxTimer = 5 * 1000;
float totalTime;



void setup() {
  // Setup button and LEDs:
  pinMode(switchPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  // Begin serial communication
  Serial.begin(9600);
}

void loop() {
  // Check https://www.arduino.cc/en/Tutorial/StateChangeDetection to understand the following code.
  if ((millis() - beginTime) > (randomSeconds + maxTimer)) {
    Stop();
    
    //resets game:
    gameStarted = false;
    timerFlag = false;
    currentButton = LOW;
    lastButton = LOW;
    
    
    Blink(2);
    Serial.println("message");

  }
  // read the pushbutton input pin in the current loop:
  currentButton = buttonPressed(lastButton);

  // if there's a change from low to high (comparing last and current loop) then the following is true
  if (currentButton == HIGH && lastButton == LOW) {   // outer IF

    if (gameStarted == false) {                       // middle IF. starts the game
      gameStarted = true;
      randomSeconds = random(2, 5) * 1000; // generates a random number of seconds between 3 and 8
      Blink(1);
      Serial.println("9090"); // signal code for start sound
      beginTime = millis();
    } else {

      if ((millis() - beginTime) >= randomSeconds) {
        Stop();
        gameStarted = false;
        timerFlag = false;

      } else if ((millis() - beginTime) < randomSeconds ) {
        gameStarted = false;
        timerFlag = false;
        Serial.println("1010"); // signal code for early response
        Blink(3);
      }

    }
  }                             // end outer if

  // save the current state as the last state,
  //for next time through the loop
  lastButton = currentButton;




  // If true, starts the response time timer and lights up the LED
  if (gameStarted == true && (millis() - beginTime) >= randomSeconds && timerFlag == false) {
    timerFlag = true;

    Start();

  }
  
} // end void loop

//===========================================================================================

boolean buttonPressed(boolean last) {       //button debouncing function
  boolean current = digitalRead(switchPin);
  if (last != current) {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void Start() {

  startTime = millis();
  Light(ledPin1, "on");

}

void Stop() {
  if ( (millis() - beginTime) <= maxTimer ) {
    endTime = millis();
    elapsedTime = (endTime - startTime) + 5;
    float elapsedSeconds = elapsedTime / 1000;
    Serial.println(elapsedSeconds);
  }
  else Serial.println("Timed out");
  Light(ledPin1, "off");

}

void Blink(int repetitions) {
  for (int i = 0; i < repetitions; i++) {
    digitalWrite(ledPin2, HIGH);
    delay(100);
    digitalWrite(ledPin2, LOW);
    delay(100);
  }
}

void Light(int lednumber, String onOff) {
  if (onOff == "on") {
    digitalWrite(lednumber, HIGH);
  } else if (onOff == "off") {
    digitalWrite(lednumber, LOW);
  }

}

Repeat - state machine - you need states in your program.

luispotro: The problem right now is that right after it times out, it loops back again into a new game (which supposedly starts only by a button press). Any ideas?

I've exhausted all of my ideas in the working code that includes a STATE MACHINE!!!

Did I mention that I think you need a State Machine?

If you don't agree, then I think you should follow @MarkT's advice. ;)

I got the idea, guys!!

I was just holding on to an old idea, and needed to let it go :P . Remember that I am a beginner. I'm not familiar with machine state, so, like Luke in Dagobah I "must unlearn what I've learned".

I'll keep you posted if you don't mind.

Ok, here’s what I’ve come to do so far. It works good on the flow of what is supposed to do, but now there’s a problem with the reaction time. I got lost in the part that counts the amount of seconds between the light on and the time when I press the button.

The sketch:

/* REACTION TIME (with 2 leds) v3.0 beta
    Luis Andrés Gonzalez
   Reaction time original version from http://www.instructables.com/id/Arduino-Reaction-Time-Tester/?ALLSTEPS
   Send data to processing via the Serial Port original from By Elaine Laguerta http://url/of/online/tutorial.cc
*/
#define TIMEOUT_MILLISECONDS  5000UL  // not too tough; make smaller for a bigger challenge

const char* const stateText[] = { "Stand By", "Active Game", "Early Press", "Good Press", "Late Press"};

enum GameState {
  STAND_BY,
  ACTIVE_GAME,
  EARLY_PRESS,
  GOOD_PRESS,
  LATE_PRESS,
};
enum Outcomes {
  GOOD,
  EARLY,
  LATE,
};

const byte buttonPin = 6;  // pin where the button will be connected
const byte ledPin1 = 3 ;   // Left LED
const byte ledPin2 = 8 ;   // Middle LED
const byte ledPin3 = 12;   // Right LED

GameState gameState = STAND_BY;
Outcomes outcome;
GameState lastState;

// declare some variables:
boolean lastButton = LOW;
boolean pressed = LOW;
unsigned long lastMillis = 0;
unsigned long elapsedMillis;


boolean gameStarted = false;  // true if game has started
boolean timerFlag = false;    // true if timer is running
long startTime;
long endTime;
int randomSeconds;
long beginTime;
float elapsedTime;
int maxTimer = 5 * 1000;
float totalTime;
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by




void setup() {
  // Setup button and LEDs:
  pinMode(buttonPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  // Begin serial communication
  Serial.begin(9600);
  Serial.println(stateText[gameState]);
}

void loop() {

  // read the pushbutton input pin in the current loop:
  pressed = checkButton();

  if (gameState == STAND_BY) {
    Fade();
    if (pressed) {
      Light(ledPin1, "off");
      randomSeconds = random(2, 5) * 1000; // generates a random number of seconds between 3 and 8
      Blink(1);
      gameState = ACTIVE_GAME;
      Serial.println("9090"); // signal code for start sound
      Serial.println(stateText[gameState]);
    }
  }

  else if (gameState == ACTIVE_GAME) {
    elapsedMillis = millis() - lastMillis;
    long prueba = millis();
    unsigned long lightOnMillis;
    if (elapsedMillis >= randomSeconds) {
      if (elapsedMillis < randomSeconds + TIMEOUT_MILLISECONDS) {
        Light(ledPin1, "on");
        lightOnMillis = millis();
      }
      else if (elapsedMillis > randomSeconds + TIMEOUT_MILLISECONDS) {
        Serial.println("TimeOut!!");
        Light(ledPin1, "off");
        gameState = LATE_PRESS;
      }

    }
    else if (pressed)
    {
      if (digitalRead(ledPin1))
      {
        unsigned long pressedMillis = millis() - lightOnMillis;
        unsigned long tiempo = millis()- prueba;
        gameState = GOOD_PRESS;
        Serial.print("millis() - lightOnMillis =");
        Serial.println(pressedMillis);
        Serial.print("millis - prueba =");
        Serial.println(tiempo);
        Serial.println(stateText[gameState]);
      }
      else
      {
        gameState = EARLY_PRESS;
      }
    }


  }
  else if (gameState == EARLY_PRESS) {
    
      Serial.println("1010"); // signal code for early response
      Blink(3);
      gameState = STAND_BY;
      Serial.println("Standing by...");
      delay(1000);
    
  }
  else if (gameState == GOOD_PRESS) {
    gameState = STAND_BY;
    Serial.println("Standing by...");
    delay(1000);

    if (pressed)
    {

    }
  }
  else if (gameState == LATE_PRESS) {
    gameState = STAND_BY;
    Serial.println("Standing by...");
    delay(1000);
  }


}




bool checkButton()
{
  static byte lastButtonState = 1;
  byte buttonState = digitalRead(buttonPin);
  if (buttonState == 0 && lastButtonState == 1 && millis() - lastMillis > 75UL) // <<<<<<< adjust 75 down as far as possible
  {
    Serial.println("!");
    lastMillis = millis();
    return true;
  }
  lastButtonState = buttonState;
  return false;
}

void Light(int lednumber, String onOff) {
  if (onOff == "on") {
    digitalWrite(lednumber, HIGH);

  } else if (onOff == "off") {
    digitalWrite(lednumber, LOW);
  }
}
void Blink(int repetitions) {
  for (int i = 0; i < repetitions; i++) {
    digitalWrite(ledPin2, HIGH);
    delay(100);
    digitalWrite(ledPin2, LOW);
    delay(100);
  }
}

void Fade() {
  analogWrite(ledPin1, brightness);
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }

  delay(30);
}

Ouch.

you already had these three states:

enum Outcomes {
  GOOD,
  EARLY,
  LATE,
};

here

enum GameState {
  STAND_BY,
  ACTIVE_GAME,
  EARLY_PRESS,
  GOOD_PRESS,
  LATE_PRESS,
};

did you even try it unadulterated?

You mean your code unadulterated? In case I haven't expressed myself corrected, here are the rules of what I intend the game to be:

  • wait for a button press. once this happens, a led blinks once indicating the game begins. "9090" is printed in the serial (is a code that sends a signal to the PC to play a sound).
  • after a random lapse, the led lights up, and a clock starts to measure the time until you press the button again. In this lapse of time, nothing is printed.
  • if you press the button after the light is turned on, it shows the reaction time in seconds (which the computer stores in a CSV file).
  • if you press before the led lights up, it blinks three times and the game ends. ("1010" is a code that signals the PC to play an error sound). it then should return to an idle state and return to step 1.
  • if you don't press the button after a time, the led blinks twice and the game ends. returns to step 1. (another code goes here, i haven't thought of it yet).
  • once the game ends, it only begins again if you press the button again.

Those Outcomes states were a test for something else. I'm going to remove them, unless you see a better use for them.

luispotro:
Those Outcomes states were a test for something else. I’m going to remove them, unless you see a better use for them.

this is closer:

/* Reaction Time Game

Flashes blue  "ready lite" waiting for you to press buttton to start the game
Waits random interval to breifly illuminate green led
If you press button while green, green led blinks
Early or late, red led blinks
Press button again to return to ready state and start over!!!
*/

#define TIMEOUT_MILLISECONDS  500UL  // not too tough; make smaller for a bigger challenge

const char* const stateText[] = { "Stand By", "Active Game", "Early Press", "Good Press!!!", "Late Press"};

enum GameState {
  STAND_BY,
  ACTIVE_GAME,
  EARLY_PRESS,
  GOOD_PRESS,
  LATE_PRESS,
};

GameState gameState = STAND_BY;
GameState lastState;

byte buttonPin = 5;
byte redLed = 6;
byte greenLed = 13;
byte blueLed = 8;

unsigned long lastMillis = 0;
unsigned long randomTimerDelay = 0;
unsigned long lightTimerStart = 0;

void setup()
{
  Serial.begin(112500);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(redLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);
  randomSeed(analogRead(A4));
  Serial.println(stateText[gameState]);
}

void loop()
{
  bool pressed = checkButton();
  if (gameState == STAND_BY)
  {
    //fastFlash(blueLed);
    if (pressed)
    {
      digitalWrite(blueLed, HIGH);
      delay(250);
      digitalWrite(blueLed, LOW);
      randomTimerDelay = 1000 + random(5000);  // random anticipation time between 1 and 6 seconds
      gameState = ACTIVE_GAME;

    }
  }
  else if (gameState == ACTIVE_GAME)
  {
    unsigned long elapsedMillis = millis() - lastMillis;
    if (elapsedMillis >= randomTimerDelay && !digitalRead(greenLed))
    {
      digitalWrite(greenLed, HIGH);
      lightTimerStart = millis();
      Serial.println(F("Lite On!!"));
    }
    else if (elapsedMillis > randomTimerDelay + TIMEOUT_MILLISECONDS)
    {
      Serial.println(F("TimeOut!!"));
      for (byte i = 0; i < 2; i++)
      {
        digitalWrite(redLed, HIGH);
        delay(250);
        digitalWrite(redLed, LOW);
        delay(250);
      }
      digitalWrite(greenLed, LOW);
      gameState = LATE_PRESS;
    }
    if (pressed)
    {
      if (digitalRead(greenLed))
      {
        Serial.print((millis() - lightTimerStart) / 1000.0, 4);
        Serial.println("seconds Reaction Time");
        Serial.println("9090");
        digitalWrite(blueLed, HIGH);
        delay(250);
        digitalWrite(blueLed, LOW);
        digitalWrite(greenLed, LOW);
        gameState = GOOD_PRESS;
      }
      else
      {
        for (byte i = 0; i < 3; i++)
        {
          digitalWrite(redLed, HIGH);
          delay(250);
          digitalWrite(redLed, LOW);
          delay(250);
        }
        Serial.println("1010");
        gameState = EARLY_PRESS;
      }
    }
  }
  else if (gameState == EARLY_PRESS)
  {
    if (pressed)
    {
      gameState = STAND_BY;
    }
  }
  else if (gameState == GOOD_PRESS)
  {
    if (pressed)
    {
      gameState = STAND_BY;
    }
  }
  else if (gameState == LATE_PRESS)
  {
    if (pressed)
    {
      digitalWrite(redLed, LOW);
      gameState = STAND_BY;
    }
  }
  if (lastState != gameState)
  {
    Serial.println(stateText[gameState]);
    lastState = gameState;
  }
}

bool checkButton()
{
  static byte lastButtonState = 1;
  byte buttonState = digitalRead(buttonPin);
  if (buttonState == 0 && lastButtonState == 1 && millis() - lastMillis > 75UL) // <<<<<<< adjust 75 down as far as possible
  {
    Serial.println(F("!"));
    lastMillis = millis();
    return true;
  }
  lastButtonState = buttonState;
  return false;
}

//void fastFlash(int pin)
//{
//  static unsigned long lastFlashMillis = 0;
//  if (millis() - lastFlashMillis > 200UL)
//  {
//    digitalWrite(pin, !digitalRead(pin));
//    lastFlashMillis = millis();
//  }
//}

I think I got it. I’m not absolutely sure if the value is exactly the reaction time, but it’s preeetty close to it.

Check it out:

/* REACTION TIME (with 2 leds) v3.0 
    Luis Andrés Gonzalez
   Reaction time original version from http://www.instructables.com/id/Arduino-Reaction-Time-Tester/?ALLSTEPS
   Send data to processing via the Serial Port original from By Elaine Laguerta http://url/of/online/tutorial.cc
*/
#define TIMEOUT_MILLISECONDS  5000UL  // not too tough; make smaller for a bigger challenge

const char* const stateText[] = { "Stand By", "Active Game", "Early Press", "Good Press", "Late Press"};

enum GameState {
  STAND_BY,
  ACTIVE_GAME,
  EARLY_PRESS,
  GOOD_PRESS,
  LATE_PRESS,
};


const byte buttonPin = 6;  // pin where the button will be connected
const byte ledPin1 = 3 ;   // Left LED
const byte ledPin2 = 8 ;   // Middle LED
const byte ledPin3 = 11;   // Right LED

GameState gameState = STAND_BY;
GameState lastState;

// declare some variables:
boolean lastButton = LOW;
boolean pressed = LOW;
unsigned long lastMillis = 0;
unsigned long elapsedMillis;


long startTime;
long endTime;
int randomMillis;
long beginTime;
float elapsedTime;

float totalTime;
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

void setup() {
  // Setup button and LEDs:
  pinMode(buttonPin, INPUT);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  // Begin serial communication
  Serial.begin(9600);
  
}

void loop() {
  startTime = millis ();
  // read the pushbutton input pin in the current loop:
  pressed = checkButton();

  if (gameState == STAND_BY) {
    Fade();
    Light(ledPin1,"off");
    if (pressed) {
      endTime = millis();
      Light(ledPin1, "off");
      randomMillis = random(2, 8) * 1000; // generates a random number of milliseconds between 2 and 5
      Blink(1);

      gameState = ACTIVE_GAME;
      Light(ledPin3,"off");
      Serial.println("9090"); // signal code for start sound
      beginTime = millis() - lastMillis;
      

    }
  }

  else if (gameState == ACTIVE_GAME) {
    elapsedMillis = millis() - lastMillis;

    if (elapsedMillis >= randomMillis) {
      if (elapsedMillis < randomMillis + TIMEOUT_MILLISECONDS) {
        Light(ledPin1, "on");
        


      }
      else if (elapsedMillis > randomMillis + TIMEOUT_MILLISECONDS) {
        Serial.println("7777");
        delay(1000);
        Light(ledPin1, "off");
        gameState = LATE_PRESS;
      }

    }
    else if (pressed)
    {
      if (digitalRead(ledPin1))
      {
        gameState = GOOD_PRESS;

      }
      else
      {
        gameState = EARLY_PRESS;
      }
    }


  }
  else if (gameState == EARLY_PRESS) {

    Serial.println("1010"); // signal code for early response
    Blink(3);
    gameState = STAND_BY;
    delay(1000);

  }
  else if (gameState == GOOD_PRESS) {

    gameState = STAND_BY;
    
    long reactionTime = (startTime - endTime - randomMillis);
    Serial.println(reactionTime);
    
    
  }
  else if (gameState == LATE_PRESS) {
    gameState = STAND_BY;
    delay(1000);
  }


}




bool checkButton()
{
  static byte lastButtonState = 1;
  byte buttonState = digitalRead(buttonPin);
  if (buttonState == 0 && lastButtonState == 1 && millis() - lastMillis > 5UL) // <<<<<<< adjust 75 down as far as possible
  {
    lastMillis = millis();
    return true;
  }
  lastButtonState = buttonState;
  return false;
}

void Light(int lednumber, String onOff) {
  if (onOff == "on") {
    digitalWrite(lednumber, HIGH);

  } else if (onOff == "off") {
    digitalWrite(lednumber, LOW);
  }
}
void Blink(int repetitions) {
  for (int i = 0; i < repetitions; i++) {
    digitalWrite(ledPin2, HIGH);
    delay(100);
    digitalWrite(ledPin2, LOW);
    delay(100);
  }
}

void Fade() {
  analogWrite(ledPin3, brightness);
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  delay(30);
}

Thank you so far for the help. One way or another your suggestion helped me crack this through. ;D