Reaction Game

6,537

23

26

Introduction: Reaction Game

About: Coder by trade, tinkerer by hobby. Spends time working, running, family and computer games ...

My son has won a place on the World Scout Jamboree 2019 and I was looking at ways to help him fund raise. One of the options was to create some 'fair ground' style games that could be taken to various events and charge people to play them.

I had always fancied having a play with the Batak games you get in expensive gyms, but as a non-gym member I have never had a chance. Looking at the cost of hire, I'm not sure I could afford it anyway!

I therefore decided to build my own version!

The final product contains a number of different games which can be chosen without any additional set up.

Parts you will need:

Tools you will need:

  • Soldering iron (solder, stand, solder remover etc.)
  • 1.2mm drill bit
  • 1.5mm drill bit
  • Drill and drill bits
  • 25mm flat drill bit
  • Wire stripper/cutter
  • G-Clamps

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Basic Design

A reaction game is very simple. It is a timer, a display and how every many illuminated buttons that you require.

The main parts of the wiring for the reaction game is a collection of two independent circuits that are repeated. These two circuits are:

1. Button

There are many tutorials on adding buttons to an Arduino including on the official Arduino website.

2. Independently lit LEDs (12v)

For the LEDs, as we are using 12v LEDs, we require an external power supply that is separated from the Arduino which can only work with up to 5v. For a previous project (a photo booth that I hope to write up at some point) I used MOSFETs to interface between a Raspberry PI and some LED strip lights. I used this excellent tutorial regarding the connection between the PI and the LEDs. For this project I have simply repeated the exercise multiple times.

Output Displays

The third part of the game is the LED matrix display to display the score and time remaining. For this I used 4 of the linked MAX7219 matrix displays. To get them working I used the linked tutorial which links to the driver library, and gives examples of using the displays.

Step 2: Circuit Board - Button Connectors

The instructable has been written while building my second of the reaction games that I have made. During the building of the first reaction game I made a few minor errors, so have improved on the design slightly. (Ideally I would like to make a PCB for all of the electronics, and I plan to do that when I have more time).

  1. Drill two 6mm holes in the vero board at a convenient location. If using the same vero board, then I recommend the same location as I have used. This avoids all the major routes, including the large route that I use for ground. The holes are used for mounting the board to the back of the reaction game. In my original design I didn't do that, and ended up hot gluing the circuit board. That is fine until it goes wrong and I am in trouble!
  2. Using a 1.5mm drill bit, increase the size of the pins along one edge. The 4 pin female connectors that I use to connect each button to the board have significantly wider pins. As the 4 pin connectors span 2 holes each, only every other hole needs widening.
  3. Push all 8 of the female connectors to the board, and solder into place.

Step 3: Circuit Board - Main Wiring

This section details the wiring of the main components to the board.

  1. A 16 pin male header component it wired centrally near the bottom of the board. This is the interface between the buttons, LEDs and the Arduino
  2. Because of the vero board that is being used, it is easy to split the separate circuits (LED and button) into groupings. The female connector spans 8 holes. This means that the LED can use 4 holes and the button can use 4 holes to keep the circuitry in the same 'vertical'. Therefore all 8 circuits can be repeated with a space of 8 holes apart.
  3. To make wiring slightly easier I tended to wire all of the same parts for each circuit in turn (as shown in the pictures)

Step 4: Board

To mount the electronics I bought the largest board available that I could transport (610 mm x 1220 mm x 9 mm).

  1. I marked the locations of all the buttons.
    1. Each corner button is 100 mm x 100 mm from the corner.
    2. The top and bottom middle buttons are in the middle, but 100 mm from the edge
    3. The two buttons in the middle (left and right) are equal distance from the other buttons on the appropriate side.
  2. After marking the locations of the buttons I used a 25 mm flat head bit to drill out the holes for the buttons.
  3. I marked the locations of the displays
    1. A friend has a oscillating multi-tool, so I borrowed him to cut the rectangular holes for the display.
  4. Due to the thickness and design of the displays I used, I used a router to remove about 5mm deep of the MDF.
  5. I cut 3 support legs for the board. The legs are cut with an angle, allowing the board to be used both lying down on a table or standing up against a wall. The middle legs requires a slot for cables to be passed through.
    • On version 1 of the project I only used 2 legs, but that led to a lot of bouncing of the board when angled in the 'table top' (lying flat) position.
  6. Glue the legs into position.
  7. I painted the board using blackboard paint. This is mainly to allow us to draw on the board using chalk to advertise the game, and also write down the different game names on the buttons.
  8. Finally I hot glued two bolts to the board (near the top of the board) to mount the electronics via the 2 holes that were drilled earlier in the PCB. I also hot glued a ring of glue on (now topside of) the bolt to minimise the risk of short circuits.

