Audrey LuJosh WashingtonClara SelbredeJoshua KearneyAmanda Lu
Created April 22, 2019

React!

React! is a semi educational (but still fun!) quick response game. It's multiplayer and child-friendly so anyone can play!

23
React!

Things used in this project

Hardware components

Soil Moisture & Temperature Sensor
Seeed Studio Soil Moisture & Temperature Sensor
×2
Buzzer
Buzzer
×1
RGB Diffused Common Cathode
RGB Diffused Common Cathode
×2
Breadboard (generic)
Breadboard (generic)
×1
Resistor 100 ohm
Resistor 100 ohm
×2
Jumper wires (generic)
Jumper wires (generic)
×4
Seeed Studio Four Digit Display
×1
EK-TM4C123GXL TM4C Tiva LaunchPad
Texas Instruments EK-TM4C123GXL TM4C Tiva LaunchPad
×1
Grove Starter Kit for LaunchPad
Seeed Studio Grove Starter Kit for LaunchPad
×1

Software apps and online services

Energia
Texas Instruments Energia

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)

Story

Read more

Custom parts and enclosures

Housing

0.2" birch wood, laser cut

Schematics

Diagram for the Modules and Reset Button

Circuit Diagram for the LEDs

Code

React Game Code

C/C++
#include "TM1637.h"

#define true 1
#define false 0

// Pin defintions for the 4-digit display
#define CLK 39
#define DIO 38

# In/out pins
#define RESET_PIN 31
#define MOISTURE1_PIN 27
#define MOISTURE2_PIN 25
#define BUZZER_PIN 40
#define LED1_PIN 34
#define LED2_PIN 33

// Initialize the 4-digit display
TM1637 disp(CLK,DIO);

// Together, these represent the current state of the game
int score1 = 0;
int score2 = 0;
int player1Touching = false;
int player2Touching = false;
int resetPressed    = false;
int counting        = true;
int player1Played   = false;
int player2Played   = false;
int playing         = false;
int waiting         = false;
int count           = 40000;
float shift         = 0;
int buzzer_count    = 0;
int buzzer_on       = false;
int buzzer_duration = 0;

void setup() {
  // Initialize the buzzer
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RESET_PIN, INPUT);       
  pinMode(LED1_PIN, OUTPUT);          
  pinMode(LED2_PIN, OUTPUT);             

  // Initialize the display pins
  disp.init();

  // BRIGHT_TYPICAL = 2, BRIGHT_DARKEST = 0, BRIGHTEST = 7
  disp.set(BRIGHTEST);

  // Enable the colon
  disp.point(true);

  // Turn on the display
  display_scores();
}

void loop() {  
  // Read the input pins
  int moist1 = analogRead(MOISTURE1_PIN);
  int moist2 = analogRead(MOISTURE2_PIN);
  int reset = digitalRead(RESET_PIN);

  // The reset press is over, so reset the game
  if (resetPressed && !reset) {
    // Clear all of the states
    player1Touching = player2Touching = counting = player1Played = player2Played = waiting = playing = buzzer_on = resetPressed = false;
    score1 = score2 = count = shift = buzzer_count = buzzer_duration = 0;

    // Turn off the buzzer and refresh the display
    digitalWrite(BUZZER_PIN, LOW);
    display_scores();

    // Put the game back into a counting state
    counting = true;
    count = 100000;
    
    return;
  }

  // Check if the reset is pressed
  if (!resetPressed && reset) {
    resetPressed = true;
  }

  // The buzzer is on
  if (buzzer_count > 0) {
      buzzer_duration -= 1;

      // The buzzer finished its current on/off cycle
      if (buzzer_duration <= 0) {
        buzzer_count -= 1;

        // Toggle the buzzer with the correct frequency
        if (buzzer_on) {
          buzzer_on = false;
          digitalWrite(BUZZER_PIN, LOW);
          buzzer_duration = (int)(20.0*sin(buzzer_count/500.0 + shift)*sin(buzzer_count/500.0 + shift) + 30);
        }
        else {
          buzzer_on = true;
          digitalWrite(BUZZER_PIN, HIGH);
          buzzer_duration = 10;
        }
      }
   }

  if (counting) {
    // Count down
    count -= 1;

    // Move out of the counting state
    if (count <= 0) {
      counting = false;
    }
  }
  else if (playing) {    
    // Move from playing to waiting if required
    if (player1Played || player2Played) {
      playing = false;
      waiting = true;
      count = 40000;      
    }
  }
  else if (waiting) {
    // Decrement the waiting counter
    count -= 1;

    // If we're done waiting, turn off the lights and move into counting
    if (count <= 0) {
      waiting = false;
      counting = true;
      count = get_beep_delay()*100;
      
      digitalWrite(LED1_PIN, LOW);
      digitalWrite(LED2_PIN, LOW);
    }
  }
  else {
    // If none of the above states are active, start the game
    playing = true;
    buzzer_on = false;
    buzzer_duration = 0;
    shift = rand() * 2*PI;
    player1Played = player2Played = false;

    // Start the buzzer with a random time
    buzzer_count = random(400, 600)*2;
    if (buzzer_count > 1100){
      buzzer_count = 4000;
    }
  }

  if (player1Touching) {
    // The touch finished      
    if (moist1 <= 20) {
      player1Touching = false;
    }
  }
  else {
    if (moist1 >= 50) {
      player1Touching = true;

      // Give a point to player1 if this is the first touch
      if (playing && !player1Played) {
        score1 += 1;
        player1Played = true;
        digitalWrite(LED1_PIN, HIGH);
      }
      else if (!waiting) {
        // Deduct points if the touch is at the wrong time
        score2 += 1;
      }

      display_scores();
    }
  }

  if (player2Touching) {
    // The touch finished      
    if (moist2 <= 20) {
      player2Touching = false;
    }
  }
  else {
    if (moist2 >= 50) {
      player2Touching = true;

      // Give a point to player2 if this is the first touch
      if (playing && !player2Played) {
        score2 += 1;
        player2Played = true;
        digitalWrite(LED2_PIN, HIGH);
      }
      else if (!waiting) {
        // Deduct points if the touch is at the wrong time
        score1 += 1;
      }

      display_scores();
    }
  }
}

// This calculates a random delay for the buzzer beeps using a normal distribution
int get_beep_delay() {
  float rand1 = 0;
  
  for(int i = 0; i <4;i++){
    rand1 += (float) random(2,4);
  }
  
  rand1 /= 4.7;
  float rand2 = ((random(100000)/100000.)-0.5)*2;  

  return (int) (800+pow(10, rand1)+200*rand2);
}

// Refreshes the display with the current score
void display_scores() {
  if (score1 < 0 || score1 >= 100) {
    score1 = 0;
  }

  if (score2 < 0 || score2 >= 100) {
    score2 = 0;
  }

  disp.display(0, score1 / 10);
  disp.display(1, score1 % 10);
  disp.display(2, score2 / 10);
  disp.display(3, score2 % 10);
}

Credits

Audrey Lu
1 project • 0 followers
Contact
Josh Washington
1 project • 0 followers
Contact
Clara Selbrede
1 project • 0 followers
Contact
Joshua Kearney
1 project • 0 followers
Contact
Amanda Lu
2 projects • 0 followers
Contact

Comments

Please log in or sign up to comment.