How to Build an Arcade Reaction Tower with ESP32

Fast reflex game with LED cues, score tracking, and victory sounds

ESP32GamingBeginner40 minutes4 components

Updated

How to Build an Arcade Reaction Tower with ESP32
For illustrative purposes only
On this page

What you'll build

In this guide you will construct an arcade-style reaction tower using an ESP32, a WS2812B LED ring, a large arcade push button, a piezo buzzer, and an OLED score display. The game lights up a random LED on the ring as a cue, and you must slap the arcade button as fast as possible before the light moves on. Each successful hit earns points based on how quickly you reacted -- measured in milliseconds -- while a miss triggers a buzzer penalty sound and resets your combo multiplier. The OLED shows your current score, best reaction time, and combo streak in real time, and a victory fanfare plays when you beat your high score.

Arcade games are one of the most rewarding categories of maker projects because the feedback loop is immediate and physical. This build teaches you microsecond-precision timing with the ESP32's hardware timers, interrupt-driven button detection for accurate reaction measurement, random number generation for unpredictable cue placement, and smooth LED animations that provide clear visual feedback without blocking the main game loop. You will also implement a simple scoring algorithm with combo multipliers and persistent high-score storage in flash memory so your best run survives a power cycle.

The completed tower is a genuinely addictive tabletop game that friends and family will want to play repeatedly. The modular code makes it easy to add difficulty levels that shorten the reaction window, introduce multi-color cues where only a specific color should be hit, or chain multiple towers together over ESP-NOW for a competitive multiplayer experience. It is an ideal beginner project that produces something immediately fun while teaching timing, interrupts, and state management patterns that are essential for any real-time embedded application. For another interactive game prop, try the RFID treasure chest which combines NFC tag reading with a servo-driven lock mechanism.

Wiring diagram

Wiring diagram

Interactive wiring diagram

Components needed

ComponentTypeQtyBuy
WS2812B LED Ringactuator1
Arcade Buttonother1€8.30
Piezo Buzzeractuator1€4.75
SSD1306 OLEDdisplay1€4.30

Prices and availability are indicative and may have been updated by the supplier. Schematik may earn a commission from purchases made through affiliate links.

Assembly

1

Wire game controls

Connect LED ring DIN to GPIO4, arcade button to GPIO27, and buzzer to GPIO26.

2

Attach score display

Wire OLED SDA/SCL to GPIO21/GPIO22 and start reaction rounds.

Pin assignments

PinConnectionType
GPIO 4arcade-led-ring-1 DINDATA
GPIO 27arcade-button-1 SIGDIGITAL
GPIO 26arcade-buzzer-1 SIGPWM
GPIO 21arcade-oled-1 SDAI2C
GPIO 22arcade-oled-1 SCLI2C

Code

#include <Wire.h>
#include <FastLED.h>
#include <Adafruit_SSD1306.h>

#define LED_PIN 4
#define NUM_LEDS 16
#define BTN_PIN 27
#define BUZZER_PIN 26
#define SDA_PIN 21
#define SCL_PIN 22

CRGB leds[NUM_LEDS];
Adafruit_SSD1306 display(128, 64, &Wire, -1);
unsigned long roundStart = 0;
bool waitingForPress = false;
int score = 0;

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN);
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(140);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  pinMode(BTN_PIN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);
  randomSeed(micros());
}

void loop() {
  if (!waitingForPress) {
    int target = random(NUM_LEDS);
    fill_solid(leds, NUM_LEDS, CRGB::Black);
    leds[target] = CRGB::Orange;
    FastLED.show();
    roundStart = millis();
    waitingForPress = true;
  }

  if (!digitalRead(BTN_PIN) && waitingForPress) {
    int reactionMs = (int)(millis() - roundStart);
    score += max(0, 1500 - reactionMs);
    tone(BUZZER_PIN, reactionMs < 350 ? 2200 : 1200, 70);
    display.clearDisplay();
    display.setCursor(0, 0);
    display.printf("Reaction: %dms\nScore: %d", reactionMs, score);
    display.display();
    waitingForPress = false;
    delay(350);
  }
}

// Run this and build other cool things at schematik.io
Libraries: FastLED, Adafruit SSD1306, Adafruit GFX Library