Step 5: Wire the Buttons and Assemble

  1. Cut appropriate lengths of cable for each button. These cables will vary in length due to the distance of the board/buttons.
  2. On one end, screw the stripped wires into a connecting block. Keep all 4 wires in the same order for each connecting block as this will simplify the wiring later, and also make it easier to fix any issues. The order I used was:
    • RED - LED 12v
    • BLACK - LED Ground
    • YELLOW - Switch to pin
    • GREY - Switch 5v
  3. On the other end I crimped connectors to keep the connections nice and clean. I did run out of connectors so not all of mine have been done
  4. Once all of the connectors have been wired, assemble the buttons as shown. My LEDs were not marked, so getting them in the right orientation involved some trial and error, but that isn't possible until after the code has been completed
  5. My buttons had two small pieces of plastic on the back to stop the button rotating when in the board. This required two small holes to be drilled in the front of the board for each button. The easiest way of doing this I found was to put the button in and twist it by 45 degrees. After taking the button out, it was possible to see the two lines drawn by the pins. Drill the one end of each of these lines with a small 3mm drill bit. Make sure you drill the same end of each (e.g. the clockwise end of both lines!)

Step 6: Wiring the Arduino

The instructions below are for wiring the Arduino MEGA.

  • A 16 pin Male to Female ribbon jumper cable is required to be routed from the 16 pin header on the PCB to the digital data pins on the Arduino as shown in the diagram.
  • Two pins connect from the Arduino to the PCB. 5v goes to the small circuit on the PCB which has the RED wire. The Ground pin goes from the Arduino to the PCB,
  • The Display is wired as shown in the wiring diagram.
  • Finally the 12v wires for the LEDs are wired to a female jack connector.

The Displays

The displays are paired up and put in the holes (making sure they are put in the right way round). I use duct tape to secure the displays in the board.

The reason I use duct tape and don't permanently fix the displays in place is that I want the ability to play the game either standing up against a wall, or lying flat on a table. This is why the struts at the back are cut at an angle. However these two positions require the displays to be switched around so that they are the correct way round each time. Therefore by using the duct tape method they can be changed easily.

Step 7: Coding the Arduino

I am not going to give a huge tutorial on Arduino programming as there are some excellent tutorials, but I will step through my code giving a generic overview. I am sure I can improve on the code and also add in a number of additional games.

This project requires the HCMAX7219 libraries. There may be multiple versions available, but I used the ones referenced by the Hobby Components Blog. This is the reason I would recommend getting the matrix displays from here as it seems cheeky using their work without donating!

Once downloaded, edit the HCMAX7219.h file and change the following line to 4:

