|
Arduino Nano R3 |
x 1 | |
|
WS2812 Addressable LED Strip |
x 1 | |
|
Transistor NPN |
x 1 | |
|
Rotary potentiometer |
x 2 | |
|
Pushbutton |
x 4 | |
|
Buzzer |
x 1 |
![]() |
Soldering Iron Kit |
|
![]() |
arduino IDEArduino
|
Tug of War Arduino Game on WS2812 Led strip
A Tug of War is a classic team-based game where two opposing teams compete to pull a rope in opposite directions. The objective is to pull the other team across a certain marker (often a line or flag) positioned in the center of the rope.
This time I will describe how to make an Arduino version of this game for two players. In fact, each player represents a team and has its own color. Thanks to the LED strip with programmable RGB LEDs with a built-in WS 2812 chip we can make this game in a very simple way.
To make the game, we only need a few components:
- Arduino Nano microcontroller board
- Led Strip with 60RGB leds with built-in WS2812 chip
- Four buttons
- NPN Transistor
- Two potentiometyers 10K
- Two resistors
- and Buzzer
This project is sponsored by Altium 365 . Altium 365 is a cloud-based platform designed for electronics design and engineering. It provides a suite of tools for PCB design tools, including Requipments management, Supply chain, Library managment, ECAD connectivity, Co-design and integration, and manufacturing port
I'm actually using the box from a previous project of mine that used 4 buttons and two potentiometers, so I used the same hardware configuration, and the game even got more features and became more interesting to play. First, before I start playing, let me explain all the functions and how to play. Immediately after turning on the game, the two LEDs in the middle of the strip are activated, twice with red color, and the third time with magenta, which indicates the start of the game. This part is accompanied by appropriate sounds. Then, on both sides of these two LEDs, the remaining LEDs light up with the characteristic color for each player, in this case blue for Player1 and yellow for Player2.
The starting diode, seen from both sides, is magenta, and this is the limit to which we have to pull the opposing player. The movement of each player is indicated by beeps with different frequencies. Two red LEDs in the middle are actually the flag that shows the current position of the players. When this flag reaches one of the magenta LEDs, victory is declared for that player, in a way that all LEDs light up and flash three times with the color of the winner, of course by emitting appropriate sounds.
After the game ends, after a few seconds a new game starts in the way I explained previously. The two main buttons are used to pull the rope and the strength of the pull is proportional to the speed of pressing these buttons. The player who presses faster pulls the flag to his side. The second BOOST buttons, as the name suggests, are used to pull the rope with double strength and these buttons can only be used once during a specific game. The use of the BOOST button is signaled by a brief flashing of the magenta LEDs on the corresponding side of the player who used it.
Therefore, we need to think carefully at what point to use these buttons, which also gives the game a strategic component. When testing the game, I noticed that if the typing speed of both players is approximately the same, the game lasts a very long time and becomes boring. To avoid this moment, I used the first potentiometer to regulate the speed of movement of the rope, in 5 steps continuously. Here is what the movement looks like in the lowest and highest pulling speed. I used the second potentiometer to regulate the intensity of the LEDs, which is actually a very useful option that allows the device to adapt to operating in different conditions, for example, day and night.
As you can see, the Arduino code may not be fully optimized, but it is relatively understandable, so you can easily make changes to it according to your own ideas, especially in terms of changing colors, sounds, and speed.
Now I will demonstrate to you what the gameplay looks like, noting that I will represent both players, and in a real game with different players, the gameplay is far more interesting and even addictive.
And finally a short conclusion. This is an interesting simple to make Arduino game that can be made in less than a day. The simplicity is due to the LED strip consisting of 60 special LEDs with built-in chips, so at any moment we have full control of each LED individually thanks to the Adafruit_NeoPixel library. The device is built into a suitable box made of PVC material, and covered with colored self-adhesive wallpaper. The power supply is 5V and a minimum current of 1A.
#include <Adafruit_NeoPixel.h> // Pin definitions #define LED_PIN 6 #define BUTTON1_PIN 2 // Player 1 button #define BUTTON2_PIN 3 // Player 2 button #define BUZZER_PIN 4 // Buzzer pin #define LED_INTENSITY_POT A0 // Potentiometer for LED brightness #define SPEED_POT A1 // Potentiometer for game speed #define POWER1_PIN 7 // Player 1 power move button #define POWER2_PIN 8 // Player 2 power move button // LED strip configuration #define NUM_LEDS 60 // Total number of LEDs (29 + 2 + 29) #define CENTER_POS 30 // Center position (0-based index) // Game constants #define DEBOUNCE_TIME 50 // Button debounce time in milliseconds #define VICTORY_FLASHES 3 // Number of victory flashes #define FLASH_DELAY 200 // Delay between flashes in milliseconds #define MIN_CLICK_SPEED 1 // Minimum pixels to move per click #define MAX_CLICK_SPEED 5 // Maximum pixels to move per click // Power move constants #define POWER_BOOST 3 // Fixed amount added to speed during power move #define POWER_MOVES_COUNT 3 // Number of powered moves each player gets #define POWER_FLASH_DURATION 500 // Duration of power move activation flash #define MAX_POWER_SPEED (MAX_CLICK_SPEED + 2) // Maximum speed during power move // Initialize LED strip Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800); // Colors uint32_t COLOR_RED; uint32_t COLOR_BLUE; uint32_t COLOR_YELLOW; uint32_t COLOR_MAGENTA; const uint32_t COLOR_OFF = strip.Color(0, 0, 0); // Game state variables int flagPosition = CENTER_POS; // Current position of the center of the red flag unsigned long lastButton1Press = 0; unsigned long lastButton2Press = 0; bool gameActive = false; // Changed to false initially int clickSpeed = 1; // Number of pixels to move per click // Power move state variables bool player1PowerActive = false; bool player2PowerActive = false; int player1PowerMovesLeft = 0; int player2PowerMovesLeft = 0; bool player1PowerAvailable = true; // Can only use once per round bool player2PowerAvailable = true; // Can only use once per round unsigned long lastPower1Press = 0; unsigned long lastPower2Press = 0; bool button1LastState = HIGH; bool button2LastState = HIGH; bool power1LastState = HIGH; bool power2LastState = HIGH; void setup() { // Initialize LED strip strip.begin(); strip.show(); // Set up buttons with internal pull-up resistors pinMode(BUTTON1_PIN, INPUT_PULLUP); pinMode(BUTTON2_PIN, INPUT_PULLUP); pinMode(POWER1_PIN, INPUT_PULLUP); pinMode(POWER2_PIN, INPUT_PULLUP); pinMode(BUZZER_PIN, OUTPUT); pinMode(LED_INTENSITY_POT, INPUT); pinMode(SPEED_POT, INPUT); button1LastState = digitalRead(BUTTON1_PIN); button2LastState = digitalRead(BUTTON2_PIN); power1LastState = digitalRead(POWER1_PIN); power2LastState = digitalRead(POWER2_PIN); // Initial game state resetGame(); } void loop() { if (!gameActive) { playStartSequence(); } if (gameActive) { // Update LED brightness based on potentiometer updateColors(); // Update game speed based on potentiometer updateGameSpeed(); // Check for power moves checkPowerMoves(); // Check for button presses with debounce checkButtons(); updateLEDs(); } } void checkPowerMoves() { // Read current power button states bool power1CurrentState = digitalRead(POWER1_PIN); bool power2CurrentState = digitalRead(POWER2_PIN); // Check Player 1 power move button if (power1CurrentState == LOW && power1LastState == HIGH) { // Detect only falling edge if (millis() - lastPower1Press > DEBOUNCE_TIME && player1PowerAvailable) { activatePowerMove(1); lastPower1Press = millis(); } } // Check Player 2 power move button if (power2CurrentState == LOW && power2LastState == HIGH) { // Detect only falling edge if (millis() - lastPower2Press > DEBOUNCE_TIME && player2PowerAvailable) { activatePowerMove(2); lastPower2Press = millis(); } } // Update power button states power1LastState = power1CurrentState; power2LastState = power2CurrentState; } void activatePowerMove(int player) { if (player == 1 && player1PowerAvailable) { player1PowerActive = true; player1PowerMovesLeft = POWER_MOVES_COUNT; player1PowerAvailable = false; flashPowerMove(1); } else if (player == 2 && player2PowerAvailable) { player2PowerActive = true; player2PowerMovesLeft = POWER_MOVES_COUNT; player2PowerAvailable = false; flashPowerMove(2); } } void flashPowerMove(int player) { strip.clear(); // Flash player's side if (player == 1) { for (int i = 0; i < CENTER_POS; i++) { strip.setPixelColor(i, COLOR_MAGENTA); } tone(BUZZER_PIN, 2000, 200); // Power move activation sound } else { for (int i = CENTER_POS; i < NUM_LEDS; i++) { strip.setPixelColor(i, COLOR_MAGENTA); } tone(BUZZER_PIN, 2500, 200); // Power move activation sound } strip.show(); delay(POWER_FLASH_DURATION); updateLEDs(); } void playStartSequence() { // First update colors for the sequence updateColors(); // Flash center position in preparation for (int i = 0; i < 3; i++) { // First two beeps with one frequency if (i < 2) { strip.clear(); strip.setPixelColor(CENTER_POS, COLOR_RED); strip.setPixelColor(CENTER_POS - 1, COLOR_RED); strip.show(); tone(BUZZER_PIN, 800, 200); // Lower frequency for ready beeps delay(300); strip.clear(); strip.show(); delay(300); } // Final beep with different frequency else { strip.clear(); strip.setPixelColor(CENTER_POS, COLOR_MAGENTA); strip.setPixelColor(CENTER_POS - 1, COLOR_MAGENTA); strip.show(); tone(BUZZER_PIN, 1200, 400); // Higher frequency for start beep delay(400); } } // Start the game gameActive = true; flagPosition = CENTER_POS; updateLEDs(); } void updateColors() { // Read LED intensity from potentiometer (0-255) int intensity = map(analogRead(LED_INTENSITY_POT), 0, 1023, 0, 255); // Update colors with new intensity COLOR_RED = strip.Color(intensity, 0, 0); COLOR_BLUE = strip.Color(0, 0, intensity); COLOR_YELLOW = strip.Color(intensity, intensity, 0); COLOR_MAGENTA = strip.Color(intensity, 0, intensity); } void updateGameSpeed() { // Read speed value from potentiometer clickSpeed = map(analogRead(SPEED_POT), 0, 1023, MIN_CLICK_SPEED, MAX_CLICK_SPEED); } void checkButtons() { // Read current button states bool button1CurrentState = digitalRead(BUTTON1_PIN); bool button2CurrentState = digitalRead(BUTTON2_PIN); // Check Player 1 button (pulls flag left) if (button1CurrentState == LOW && button1LastState == HIGH) { // Detect only falling edge if (millis() - lastButton1Press > DEBOUNCE_TIME) { // Calculate move amount with a more balanced power multiplier int moveAmount = clickSpeed; if (player1PowerActive && player1PowerMovesLeft > 0) { moveAmount = min(moveAmount + POWER_BOOST, MAX_POWER_SPEED); player1PowerMovesLeft--; if (player1PowerMovesLeft <= 0) { player1PowerActive = false; } } flagPosition -= moveAmount; tone(BUZZER_PIN, player1PowerActive ? 800 : 1000, 20); lastButton1Press = millis(); } } // Check Player 2 button (pulls flag right) if (button2CurrentState == LOW && button2LastState == HIGH) { // Detect only falling edge if (millis() - lastButton2Press > DEBOUNCE_TIME) { int moveAmount = clickSpeed; if (player2PowerActive && player2PowerMovesLeft > 0) { moveAmount = min(moveAmount + POWER_BOOST, MAX_POWER_SPEED); player2PowerMovesLeft--; if (player2PowerMovesLeft <= 0) { player2PowerActive = false; } } flagPosition += moveAmount; tone(BUZZER_PIN, player2PowerActive ? 1300 : 1500, 20); lastButton2Press = millis(); } } // Update button states button1LastState = button1CurrentState; button2LastState = button2CurrentState; // Keep flag position within bounds flagPosition = constrain(flagPosition, 1, NUM_LEDS - 2); // Check for victory conditions if (flagPosition <= 1 || flagPosition >= NUM_LEDS - 2) { gameActive = false; celebrateVictory(); } } void updateLEDs() { strip.clear(); // Draw the red flag (2 LEDs) strip.setPixelColor(flagPosition, COLOR_RED); strip.setPixelColor(flagPosition - 1, COLOR_RED); // Draw Player 1 side (blue) for (int i = 0; i < flagPosition - 1; i++) { strip.setPixelColor(i, i == 0 ? COLOR_MAGENTA : COLOR_BLUE); } // Draw Player 2 side (yellow) for (int i = flagPosition + 1; i < NUM_LEDS; i++) { strip.setPixelColor(i, i == NUM_LEDS - 1 ? COLOR_MAGENTA : COLOR_YELLOW); } strip.show(); } void celebrateVictory() { // Determine winner's color uint32_t winnerColor = (flagPosition <= 1) ? COLOR_BLUE : COLOR_YELLOW; // Victory tune if (flagPosition <= 1) { playVictoryTune(1000); // Lower pitch for Player 1 } else { playVictoryTune(1500); // Higher pitch for Player 2 } // Flash victory animation for (int i = 0; i < VICTORY_FLASHES; i++) { // Fill with winner's color for (int j = 0; j < NUM_LEDS; j++) { strip.setPixelColor(j, winnerColor); } strip.show(); delay(FLASH_DELAY); // Turn off strip.clear(); strip.show(); delay(FLASH_DELAY); } delay(3000); resetGame(); } void playVictoryTune(int baseFreq) { tone(BUZZER_PIN, baseFreq, 200); delay(200); tone(BUZZER_PIN, baseFreq * 1.25, 200); delay(200); tone(BUZZER_PIN, baseFreq * 1.5, 400); delay(400); } void resetGame() { flagPosition = CENTER_POS; gameActive = false; player1PowerActive = false; player2PowerActive = false; player1PowerMovesLeft = 0; player2PowerMovesLeft = 0; player1PowerAvailable = true; player2PowerAvailable = true; updateLEDs(); }

