Introduction: Cyclone LED Arcade Game

The intent of this project was to create a simple game using an Arduino that would be interactive and entertaining for kids. I remember the Cyclone arcade game being one of my favorite arcade games when I was younger, so I decided to replicate it. This is a very simple project that consists of an Arduino, string of individually adressable LEDs, and a push button.

The goal of the game is to stop the cycling light when it reaches the indicated (red) LED. If successful, the difficulty level will increase. If unsuccessful, the light cycle will restart at the current difficulty level.

This instructable was a huge resource for the core of my coding.

Step 1: Gather Supplies

  • Main Components:
    • Arduino (I used an UNO)
    • String of individually addressable LEDs (I used link)
    • Push button (I used link)
    • Printed circuit board (PCB) or breadboard
    • Power Supply (I used two separate power supplies, you may get away with one if you are creative)
      • 5V 3A for LEDs
      • 9V 1A for Arduino
  • Framework:
    • Electronics housing (I modified a wooden lamp fixture from Goodwill)
    • LED housing (I modified your standard wall clock and drilled holes using the minute identifiers as hole markings. Use a wood clock if possible to make drilling easier.)
    • Button housing (I used an elbow PVC pipe)
  • Tools / Other Materials:
    • Spare wiring for your circuit
    • 10K (pull-down resistor for switch) and 470 ohm (for data wire on LEDs) resistors
    • Drill for creating holes to house your LEDs and and making any necessary holes in your fixture to pass wires through
    • Soldering iron for soldering your circuit to a PCB
    • Hot glue gun for securing the LEDs to your fixture
    • Velcro or some means of securing the framework together
    • Gaskets optional for holes drilled for wires to pass through

Step 2: Upload Code

Make sure you download and add the "FastLED" library

The core of the code (void loop) consists of two states: push button high (End Game) and push button low (Playing). Once the user presses the button, the LED address the light was stopped on is compared to the address of the center LED. If they are not the same, all the lights flash red twice and the current level restarts. If they are the same, cylon (FastLED library script) runs twice, the difficulty level increases, and playing resumes. Once the player beats the last level, cylon runs eighth times and the game restarts at level 1.


//Cyclone Game

#include "FastLED.h"

//up to 50
#define NUM_LEDS 40 

#define CENTER_LED 21

#define DATA_PIN 7 

#define LED_TYPE WS2811

#define COLOR_ORDER RGB 

//range 0-64
#define BRIGHTNESS 50

//Definition of difficulty levels
#define EASY 1
#define MEDIUM 2
#define HARD 3
#define ON_SPEED 4
#define SONIC_SPEED 5
#define ROCKET_SPEED 6
#define LIGHT_SPEED 7
#define MISSION_IMPOSSIBLE 8

//Starting difficulty
int difficulty = 1;

// Define the array of leds
CRGB leds[NUM_LEDS];

// Did player win this round? This tag is used for difficulty parameters.
bool wonThisRound = false;

// Starting location of the cycling light
int LEDaddress = 0;

// Is game running?
bool Playing = true;

// Is this the first win?
bool CycleEnded = true;

// Button details
const int buttonPin = 9;
int buttonState = 0;

// Initialize the led library and arduino functions

void setup() 
{
  FastLED.addLeds(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

// The meat and potatoes
//Two Modes - Playing and End Game
void loop() 
{
  //END GAME
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH)
  {
    Playing = false; //User has pressed the button, and the LED has stopped on the winning address.
     for (int i = 0; i < NUM_LEDS; i++)
     {
      leds [i] = CRGB::Black;
     }
    leds[CENTER_LED] = CRGB::Red;
    leds[LEDaddress] = CRGB::Green;  
    FastLED.show();
    if (CycleEnded = true)
    {
      int diff = abs(CENTER_LED - LEDaddress); //Finds distance between the lit led and the center led
      if (diff == 0)
      {
        wonThisRound = true; //Player sucessfully beat the level
        if (difficulty != MISSION_IMPOSSIBLE)
         {
          for (int i = 0; i < 2; i++)
           {
            cylon();
           }
         }
        if (difficulty == MISSION_IMPOSSIBLE)
         {
          for (int i = 0; i < 8; i++)
           {
            cylon();
           }
          difficulty = 0; 
         }
        increaseDifficulty();      
        wonThisRound = false;
      }
       else
      {
      delay(1000);  
      for (int i = 0; i < 2; i++)
       {
        flash();
       }
      }
        CycleEnded = false;
      }
    LEDaddress = 0; 
    delay(250);
    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW)
    {
     Playing = true;
    }
  }
  
  //PLAYING
  if(Playing)
  {
    for (int i = 0; i < NUM_LEDS; i++)
    {
      leds[i] = CRGB::Black; //Turns off all the leds
    }
    leds[CENTER_LED] = CRGB::Red; //Sets center led color to green
    leds[LEDaddress] = CRGB::Green; //Sets cyling led color to red
    FastLED.show(); //Initializes light cycle
    LEDaddress++; //Sets light cycle to one led at a time
    if (LEDaddress == NUM_LEDS)
    {
      LEDaddress = 0;
    }
    delay(getTime(difficulty));
    buttonState = digitalRead(buttonPin);
    if (buttonState == HIGH)
    {
     Playing = false;
     CycleEnded = true;
    }
 }
}

//Level Parameters
int getTime(int diff) // Returns time delay for led movement base on difficulty
{
  int timeValue = 0;
  switch (diff) 
  {
    case EASY:
      timeValue = 100;
      break;
    case MEDIUM:
      timeValue = 80;
      break;
    case HARD:
      timeValue = 60;
      break;
    case ON_SPEED:
      timeValue = 40;
      break;
    case SONIC_SPEED:
      timeValue = 30;
      break;
    case ROCKET_SPEED:
      timeValue = 20;
      break;
    case LIGHT_SPEED:
      timeValue = 13;
      break;
    case MISSION_IMPOSSIBLE:
      timeValue = 7;
  }
  return timeValue;// Return the delay amount
}

//Winning difficulty increase parameters
void increaseDifficulty() 
{
  if (difficulty != MISSION_IMPOSSIBLE && wonThisRound) 
  {
    difficulty++;
  }
}

//Lost LED Show
void flash()
{ 
  fill_solid(leds, NUM_LEDS, CRGB::Red);
  FastLED.show();
  delay(500);
  fill_solid(leds, NUM_LEDS, CRGB::Black);
  FastLED.show();
  delay(500);
}

//Won LED Show
void fadeall() 
{ 
  for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } 
}

void cylon() 
{ 
  static uint8_t hue = 0;
  Serial.print("x");
  // First slide the led in one direction
  for(int i = 0; i < NUM_LEDS; i++) {
    // Set the i'th led to red 
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show(); 
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }
  Serial.print("x");

  // Now go in the other direction.  
  for(int i = (NUM_LEDS)-1; i >= 0; i--) {
    // Set the i'th led to red 
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }
}

Step 3: Install in Fixture

I am not going to go into details in this section. There are a thousand different ways to go about this part and I think you should be creative to make it look how you like it. That being said, the clock was pretty convenient to use for housing the LEDs as it had minute indicators that I was able to use as drill markings. Also, the glass cover also lets me use this as a table.

The velcro was very useful as well for securing the LED fixture to the electronics housing fixture. I also used velcro on the Arduino. This made it very convenient for pulling the Arduino out if I ever want to modify the code.

Step 4: Play!