(line #31)

#define NUMBEROFDRIVERS 4

This value determines how many of the LED matrix displays are daisy chained together. For the one player game we use 4, for the two player game we use 8.

Attached to the Instructable is my code.

The code contains two arrays, one for the LEDs and one for the buttons:

const int LED[8] = { 2, 4, 6, 8, 22, 24, 26, 28 };
const int BUTTON[8] = { 3, 5, 7, 9, 23, 25, 27, 29 };

By using arrays, it is possible to index a specific button, and return the appropriate pin values.

The program consists of the following main parts:

  1. Setup - Run once to set up the game when the Arduino is powered on
  2. Loop - Constantly run
    1. ScreenSaver - Randomly light the buttons until a button is pressed. There are 3 screen savers in the program which are randomly chosen
    2. CountDown - When a button is pressed, perform a short countdown, flashing the lights faster and faster so that the player is ready to start
    3. PlayGame - Play the actual game

Setup

  • Setup randomises the seed by reading 'noise' from an analog port.
  • If DEBUG is set, it opens the serial port. When running with DEBUG set, there can be a significant delay in reading the buttons, so turn off the DEBUG when running the game properly
  • Set up all the input and output pins appropriately
/*<br>  Set up the game
*/
void setup() {
  // Set up the seed
  randomSeed(analogRead(0));<br>  if (DEBUG)
    Serial.begin(9600);
  
  // Set up the pins
  for (int i = 0; i < NUMBER_BUTTONS; i++)
  {
    pinMode(LED[i], OUTPUT);
    pinMode(BUTTON[i], INPUT);
  }
}

Loop

  • The main loop starts the 'screen saver', which waits for a button press
  • Display the count down of flashing the lights faster and faster before starting
  • Play the game
/*<br>  The main loop
*/
void loop() 
{
  Debug("DEBUG ON - ", 0);
  // Run the screen saver
  ScreenSaver();<br>  // Countdown to start
  CountDown();<br>  // Play the game
  PlayGame();
}

Screen Saver

The 'screen saver' simply flashes the buttons on in different patterns. This was useful for debugging the electronics, as well as 'advertising' that the reaction game is working and ready to play. I created 3 different screen savers, from simply randomly showing lights, building up and breaking down all the lights, and showing the lights in different lines that 'bounce' around. Each screen saver is in its own function that turns on and turns off the appropriate lights while waiting for a button to be pressed. As we have 8 buttons, each button corresponds to a bit in a byte. This allows the SetLEDs function to use bitwise operations to turn on and off the lights.

The Build up and Lines screen savers use a lookup table that contains the byte patterns to display. The random screen saver simply picks a random b=number between 1 and 255 and displays the lights that correspond to that number.

/*<br>  Randomly does a screen saver
*/
void ScreenSaver()
{
  int screenSaver = random(3);
  bool response = false;
  
  while (!response)
  {
    switch(screenSaver)
    {
      case 0:
        Debug("Screen saver random: ", screenSaver);
        response = ScreenSaverRandom();
        break;
      case 1:
        Debug("Screen saver build up: ", screenSaver);
        response = ScreenSaverBuildUp();
        break;
      case 2:
        Debug("Screen saver lines: ", screenSaver);
        response = ScreenSaverLines();
        break;
      default:
        Debug("Screen saver default: ", screenSaver);
        response = ScreenSaverRandom();
    }
  }
}

Setting the LEDs

The following two functions are used to set the LEDs on and off (depending on the requirements of that is calling them).

SetLED writes to a specific pin, setting the pin to HIGH or LOW.

SetLEDs uses a byte pattern to set multiple LEDs on and off.

/*<br>  Set a button
*/
void SetLED (int button, int led)
{
  if (button != HIGH)
    digitalWrite(led, LOW);
  else
    digitalWrite(led, HIGH);
}<br><br>/*
  Set the LED pattern using bits
  0000 0001 - LED 01
  0000 0010 - LED 02
  0000 0100 - LED 03
  0000 1000 - LED 04
  0001 0000 - LED 05
  0010 0000 - LED 06
  0100 0000 - LED 07
  1000 0000 - LED 08
*/
void SetLEDs (int pattern)
{
  Debug("SetLEDs: ", pattern);
  int bitPattern = 0x01;
  
  for(int i=0;i<NUMBER_BUTTONS;i++) {<br>    if ((pattern & bitPattern) != 0)<br>      SetLED(HIGH, LED[i]);<br>    else<br>      SetLED(LOW, LED[i]);<br><br>    bitPattern = bitPattern << 1;<br>  }<br>}

Check for a button press

The following function returns true is any button has been pressed, or false if none have.

/*<br>  Check to see if any button is pressed
*/
bool CheckButtons()
{
  for (int i=0; i< NUMBER_BUTTONS; i++)
  {
    if(digitalRead(BUTTON[i]) > 0)
    {
      Debug("CheckButtons() - pressed: ", i);
      return true;
    }
  }  Debug("CheckButtons() - NOT PRESSED - ", -1);
  return false;
}

Play the game

This function is the main one player game. It simply loops for 31 seconds, updating the time, turning on a single LED, and waiting for the appropriate button to be pressed. When the appropriate button has been pressed, it increments the score, randomly choses a different button and repeats.

The game actually lasts for 31 seconds, but when using 30 seconds the perception is that you are getting 29 seconds. For a 31 second game, the timer shows 30 seconds and then waits a second to decrement. When it reaches 0 the game stops. If you were to use a 30 second timer, the game would show 30 seconds and immediately change to 29 seconds. This seems like you aren't getting the full 30 seconds (although you are). I found it better to give an extra second than make the user think they were being cheated!

Once the time has elapsed it shows the players score for 10 seconds, updates the high score if appropriate and returns to the screen saver (which shows the high score for the game).

/*<br>  Play the game
*/
void PlayGame()
{
  unsigned long endTime = millis() + 31000;
  int score = 0;
  
  Debug("endTime: ", endTime);
  Debug("millis(): ", millis());  long randButton = random(8);  
  while (millis() < endTime)
  {
    // Set the button to press as lit
    SetLED(HIGH, LED[randButton]);
    
    UpdateDisplay((endTime - millis())/1000, score);
    
    // Check to see if the button was pressed
    if(digitalRead(BUTTON[randButton]))
    {
      score ++;
      // Turn off the button
      SetLED(LOW, LED[randButton]);
      
      // Get the new button and check it has changed
      int newButton = random(8);
      while(newButton == randButton)
      {
        newButton = random(8);
      }
      
      // Values differ, so continue
      randButton = newButton;
    }
  }
  
  // Clear all the LEDs
  SetLEDs(0);
  
  // Wait 10 seconds to show the score
  delay(10000);
  
  // If a new high score, set it
  if (score > highScore)
    highScore = score;
}

Updating the display

This function updates the display during the game. The function converts the time and score to strings, prefixing any 1 character values with a '0' to pad them out. It then sends the buffer to the HCMAX7219 library to print the values, and then refreshes the display.

The high score function does very similar work, but shows the value HI and the high score.

void UpdateDisplay(unsigned long time, int score)<br>{
  // Update the time, make sure it is 2 digits
  String timeStr = String(time);
  if(timeStr.length() < 2)
    timeStr = "0" + timeStr;<br><br>  // Add the score which must be 2 digits
  String scoreStr = String(score);
  if(scoreStr.length() < 2)
    scoreStr = "0" + scoreStr;<br><br>  // Combine the string
  String numberStr = timeStr + scoreStr;
  
  char charBuf[5];
  numberStr.toCharArray(charBuf, 5);<br><br>  // Display the string
  HCMAX7219.printMatrix(charBuf,32);
  HCMAX7219.Refresh();
}

Improvements made for the 2 player game

I have made a few improvements for the 2 player game that should be moved back to the one player game. These include:

  1. The high score is stored in the EEPROM so that when the game is turned off it saves the high score. When the game is first turned on, the setup has been modified to look for button 7 being pressed. If button 7 is pressed on start up it resets the high score to 0.
  2. The CheckButtons function was changed to return -1 if no button was pressed, or the value of the button that was pressed. This allows the main menu to check the value returned and chose a different game to be played in the main loop.

Step 8: Optional Improvements

As I progressed on the original project I was continuously improving, updating and refining what I was doing.

Second board for 2 player games

Originally I was looking at the one player reaction game, but when play testing the game, several other ideas came up that could be implemented. The first one is the two player option. By having a second board, a significant number of additional games could be coded. By using a Arduino Mega, it is possible to run the two boards off one processor.

Improve the number of game types

There are a significant number of game types available. Most are a variation on a theme

  1. Reaction game - similar to 'whack a mole'. If it lights up, press the button, get a point, repeat for 30 seconds.
  2. Reaction minus game - same as game #1, but you lose a point for each press you get wrong. You can only go back to zero though (display isn't large enough for negative numbers).
  3. Multiple button reaction game - Similar to #1, but multiple buttons light up and all have to be cleared before a new random set of buttons are displayed.
  4. Simon says - Although all my buttons are a single colour, it is possible to light up the lights in a given order and make the player repeat the given pattern

Add displays to the buttons

If you could add a matrix display to each button, and a larger matrix display in the middle, you could ask simple questions with multiple choice answers. Even without a display on each button, you could number each button and ask simple math questions.

Step 9: Conclusion

During the write up I was doing some research to document my decisions and was surprised by the cost of hire of the Batak games, as these reaction games are so easy to make. This game can be modified in many ways including adding more buttons, (the MEGA should be able to handle 20+ for a single player game), larger displays to allow questions and answers, and many more game types.

I hope people find the instructable useful!

Game Life Contest

Participated in the
Game Life Contest

2 People Made This Project!

Recommendations

  • Trash to Treasure Contest

    Trash to Treasure Contest
  • Raspberry Pi Contest 2020

    Raspberry Pi Contest 2020
  • Wearables Contest

    Wearables Contest

26 Discussions

0
broomheadk
broomheadk

Question 6 weeks ago

What a fantastic game, it attracts young and old alike. Built this game, but modified some parts of the construction, which I am prepared to share with others, especially the author/coder who originated this game. Hats off to you sir!. First version I built was used to attract students to our stand to interest people in courses at our college, it was a knockout, people flocked to the game. I am interested, and started, to build a second version of the game, all financed by myself, with one sole purpose, to raise money for charity, not personal gain. My question is to coders, or the author, I wish to change the parameters of the game! I am a newbie to arduino coding, but fascinated by it. The original game lasts for 30 seconds, I wish to extend that to 60 seconds (which I have done). Secondly, the highest score I saw in the 30 seconds version was an amazing 79, therefore I need to raise the score level to the 100+, which means adding an extra 8x8 matrix, and the code cannot be restricted to 2 digits, at least 3 digits.Can anyone help? much appreciated.

0
Adam Redfern
Adam Redfern

4 months ago

Great project. I have been building something very similar and was struggling with the code but upon researching on how others have written code similar to what I want I came across this. Just a few questions. I have 12 buttons on my game so in the code do I just need to change the number of buttons and assign them to some pins? Also how do you start the game and select the game mode.

0
billytkid
billytkid

Question 7 months ago

Great instructable! I'm in the process of making this as a game in our office.

I've built a test rig on a Mega and I'm having some issues with random buttons being 'pressed' even though they're not, and I'm assuming it's because the buttons when not +5v are floating.

How are you pulling each read pin to 0v?

0
Dazhfc1
Dazhfc1

8 months ago

Hi RORSCHACH
I've competed the 2nd board for the 2 player game. Is it possible for 2 players to play with the same pattern of buttons over the 30seconds to see who gets the higher score, but code it so they don't turn each others buttons/light off.
I've also tried the 2 player code on one board for 1 player and commented out the 'menu options' for the 2 player games in the main loop as you suggested, but the lights get stuck when it is going through the screensaver. Any idea what I might be doing wrong?
My boy is loving this. Thank you for taking the time to share the instructions and code.


0
R0RSCHACH
R0RSCHACH

Reply 8 months ago

I will try to add in this as a new mode.
It will take a re-think on how the game works as I need to pre-set the buttons at the start of the game, then play through the buttons in order as player 1 may be significantly quicker than player 2.
I will try to sort this out during the week or next weekend. I'll keep you posted!

0
Dazhfc1
Dazhfc1

Reply 8 months ago

Thank you.

0
Dazhfc1
Dazhfc1

8 months ago

Thanks for this. I've just completed my first board and it works great. My boy loves it. I'm thinking about adding the 2nd board for 2 players. Does your 2 player code include the additional games you mention, or are these just just suggestions of what else could be done. Thanks again for this great tutorial and code.

0
R0RSCHACH
R0RSCHACH

Reply 8 months ago

Yes the 2 player games are included. If you have any other ideas for games, let me know and I'll try to include them

0
Dazhfc1
Dazhfc1

Reply 8 months ago

Thank you. I'm going to try and make the 2 player version in to a table. I'll let you know if we come up with any ideas.

0
masher38
masher38

9 months ago

I built this almost exactly the same as R0RSCHACH and it works perfectly. I changed the LEDS for white ones (in yellow buttons) as they were a bit brighter and easier to see and I changed the RSET resistor on the dot-matrix displays from 10k to 22k, reducing their brightness and the overall current draw - making life a bit easier for my voltage regulator :)
Many thanks to R0RSCHACH for an excellent project.

