Arduino Retro Gaming mit einem OLED-Display
Haben Sie sich schon immer gefragt, wie viel Arbeit Sie benötigen, um Ihre eigenen Retro-Spiele zu schreiben? Wie einfach ist es, dass Pong für den Arduino kodiert? Begleiten Sie mich, wenn ich Ihnen zeige, wie Sie eine von Arduino betriebene Mini-Retro-Spielekonsole bauen und wie Sie Pong von Grund auf neu codieren. Hier ist das Endergebnis:
Plan erstellen
Dies ist eine ziemlich einfache Schaltung. EIN Potentiometer (Pot) steuert das Spiel, und ein OLED-Display wird vom Arduino gesteuert. Diese wird auf einem Steckbrett hergestellt. Sie können jedoch eine permanente Schaltung erstellen und diese in einem Gehäuse installieren. Wir haben über das Wiederherstellen von Pong geschrieben, wie man das klassische Pong-Spiel mit Arduino wiederherstellt Wie man das klassische Pong-Spiel mit Arduino wiederherstellt Pong war das erste Videospiel, das den Massenmarkt erreichte. Zum ersten Mal in der Geschichte wurde das Konzept eines "Videospiels" dank des Atari 2600 in das Familienheim gebracht. Lesen Sie mehr darüber, aber heute zeige ich Ihnen, wie Sie den Code von Grund auf neu schreiben und brechen jeden Teil hinunter.
Was du brauchst
Hier ist was Sie brauchen:
- 1 x Arduino (jedes Modell)
- 1 x 10k Potentiometer
- 1 x 0,96 "I2C OLED-Display
- 1 x Brotschneidebrett
- Verschiedene männliche> männliche Anschlussdrähte
DIYmall 0,96 "Zoll I2c IIC seriell 128x64 Oled LCD LED Weißes Anzeigenmodul für Arduino 51 Msp420 Stim32 SCR DIYmall 0,96" Zoll I2c IIC Serial 128x64 Oled LCD LED weißes Anzeigenmodul für Arduino 51 Msp420 Stim32 SCR Kaufen Sie jetzt bei Amazon $ 8.99
Jeder Arduino sollte funktionieren. Schauen Sie sich unseren Einkaufsführer an. Arduino Buying Guide: Welches Board sollten Sie bekommen? Arduino Buying Guide: Welches Board sollten Sie bekommen? Es gibt so viele verschiedene Arten von Arduino-Boards, dass Sie sich verwechseln könnten. Was solltest du für dein Projekt kaufen? Lassen Sie uns mit diesem Arduino Einkaufsführer helfen! Lesen Sie mehr, wenn Sie nicht sicher sind, welches Modell Sie kaufen möchten.
Diese OLED-Displays sind sehr cool. Sie können normalerweise in Weiß, Blau, Gelb oder einer Mischung der drei gekauft werden. Sie sind zwar in Vollfarbe vorhanden, fügen jedoch der Komplexität und den Kosten dieses Projekts eine ganz andere Ebene hinzu.
Die Rennbahn
Dies ist eine ziemlich einfache Schaltung. Wenn Sie nicht viel Erfahrung mit Arduino haben, sehen Sie sich diese Projekte für Anfänger an. 15 Große Arduino-Projekte für Anfänger 15 Große Arduino-Projekte für Anfänger Sie interessieren sich für Arduino, wissen aber nicht, wo Sie anfangen sollen? Hier sind einige unserer besten Arduino-Projekte für Anfänger! Lesen Sie zuerst mehr.
Hier ist es:
Verbinden Sie den linken Stift mit dem Potentiometer +5V und den richtigen Pin an Boden. Verbinden Sie den mittleren Pin mit analoger Pin 0 (A0).
Das OLED-Display ist mit dem I2C-Protokoll verbunden. Verbinden VCC und GND zum Arduino +5V und Boden. Verbinden SCL zu analog fünf (A5). Verbinden SDA zu analog 4 (A4). Der Grund, warum dies mit den analogen Pins verbunden ist, ist einfach; Diese Pins enthalten die für das I2C-Protokoll erforderliche Schaltung. Stellen Sie sicher, dass diese korrekt verbunden sind und nicht gekreuzt werden. Die genauen Pins sind je nach Modell unterschiedlich, aber beim Nano und beim Uno werden A4 und A5 verwendet. Wenn Sie kein Arduino oder Nano verwenden, lesen Sie die Dokumentation der Wire-Bibliothek für Ihr Modell.
Pot Test
Laden Sie diesen Testcode hoch (stellen Sie sicher, dass Sie die richtige Karte und den richtigen Port aus dem auswählen Werkzeuge > Tafel und Werkzeuge > Hafen Menüs):
void setup () // füge deinen Setup-Code hier ein, um ihn einmal auszuführen: Serial.begin (9600); // setup serial void loop () // füge deinen Hauptcode hier ein, um ihn wiederholt auszuführen: Serial.println (analogRead (A0)); // drucke den Wert aus der Pot-Verzögerung (500);
Öffnen Sie nun den seriellen Monitor (Oben rechts > Serienmonitor) und dreh den Topf. Der Wert sollte auf dem seriellen Monitor angezeigt werden. Ganz gegen den Uhrzeigersinn sollte es sein Null, und ganz im uhrzeigersinn sollte sein 1023:
Sie werden dies später anpassen, aber für den Moment ist es in Ordnung. Wenn nichts passiert oder sich der Wert ändert, ohne dass Sie etwas tun, trennen Sie die Verbindung und überprüfen Sie den Stromkreis.
OLED-Test
Das OLED-Display ist etwas komplexer zu konfigurieren. Sie müssen zuerst zwei Bibliotheken installieren, um die Anzeige zu steuern. Laden Sie die Bibliotheken Adafruit_SSD1306 und Adafruit-GFX von Github herunter. Kopieren Sie die Dateien in Ihren Bibliotheksordner. Dies ist abhängig von Ihrem Betriebssystem:
- Mac OS: / Benutzer / Benutzername / Dokumente / Arduino / Bibliotheken
- Linux: / home / Benutzername / Skizzenbuch
- Windows: / Benutzer / Arduino / Bibliotheken
Laden Sie jetzt eine Testskizze hoch. Gehe zu Datei > Beispiele > Adafruit SSD1306 > ssd1306_128x64_i2c. Dies sollte Ihnen eine große Skizze mit vielen Grafiken geben:
Wenn nach dem Hochladen nichts passiert, trennen Sie die Verbindung und überprüfen Sie sie erneut. Wenn sich die Beispiele nicht in den Menüs befinden, müssen Sie möglicherweise die Arduino IDE neu starten.
Der Code
Jetzt ist es Zeit für den Code. Ich werde jeden Schritt erklären, also fahren Sie mit dem Ende fort, wenn Sie es nur ausführen möchten. Dies ist eine ziemlich große Menge an Code. Wenn Sie sich also nicht sicher fühlen, sollten Sie diese 10 kostenlosen Ressourcen ausprobieren. Lernen Sie, Code zu lernen: 10 kostenlose und fantastische Online-Ressourcen, um Ihre Fähigkeiten zu verbessern Lernen Sie, Code zu lernen: 10 kostenlose und fantastische Online-Ressourcen, die Sie verbessern Fähigkeiten Codierung. Ein Thema, das von vielen gemieden wird. Es gibt eine Fülle von kostenlosen Ressourcen und Tools, die alle online verfügbar sind. Sicher könnten Sie einige Kurse zu diesem Thema in der Nähe besuchen. Lesen Sie mehr, um Code zu lernen.
Beginnen Sie mit der Einbindung der erforderlichen Bibliotheken:
#umfassen #umfassen #umfassen #umfassen
SPI und DRAHT sind zwei Arduino-Bibliotheken für die I2C-Kommunikation. Adafruit_GFX und Adafruit_SSD1306 sind die Bibliotheken, die Sie zuvor installiert haben.
Als nächstes konfigurieren Sie die Anzeige:
Adafruit_SSD1306-Anzeige (4);
Stellen Sie dann alle Variablen ein, die zum Ausführen des Spiels erforderlich sind:
int Auflösung [2] = 128, 64, Kugel [2] = 20, (Auflösung [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, GESCHWINDIGKEIT = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = 'R', ballDirectionVerti = 'S'; boolean inProgress = true;
Diese speichern alle zum Ausführen des Spiels erforderlichen Daten. Einige von ihnen speichern die Position des Balls, die Größe des Bildschirms, die Position des Spielers und so weiter. Beachten Sie, wie einige davon sind const Das heißt, sie sind konstant und werden sich niemals ändern. Dadurch kann der Arduino-Compiler die Sache etwas beschleunigen.
Die Bildschirmauflösung und der Ballstandort werden in gespeichert Arrays. Arrays sind Sammlungen ähnlicher Dinge, und für den Ball speichern Sie die Koordinaten (X und Y). Der Zugriff auf Elemente in Arrays ist einfach (fügen Sie diesen Code nicht in Ihre Datei ein):
Auflösung [1];
Wenn Arrays bei Null beginnen, wird das zweite Element im Auflösungsarray zurückgegeben (64). Das Aktualisieren von Elementen ist noch einfacher (auch diesen Code nicht enthalten):
Kugel [1] = 15;
Innerhalb void setup (), Anzeige konfigurieren:
void setup () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display ();
In der ersten Zeile wird der Adafruit-Bibliothek mitgeteilt, welche Abmessungen und welches Kommunikationsprotokoll Ihre Anzeige verwendet (in diesem Fall), 128 x 64 und I2C). Die zweite Zeile (display.display ()) weist den Bildschirm an, anzuzeigen, was im Puffer gespeichert ist (was nichts ist).
Erstellen Sie zwei aufgerufene Methoden drawBall und eraseBall:
void drawBall (int x, int y) display.drawCircle (x, y, BALL_SIZE, WHITE); void eraseBall (int x, int y) display.drawCircle (x, y, BALL_SIZE, BLACK);
Diese nehmen die x und y Koordinaten des Balls und zeichnen Sie ihn mit dem Symbol auf dem Bildschirm drawCircle Methode aus den Anzeigebibliotheken. Dies verwendet die Konstante BALL_SIZE früher definiert. Versuchen Sie dies zu ändern und sehen Sie, was passiert. Diese drawCircle-Methode akzeptiert eine Pixelfarbe - SCHWARZ oder WEISS. Da dies eine monochromatische Anzeige (eine Farbe) ist, entspricht Weiß einem Pixel, das eingeschaltet ist, und Schwarz schaltet das Pixel aus.
Erstellen Sie nun eine Methode namens moveAi:
void moveAi () eraseAiPaddle (aiPos); if (ball [1]> aiPos) ++ aiPos; else if (Ball [1] < aiPos) --aiPos; drawAiPaddle(aiPos);
Diese Methode behandelt das Verschieben von Künstliche Intelligenz oder AI Spieler. Dies ist ein ziemlich einfacher Computergegner. Wenn sich der Ball über dem Paddel befindet, bewegen Sie sich nach oben. Es ist unter dem Paddel, bewegen Sie sich nach unten. Ganz einfach, aber es funktioniert gut. Die Inkrement- und Dekrement-Symbole werden verwendet (++aiPos und -aiPos), um eins von der aiPosition hinzuzufügen oder zu entfernen. Sie könnten eine größere Zahl addieren oder subtrahieren, um die KI schneller zu machen, und daher schwieriger zu schlagen sein. So würden Sie das machen:
aiPos + = 2;
Und:
aiPos - = 2;
Das Plus gleich und Minus Equals Zeichen sind eine Abkürzung für das Addieren oder Entfernen von zwei Werten vom / zum aktuellen Wert von aiPos. Hier ist eine andere Möglichkeit, dies zu tun:
aiPos = aiPos + 2;
und
aiPos = aiPos - 1;
Beachten Sie, wie diese Methode das Paddel zuerst löscht und dann erneut zeichnet. Das muss so gemacht werden. Wenn die neue Position des Paddels gezeichnet wird, befinden sich zwei überlappende Paddles auf dem Bildschirm.
Das drawNet Methode verwendet zwei Schleifen, um das Netz zu zeichnen:
void drawNet () for (int i = 0; i < (resolution[1] / WALL_WIDTH); ++i) drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH);
Dies verwendet die WALL_WIDTH Variablen, um die Größe festzulegen.
Erstellen Sie aufgerufene Methoden drawPixels und erasePixels. Genau wie bei den Ballmethoden besteht der einzige Unterschied zwischen diesen beiden in der Farbe der Pixel:
void drawPixel (int posX, int posY, int dimensions) für (int x = 0; x < dimensions; ++x) for (int y = 0; y < dimensions; ++y) display.drawPixel((posX + x), (posY + y), WHITE); void erasePixel(int posX, int posY, int dimensions) for (int x = 0; x < dimensions; ++x) for (int y = 0; y < dimensions; ++y) display.drawPixel((posX + x), (posY + y), BLACK);
Beide Methoden verwenden wiederum zwei zum Schleifen, um eine Gruppe von Pixeln zu zeichnen. Anstatt jedes Pixel mit Hilfe der Bibliotheken zeichnen zu müssen drawPixel Bei dieser Methode zeichnen die Schleifen eine Gruppe von Pixeln basierend auf den angegebenen Abmessungen.
Das drawScore Die Methode verwendet die Textfunktionen der Bibliothek, um den Player und die AI-Bewertung auf den Bildschirm zu schreiben. Diese sind in gespeichert playerScore und aiScore:
void drawScore () display.setTextSize (2); display.setTextColor (WHITE); display.setCursor (45, 0); display.println (playerScore); display.setCursor (75, 0); display.println (aiScore);
Diese Methode hat auch eine eraseScore Gegenstück, das die Pixel auf Schwarz oder Aus setzt.
Die letzten vier Methoden sind sehr ähnlich. Sie zeichnen und löschen den Player und die AI-Paddles:
void erasePlayerPaddle (int row) erasePixel (0, Zeile - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel (0, Zeile - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, Zeile, PADDLE_WIDTH); erasePixel (0, Zeile + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, Zeile + (PADDLE_WIDTH + 2), PADDLE_WIDTH);
Beachten Sie, wie sie das nennen erasePixel Methode früher erstellen. Diese Methoden zeichnen und löschen das entsprechende Paddel.
Es gibt etwas mehr Logik in der Hauptschleife. Hier ist der ganze Code:
#umfassen #umfassen #umfassen #umfassen Adafruit_SSD1306-Anzeige (4); int Auflösung [2] = 128, 64, Kugel [2] = 20, (Auflösung [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, GESCHWINDIGKEIT = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = 'R', ballDirectionVerti = 'S'; boolean inProgress = true; void setup () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display (); void loop () if (aiScore> 9 || playerScore> 9) // Spielstatus überprüfen inProgress = false; if (inProgress) eraseScore (); EraseBall (Kugel [0], Kugel [1]); if (ballDirectionVerti == 'U') // Ball diagonal nach oben bewegen Ball [1] = Ball [1] - GESCHWINDIGKEIT; if (ballDirectionVerti == 'D') // Ball diagonal nach unten bewegen Ball [1] = Ball [1] + SPEED; wenn (Ball [1] <= 0) // bounce the ball off the top ballDirectionVerti = 'D'; if (ball[1] >= Auflösung [1]) // den Ball vom unteren Ball abprallen lassenDirectionVerti = 'U'; if (ballDirectionHori == 'R') ball [0] = ball [0] + GESCHWINDIGKEIT; // bewege Ball wenn (Ball [0]> = (Auflösung [0] - 6)) // Ball ist am AI-Rand des Bildschirms, wenn ((aiPos + 12)> = Ball [1] && (aiPos - 12) <= ball[1]) // ball hits AI paddle if (ball[1] > (aiPos + 4)) // Ball nach unten ablenken BallDirectionVerti = 'D'; else if (Ball [1] < (aiPos - 4)) // deflect ball up ballDirectionVerti = 'U'; else // deflect ball straight ballDirectionVerti = 'S'; // change ball direction ballDirectionHori = 'L'; else // GOAL! ball[0] = 6; // move ball to other side of screen ballDirectionVerti = 'S'; // reset ball to straight travel ball[1] = resolution[1] / 2; // move ball to middle of screen ++playerScore; // increase player score if (ballDirectionHori == 'L') ball[0] = ball[0] - SPEED; // move ball if (ball[0] <= 6) // ball is at the player edge of the screen if ((playerPos + 12) >= Ball [1] && (playerPos - 12) <= ball[1]) // ball hits player paddle if (ball[1] > (playerPos + 4)) // Ball nach unten ablenken BallDirectionVerti = 'D'; else if (Ball [1] < (playerPos - 4)) // deflect ball up ballDirectionVerti = 'U'; else // deflect ball straight ballDirectionVerti = 'S'; // change ball direction ballDirectionHori = 'R'; else ball[0] = resolution[0] - 6; // move ball to other side of screen ballDirectionVerti = 'S'; // reset ball to straight travel ball[1] = resolution[1] / 2; // move ball to middle of screen ++aiScore; // increase AI score drawBall(ball[0], ball[1]); erasePlayerPaddle(playerPos); playerPos = analogRead(A2); // read player potentiometer playerPos = map(playerPos, 0, 1023, 8, 54); // convert value from 0 - 1023 to 8 - 54 drawPlayerPaddle(playerPos); moveAi(); drawNet(); drawScore(); else // somebody has won display.clearDisplay(); display.setTextSize(4); display.setTextColor(WHITE); display.setCursor(0, 0); // figure out who if (aiScore > playerScore) display.println ("SIE VERLIEREN!"); else if (playerScore> aiScore) display.println ("SIE GEWINNEN!"); display.display (); void moveAi () // das AI-Paddel bewegen eraseAiPaddle (aiPos); if (ball [1]> aiPos) ++ aiPos; else if (Ball [1] < aiPos) --aiPos; drawAiPaddle(aiPos); void drawScore() // draw AI and player scores display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(45, 0); display.println(playerScore); display.setCursor(75, 0); display.println(aiScore); void eraseScore() // erase AI and player scores display.setTextSize(2); display.setTextColor(BLACK); display.setCursor(45, 0); display.println(playerScore); display.setCursor(75, 0); display.println(aiScore); void drawNet() for (int i = 0; i < (resolution[1] / WALL_WIDTH); ++i) drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH); void drawPixel(int posX, int posY, int dimensions) // draw group of pixels for (int x = 0; x < dimensions; ++x) for (int y = 0; y < dimensions; ++y) display.drawPixel((posX + x), (posY + y), WHITE); void erasePixel(int posX, int posY, int dimensions) // erase group of pixels for (int x = 0; x < dimensions; ++x) for (int y = 0; y < dimensions; ++y) display.drawPixel((posX + x), (posY + y), BLACK); void erasePlayerPaddle(int row) erasePixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(0, row, PADDLE_WIDTH); erasePixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH); void drawPlayerPaddle(int row) drawPixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); drawPixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(0, row, PADDLE_WIDTH); drawPixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH); void drawAiPaddle(int row) int column = resolution[0] - PADDLE_WIDTH; drawPixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); drawPixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(column, row, PADDLE_WIDTH); drawPixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH); void eraseAiPaddle(int row) int column = resolution[0] - PADDLE_WIDTH; erasePixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(column, row, PADDLE_WIDTH); erasePixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH); void drawBall(int x, int y) display.drawCircle(x, y, BALL_SIZE, WHITE); void eraseBall(int x, int y) display.drawCircle(x, y, BALL_SIZE, BLACK);
Hier ist, was Sie am Ende mit:
Sobald Sie mit dem Code vertraut sind, können Sie zahlreiche Änderungen vornehmen:
- Ein Menü für Schwierigkeitsgrade hinzufügen (AI und Ballgeschwindigkeit ändern).
- Fügen Sie dem Ball oder der KI eine zufällige Bewegung hinzu.
- Fügen Sie einen weiteren Pot für zwei Spieler hinzu.
- Fügen Sie eine Pause-Schaltfläche hinzu.
Werfen Sie einen Blick auf diese Retro-Gaming-Projekte von Pi Zero. 5 Retro-Gaming-Projekte mit dem Raspberry Pi Zero. 5 Retro-Gaming-Projekte mit dem Raspberry Pi Zero und inspirierende Neuankömmlinge, vor allem in den fiebrigen Köpfen der Retro-Gaming-Fans. Weiterlesen .
Haben Sie Pong mit diesem Code codiert? Welche Modifikationen haben Sie vorgenommen? Lassen Sie mich in den Kommentaren wissen, ich würde gerne ein paar Bilder machen!
Erfahren Sie mehr über: Arduino, Elektronik, Retro Gaming.