Tug of War Arduino Game on WS2812 Led strip

Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW
ESP32-S3 4.3inch Capacitive Touch Display Development Board, 800×480, 5-point Touch, 32-bit LX7 Dual-core Processor
BUY NOW
Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW- Comments(0)
- Likes(0)

- 0 USER VOTES
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
More by Mirko Pavleski
-
DIY ESP32 Bioresonance Rife Machine with ZAPPER function Rife machine therapy is an alternative treatment developed by Dr. Royal Raymond Rife in the 1930s. H...
-
Arduino VFO Project with a Large LCD Display A Variable Frequency Oscillator (VFO) is an electronic oscillator whose output frequency can be adj...
-
Exploring the Tesla Coil Driver Board, Full Review & Test Results Some time ago I presented you a video in which I analyzed a super cheap Tesla Coil driver that cost...
-
Arduino Eatrthquake alarm and protection system with D7S seismic Sensor Earthquakes are extremely common events around the world. On average, there are fifty earthquakes a...
-
Review and Comparison of Three Inexpensive Metal Detector Kits A metal detector is a device used to detect the presence of metal objects in the ground or other ma...
-
How to make simple Arduino RGB Led strip VU Meter VU meter or volume unit meter is a device intended for visual presentation of the audio signal. It ...
-
Arduino 3D Printed self Balancing Cube Self-balancing devices are electronic devices that use sensors and motors to keep themselves balanc...
-
OpenWebRX - Simplest Rasprberry Pi + RTLSDR Web SDR Radio Software-Defined Radio is a radio communication system where components that have traditionally bee...
-
Colorful Arduino Tetris Game - WS2812B LED Matrix Tutorial Tetris is a puzzle video game created in 1985 by Alexey Pajitnov. Players manipulate falling geomet...
-
Ultra cheap Ultrasonic levitation Device - functionality and testing Ultrasonic levitation is phenomenon where objects are suspended in mid-air using the power of sound ...
-
DIY -Spirit PI- ESP32 + Smartphone Sensitive Metal Detector Pulse Induction (PI) metal detector operates on a principle based on sending short pulses of electr...
-
ESP32 Analog style VU meter with GC9A01 Round Dispalys + Peak Meters A typical VU meter measures audio signals and displays them with a visual indicator. In the classic...
-
Arduino two weel self Balancing Robot Self Balancing Robot is device that can balance itself from falling to the ground. Its function is ...
-
ELECROW CrowPanel ESP32 4.2” E-paper Wi-Fi Info-Dispaly Project An e-paper display (also known as an electronic paper display or E Ink display) is a type of screen...
-
ESP32 Fluid simulation on 16x16 Led Matrix Fluid simulation is a way of replicating the movement and behavior of liquids and gases in differen...
-
Simple GU50 VTTC Tesla Coil with MOT (25+cm Spark) Vacuum Tube Tesla Coils are a common choice for homebuilders for several practical reasons. At Soli...
-
Hourglass ESP8266 Code A hourglass, also known as an sand clock, is a device used to measure the passage of time. It consi...
-
Tug of War Arduino Game on WS2812 Led strip A Tug of War is a classic team-based game where two opposing teams compete to pull a rope in opposi...
-
DIY ESP32 Bioresonance Rife Machine with ZAPPER function Rife machine therapy is an alternative treatment developed by Dr. Royal Raymond Rife in the 1930s. H...
-
Arduino VFO Project with a Large LCD Display A Variable Frequency Oscillator (VFO) is an electronic oscillator whose output frequency can be adj...
-
Exploring the Tesla Coil Driver Board, Full Review & Test Results Some time ago I presented you a video in which I analyzed a super cheap Tesla Coil driver that cost...
-
Arduino Eatrthquake alarm and protection system with D7S seismic Sensor Earthquakes are extremely common events around the world. On average, there are fifty earthquakes a...
-
Review and Comparison of Three Inexpensive Metal Detector Kits A metal detector is a device used to detect the presence of metal objects in the ground or other ma...
-
How to make simple Arduino RGB Led strip VU Meter VU meter or volume unit meter is a device intended for visual presentation of the audio signal. It ...
-
Arduino 3D Printed self Balancing Cube Self-balancing devices are electronic devices that use sensors and motors to keep themselves balanc...
-
OpenWebRX - Simplest Rasprberry Pi + RTLSDR Web SDR Radio Software-Defined Radio is a radio communication system where components that have traditionally bee...
-
Colorful Arduino Tetris Game - WS2812B LED Matrix Tutorial Tetris is a puzzle video game created in 1985 by Alexey Pajitnov. Players manipulate falling geomet...
-
Ultra cheap Ultrasonic levitation Device - functionality and testing Ultrasonic levitation is phenomenon where objects are suspended in mid-air using the power of sound ...
-
DIY -Spirit PI- ESP32 + Smartphone Sensitive Metal Detector Pulse Induction (PI) metal detector operates on a principle based on sending short pulses of electr...
-
ESP32 Analog style VU meter with GC9A01 Round Dispalys + Peak Meters A typical VU meter measures audio signals and displays them with a visual indicator. In the classic...
-
-
-
-
Modifying a Hotplate to a Reflow Solder Station
1007 1 6 -
MPL3115A2 Barometric Pressure, Altitude, and Temperature Sensor
543 0 1 -
-
Nintendo 64DD Replacement Shell
444 0 2 -
V2 Commodore AMIGA USB-C Power Sink Delivery High Efficiency Supply Triple Output 5V ±12V OLED display ATARI compatible shark 100W
1275 4 2 -
How to measure weight with Load Cell and HX711
763 0 3