0
pietro.tordini
pietro.tordini

10 months ago

Hi, i have to report a big issue that's breaking the HW:
I replicated the project on two board, and in one of them a 60mm arcade switch was defective (always in contact) and because of it before i found out it "drove the arduino crazy" making the game completely unplayable and burned the chip of the 1st and the 3rd display connected.
It took me 5 hours of troubleshooting to find out the cause of the issue, and once removed and replaced, the board started working again as expected.
How can i or (or the author) add to the code a part to "check if one button is always on" and if so remove it from the array (also from the game logic).

0
masher38
masher38

Reply 9 months ago

That's interesting. I had exactly the same issue (with a different, but similar project to this one) just last week. The micro-switch was measuring 200 ohms across the Normally Open contacts, causing all sorts of issues. I was able to prise the switch apart quite easily and, with the aid of a magnifier, I could see a very fine... it didn't look like wire, more like a hair, bridging the Com and NO contact (intriguingly, both contacts are marked on the body as NC - cheap micro-switches!). Anyway, I blew the hair out and it's been fine ever since. Possibly doesn't help you with your issue, but I thought it worth mentioning, should you have the problem again.

0
StamatisK3
StamatisK3

Question 11 months ago on Step 8

How to connect display matrix on the arduino? For score and time?

1
AjayS117
AjayS117

