// Wir fügen eine Bibliothek hinzu, um den LED-Streifen zu steuern.
#include <Adafruit_NeoPixel.h>
// Wir legen fest, an welchem Pin der LED-Streifen angeschlossen ist.
#define LED_PIN 2
// Wir geben an, wie viele LEDs unser Streifen hat.
#define NUM_LEDS 90
// Wir erstellen ein Objekt, um den LED-Streifen zu steuern.
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Wir bestimmen die Startposition des blauen Lichts (der Ball) in der Mitte.
int bluePosition = NUM_LEDS / 2;
// Wir wählen zufällig, ob das blaue Licht nach links oder rechts geht.
int direction = 1; // 1 bedeutet nach rechts, -1 bedeutet nach links.
// Pins für die Taster der Spieler
#define BUTTON_PIN_PLAYER1 3
#define BUTTON_PIN_PLAYER2 4
// Variablen für die Taster und das Entprellen (damit der Arduino die Taster richtig liest)
int buttonStatePlayer1 = HIGH; // Startzustand ist HIGH wegen INPUT_PULLUP
int lastButtonStatePlayer1 = HIGH;
unsigned long lastDebounceTimePlayer1 = 0;
unsigned long debounceDelay = 50; // 50 Millisekunden Entprellzeit
int buttonStatePlayer2 = HIGH;
int lastButtonStatePlayer2 = HIGH;
unsigned long lastDebounceTimePlayer2 = 0;
// Variable für die Geschwindigkeit des blauen Lichts
int speed = 100; // Startgeschwindigkeit in Millisekunden (je kleiner, desto schneller)
// Variablen für die Punkte der Spieler
int scorePlayer1 = 0;
int scorePlayer2 = 0;
void setup() {
// Wir starten den LED-Streifen.
strip.begin();
// Wir stellen sicher, dass alle LEDs ausgeschaltet sind.
strip.show();
// Wir starten den Zufallsgenerator.
randomSeed(analogRead(0));
// Wir wählen zufällig die Start-Richtung des blauen Lichts.
if (random(0, 2) == 0) {
direction = -1; // Nach links
} else {
direction = 1; // Nach rechts
}
// Wir legen die Taster-Pins als Eingänge mit Pullup-Widerständen fest.
pinMode(BUTTON_PIN_PLAYER1, INPUT_PULLUP);
pinMode(BUTTON_PIN_PLAYER2, INPUT_PULLUP);
}
void loop() {
// *** Taster von Spieler 1 lesen und entprellen ***
int readingPlayer1 = digitalRead(BUTTON_PIN_PLAYER1);
if (readingPlayer1 != lastButtonStatePlayer1) {
// Wenn sich der Tasterzustand geändert hat, merken wir uns die Zeit.
lastDebounceTimePlayer1 = millis();
}
if ((millis() - lastDebounceTimePlayer1) > debounceDelay) {
// Wenn genügend Zeit vergangen ist, prüfen wir, ob sich der Zustand geändert hat.
if (readingPlayer1 != buttonStatePlayer1) {
buttonStatePlayer1 = readingPlayer1;
// Wenn der Taster gedrückt wurde (LOW wegen INPUT_PULLUP)
if (buttonStatePlayer1 == LOW) {
// Prüfen, ob das blaue Licht im Bereich von Spieler 1 ist und in seine Richtung kommt
if (bluePosition >= 0 && bluePosition < 10 && direction == -1) {
// Richtung umkehren
direction = 1;
// Geschwindigkeit erhöhen (wir machen die Wartezeit kleiner)
speed = max(20, speed - 10); // Wir sorgen dafür, dass die Geschwindigkeit nicht zu hoch wird
} else {
// Spieler 1 hat falsch gedrückt und verliert die Runde
scorePlayer2++;
resetGame();
}
}
}
}
lastButtonStatePlayer1 = readingPlayer1;
// *** Taster von Spieler 2 lesen und entprellen ***
int readingPlayer2 = digitalRead(BUTTON_PIN_PLAYER2);
if (readingPlayer2 != lastButtonStatePlayer2) {
// Wenn sich der Tasterzustand geändert hat, merken wir uns die Zeit.
lastDebounceTimePlayer2 = millis();
}
if ((millis() - lastDebounceTimePlayer2) > debounceDelay) {
// Wenn genügend Zeit vergangen ist, prüfen wir, ob sich der Zustand geändert hat.
if (readingPlayer2 != buttonStatePlayer2) {
buttonStatePlayer2 = readingPlayer2;
// Wenn der Taster gedrückt wurde
if (buttonStatePlayer2 == LOW) {
// Prüfen, ob das blaue Licht im Bereich von Spieler 2 ist und in seine Richtung kommt
if (bluePosition >= NUM_LEDS - 10 && bluePosition < NUM_LEDS && direction == 1) {
// Richtung umkehren
direction = -1;
// Geschwindigkeit erhöhen
speed = max(20, speed - 10);
} else {
// Spieler 2 hat falsch gedrückt und verliert die Runde
scorePlayer1++;
resetGame();
}
}
}
}
lastButtonStatePlayer2 = readingPlayer2;
// *** Alle LEDs löschen ***
strip.clear();
// *** Spielerzonen wieder einfärben ***
for (int i = 0; i < 10; i++) {
strip.setPixelColor(i, strip.Color(0, 255, 0)); // Grün für Spieler 1
}
for (int i = NUM_LEDS - 10; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // Rot für Spieler 2
}
// *** Blaues Licht an der aktuellen Position setzen ***
strip.setPixelColor(bluePosition, strip.Color(0, 0, 255)); // Blau für den Ball
// *** Farben anzeigen ***
strip.show();
// *** Kurze Pause je nach Geschwindigkeit ***
delay(speed);
// *** Position des blauen Lichts ändern ***
bluePosition += direction;
// *** Prüfen, ob ein Spieler einen Punkt bekommt, weil der Gegner nicht reagiert hat ***
if (bluePosition < 0) {
// Spieler 2 bekommt einen Punkt
scorePlayer2++;
resetGame();
} else if (bluePosition >= NUM_LEDS) {
// Spieler 1 bekommt einen Punkt
scorePlayer1++;
resetGame();
}
// *** Prüfen, ob jemand 10 Punkte hat und gewonnen hat ***
if (scorePlayer1 >= 10) {
winnerEffect(1);
} else if (scorePlayer2 >= 10) {
winnerEffect(2);
}
// *** Sicherstellen, dass das blaue Licht innerhalb des Streifens bleibt ***
if (bluePosition < 0) {
bluePosition = 0;
} else if (bluePosition >= NUM_LEDS) {
bluePosition = NUM_LEDS - 1;
}
}
// *** Funktion zum Zurücksetzen des Spiels nach einer Runde ***
void resetGame() {
// Spielvariablen zurücksetzen
bluePosition = NUM_LEDS / 2;
speed = 100;
// Zufällige Richtung wählen
if (random(0, 2) == 0) {
direction = -1; // Nach links
} else {
direction = 1; // Nach rechts
}
// Kurze Pause, bevor es weitergeht
delay(1000);
}
// *** Funktion für den Gewinn-Effekt ***
void winnerEffect(int player) {
// Toller Effekt für den Gewinner
for (int i = 0; i < 5; i++) {
if (player == 1) {
// Spieler 1 hat gewonnen, alle LEDs grün machen
strip.fill(strip.Color(0, 255, 0));
} else {
// Spieler 2 hat gewonnen, alle LEDs rot machen
strip.fill(strip.Color(255, 0, 0));
}
strip.show();
delay(500);
// Alle LEDs ausschalten
strip.clear();
strip.show();
delay(500);
}
// Punkte zurücksetzen
scorePlayer1 = 0;
scorePlayer2 = 0;
resetGame();
}