A minimal, deterministic 1D LED game framework for ESP32, featuring runtime game selection via web interface. All 11 games are compiled into a single firmware image, and you can switch between them without recompiling!
- ๐ฎ 11 Complete Games - All games available in a single firmware
- ๐ Web Interface - Select games, monitor status, and view LED strip simulation
- ๐ Runtime Game Selection - Switch games without recompiling
- ๐พ EEPROM Persistence - Selected game persists across power cycles
- ๐ก AP Mode by Default - Self-hosted WiFi access point (no router needed)
- ๐ฏ Touch Controls - Built-in ESP32 capacitive touch pins (no extra hardware)
- ๐งช Unit Tests - Comprehensive test suite (13 test suites, 100+ tests)
- MCU: ESP32 development board (esp32dev target)
- LED Strip: WS2812B (NeoPixel-style, GRB color order)
- LED Data Pin: GPIO 16 (locked unless explicitly changed)
- LED Count: Configurable via
NUM_LEDSdefine (default: 8) - Input: ESP32 capacitive touch pins (no additional hardware needed!)
- Power: Ensure adequate power supply for your LED strip (WS2812B LEDs can draw significant current at full brightness)
- Connect the LED strip data line to GPIO 16
- Connect LED strip power (5V) and ground to appropriate power supply
- Ensure common ground between ESP32 and LED strip
- Touch Input: No wiring needed! Touch the following GPIO pins directly:
- Left: GPIO 4 (Touch0)
- Right: GPIO 15 (Touch3)
- Action: GPIO 13 (Touch4)
- Alt: GPIO 12 (Touch5)
You can touch these pins directly with your finger, or connect wires/foil pads to them for a more robust setup.
- PlatformIO installed (CLI or IDE extension)
- ESP32 development board
- WS2812B LED strip
- Clone this repository:
git clone https://github.com/Skeyelab/ESP32-Game.git
cd ESP32-Game- Build and upload:
pio run -e esp32dev -t upload-
Connect to WiFi:
- Look for WiFi network:
ESP32-Game - Connect (no password required)
- Open browser to:
http://192.168.4.1
- Look for WiFi network:
-
Select a game:
- Use the web interface to choose from 11 available games
- Game selection is saved and persists across power cycles
All 11 games are compiled into the firmware and accessible via the web interface:
- Test - Simple test game to verify touch controls (move LED, change color, flash strip)
- 1D Pacman - Control a yellow dot to eat pellets while avoiding faster red ghosts. Power pellets let you temporarily turn the tables.
- Lava Run - Control a white dot to cross unstable lava zones. The lava erupts intermittently, so you must move quickly when it's safe.
- Lava Stealth - Avoid deadly lava and reach the green goal. You have a "stealth mode" that lets you temporarily pass through danger.
- FlappyBird - Control a bird to navigate through gaps in obstacles. Press to "flap" and move up, gravity pulls down.
- 1D Pong - Classic Pong game on a 1D LED strip. Control paddle to bounce ball, opponent AI.
- RGB Guardian - Color-matching defense game. Enemies spawn with random colors, match bullet color to enemy color to score.
- RGB Guardian 2 - Enhanced version with multiple enemies and improved mechanics.
- Pulse Warrior - Rhythm-based game where you must time actions with pulses. Press at the right moment to score points.
- Color Runner X - Run through colored zones, matching your color to pass through. Change your color to match obstacles.
- 1D Splatoon - Paint the LED strip with your color. Cover more area than the opponent to win.
All games use fixed timestep game loops for deterministic behavior.
The ESP32 runs a web server in AP (Access Point) mode by default, creating its own WiFi network.
- Connect to WiFi: Look for network
ESP32-Game(no password) - Open Browser: Navigate to
http://192.168.4.1 - Select Game: Use the game selection interface to switch between games
- Monitor Status: View real-time game status, score, and LED strip simulation
- Game Selection: Switch between all 11 games instantly via buttons or dropdown
- Real-time Status: Game name, score, and state (playing/game over/won/paused)
- LED Strip Simulation: Visual representation of the physical LED strip (updates every 500ms)
- Input Status: Monitor which touch buttons are currently pressed
- Auto-refresh: Dashboard updates automatically
GET /- HTML dashboardGET /status- JSON status with game info, score, state, input, and LED colorsGET /games- List of all available games with IDsGET /game/current- Current game ID and namePOST /game/select- Switch game (send{"gameId": 0}JSON body)
Key settings in src/main.cpp:
#define LED_PIN 16 // Data pin (locked)
#define NUM_LEDS 8 // Number of LEDs in your strip
#define BRIGHTNESS 10 // Brightness level (0-255)
#define LED_TYPE WS2812B // LED chip type
#define COLOR_ORDER GRB // Color orderThe ESP32 defaults to AP mode. To use WiFi connection instead:
- Edit
src/config/wifi_config.h:
#define WIFI_SSID "YourWiFiName"
#define WIFI_PASSWORD "YourWiFiPassword"- Modify
src/main.cppto connect to WiFi before starting AP mode (see code comments)
MQTT is disabled in AP mode (no internet connection). To enable:
- Configure in
src/config/mqtt_config.h - Modify
src/main.cppto enable MQTT client
All games are managed through a centralized game_manager system:
- Game Registry: All 11 games registered with unique IDs (0-10)
- Runtime Selection: Switch games via web interface or API
- EEPROM Persistence: Selected game saved to EEPROM (survives power cycles)
- Function Pointers: Each game exposes
game_XX_setup()andgame_XX_loop()functions
ESP32-Game/
โโโ src/
โ โโโ main.cpp # Main entry point
โ โโโ input/ # Input abstraction
โ โ โโโ touch_input.h
โ โ โโโ touch_input.cpp
โ โโโ games/ # Game implementations
โ โ โโโ game_manager.h # Game manager system
โ โ โโโ game_manager.cpp
โ โ โโโ game_00_test.cpp
โ โ โโโ game_01_pacman.cpp
โ โ โโโ ... (all 11 games)
โ โโโ status/ # Status monitoring
โ โ โโโ status_monitor.h
โ โ โโโ status_monitor.cpp
โ โโโ network/ # Network components
โ โ โโโ wifi_manager.h/cpp
โ โ โโโ web_server.h/cpp
โ โ โโโ mqtt_client.h/cpp
โ โโโ config/ # Configuration files
โ โโโ wifi_config.h
โ โโโ mqtt_config.h
โโโ test/ # Unit tests
โ โโโ test_game_manager/
โ โโโ test_touch_input/
โ โโโ test_pacman/
โ โโโ ... (all game tests)
โโโ platformio.ini # Build configuration
โโโ .github/workflows/ # CI/CD
โ โโโ ci.yml
โโโ AGENTS.md # Development guidelines
โโโ README.md # This file
This project includes comprehensive unit tests using PlatformIO's Unity testing framework.
# Run all tests
pio test -e native
# Run specific test suite
pio test -e native -f test_pacman-
13 Test Suites covering all games and systems:
test_game_manager- Game manager and runtime selectiontest_touch_input- Touch input system (button states, debouncing)test_game_logic- Core game mechanics- Individual game tests for all 11 games
-
100+ Tests covering:
- Game logic and mechanics
- Collision detection
- Score calculations
- State transitions
- Input handling
- Boundary checks
GitHub Actions automatically:
- Runs all unit tests on every push/PR
- Builds ESP32 firmware
- Uploads firmware as artifact
- Create
src/games/game_XX_name.cppfollowing the existing pattern - Implement:
static void game_setup()- Initialize gamestatic void game_loop(uint32_t dt)- Game update loopvoid game_XX_setup()- Wrapper function (calls game_setup)void game_XX_loop(uint32_t dt)- Wrapper function (calls game_loop)
- Register in
src/games/game_manager.cpp:- Add to
GAMES[]array with ID, name, and function pointers
- Add to
- Add tests in
test/test_XX_name/
See AGENTS.md for detailed development guidelines:
- Use struct over class (unless inheritance needed)
- Avoid dynamic memory allocation
- Prefer compile-time configuration
- Keep deterministic, frame-rate-independent behavior
- Preserve GPIO 16 for LED output
- Use FastLED library for LED control
- Read AGENTS.md for guidelines
- Follow established patterns
- Add tests for new features
- Run tests before submitting:
pio test -e native - Ensure builds succeed:
pio run -e esp32dev
This project values:
- Physical feedback over UI complexity
- Simple visuals with tight timing
- Hackability over polish
- Deterministic behavior for reliable gameplay
If a change makes the system harder to reason about on real hardware, it's probably the wrong change.
[Add your license here]