1 year ago

Hi, this looks like a super project... i just had a quick question regarding the 12v cables on the matrix board... I noticed 2 red and 2 black, is there any reason for this?... I was assuming that you just connect ONE of the reds and blacks to 12v

0
AjayS117
AjayS117

Reply 11 months ago

Thanks so much for answering my question... I had forgotten that the design could also be used for 2 boards!!! Hence the 2 wires....this was an amazing project and I really enjoyed building it.. thanks again.

0
R0RSCHACH
R0RSCHACH

Reply 11 months ago

Apologies for the delay, I didn't notice the question come in.
The two red and two blacks are there as this was my second board for the 2 player game.
You are correct, one red and one black goes to the 12v power supply via a female jack connector. This plugs directly into the 12v power supply.
The second set goes to a male jack connector which plugs directly into the other board (via a female jack connector). This was done so I only needed a single 12v power adapter to power both players games LEDs.
You do need a 9v Arduino power supply to power the Arduino (which controls both games).
Hope this helps.

0
StefanK86
StefanK86

Question 1 year ago

Hello
Cool project. Although I do not know much about Arduino, I was able to rebuild the project without major problems. I want to use the reaction game for my children to shake up the reaction in the sport. I have decided for the 1 Player variant with 8 switches. I wanted to adapt the 1 Player variant so that I can use the -1 Game and EEPROM. Unfortunately, I have not succeeded so far. Maybe you would have me a hint how I could do that?
Next I would have the question of whether it is possible to replace the normal Led with a pixel Led Ring and this to shine, for example, with a random color?
Greetings Stefan

0
R0RSCHACH
R0RSCHACH

Answer 11 months ago

Apologies, I didn't see this question come in. I will try and adapt the 1 player game for you and post it soon.
As for the Neo Pixel LED ring, I believe this is possible. I am playing with Neo Pixels for my latest project (driven with an Arduino), and can change colours randomly for that. The biggest issue I suspect will be embedding the neo pixels in the switches, as (mine at least) don't give any room for threading the 3 wires through. However I have spotted a mod for the switches on Thingiverse that could be used:
https://www.thingiverse.com/thing:1952690
It does require a 3D printer though.

0
MikeH364
MikeH364

11 months ago


C:\Users\Downloads\ReactionGame\ReactionGame.ino:4:23: fatal error: HCMAX7219.h: No such file or directory
#include "HCMAX7219.h"
^
compilation terminated.
exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

any advise?

0
R0RSCHACH
R0RSCHACH

Reply 11 months ago

Have you downloaded the HCMAX7219 libraries detailed in Step 7? Once downloaded I believe I may have copied the files to the same directory as the sketch (hence the double quotes around the "HCMAX7219.h" rather than <HCMAX7219.h>).
The error is stating that it cannot find the file HCMAX7219.h, so this is probably the problem.
Hope that helps