Inhaltsverzeichnis:
- Schritt 1: Schließen Sie den Joystick und die IR-LED an
- Schritt 2: Erstellen Sie eine neue Skizze
- Schritt 3: Erstellen Sie das C#-Projekt
Video: Arduino-gesteuertes Platformer-Spiel mit Joystick und IR-Empfänger - Gunook
2024 Autor: John Day | [email protected]. Zuletzt bearbeitet: 2024-01-30 07:21
Heute verwenden wir einen Arduino-Mikrocontroller, um ein einfaches C#-basiertes Plattformspiel zu steuern. Ich verwende den Arduino, um Eingaben von einem Joystick-Modul zu empfangen und diese Eingabe an die C#-Anwendung zu senden, die die Eingabe über eine serielle Verbindung abhört und decodiert. Obwohl Sie keine Vorkenntnisse in der Entwicklung von Videospielen benötigen, um das Projekt abzuschließen, kann es einige Zeit dauern, einige der Dinge zu verarbeiten, die in der "Spielschleife" vor sich gehen, die wir später besprechen werden.
Um dieses Projekt abzuschließen, benötigen Sie:
- Visual Studio-Community
- Ein Arduino Uno (oder ähnlich)
- Ein Joystick-Controller-Modul
- Die Geduld
Wenn Sie bereit sind zu beginnen, machen Sie weiter!
Schritt 1: Schließen Sie den Joystick und die IR-LED an
Hier ist der Anschluss recht einfach. Ich habe Diagramme beigefügt, die nur den angeschlossenen Joystick sowie das von mir verwendete Setup zeigen, das den Joystick und eine Infrarot-LED zur Steuerung des Spiels mit einer Fernbedienung enthält, die mit vielen Arduino-Kits geliefert wird. Dies ist optional, aber es schien eine coole Idee zu sein, kabellos zu spielen.
Die im Setup verwendeten Pins sind:
- A0 (analog) <- Horizontale oder X-Achse
- A1 (analog) <- Vertikale oder Y-Achse
- Pin 2 <- Joystick-Schaltereingang
- Pin 2 <- Infrarot-LED-Eingang
- VCC <- 5V
- Boden
- Masse #2
Schritt 2: Erstellen Sie eine neue Skizze
Wir beginnen mit der Erstellung unserer Arduino-Skizzendatei. Dies fragt den Joystick nach Änderungen ab und sendet diese Änderungen alle paar Millisekunden an das C#-Programm. In einem echten Videospiel würden wir den seriellen Port in einer Spielschleife auf Eingaben überprüfen, aber ich habe das Spiel als Experiment begonnen, also basiert die Framerate tatsächlich auf der Anzahl der Ereignisse auf dem seriellen Port. Ich hatte das Projekt eigentlich im Arduino-Schwesterprojekt Processing begonnen, aber es stellte sich heraus, dass es viel, viel langsamer war und die Anzahl der Boxen auf dem Bildschirm nicht bewältigen konnte.
Erstellen Sie also zuerst eine neue Skizze im Arduino-Code-Editor-Programm. Ich zeige meinen Code und erkläre dann, was er tut:
#include "IRremote.h"
// IR-Variablen int Receiver = 3; // Signal-Pin des IR-Empfängers IRrecv irrecv (Empfänger); // Instanz von 'irrecv' erstellen decode_results Ergebnisse; // Instanz von 'decode_results' erstellen // Joystick-/Spielvariablen int xPos = 507; int yPos = 507; Byte joyXPin = A0; Byte joyYPin = A1; Byte joySwitch = 2; flüchtiger Byte-Klickzähler = -1; int minMoveHigh = 530; int minMoveLow = 490; int aktuelle Geschwindigkeit = 550; // Standard = eine Durchschnittsgeschwindigkeit int speedIncrement = 25; // Betrag zum Erhöhen / Verringern der Geschwindigkeit mit Y-Eingang unsigned long current = 0; // Hält den aktuellen Zeitstempel int wait = 40; // ms, um zwischen Nachrichten zu warten [Hinweis: niedrigere Wartezeit = schnellere Framerate] volatile bool buttonPressed = false; // Messen, wenn die Taste gedrückt wird void setup () { Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt(0, Sprung, FALLING); Strom = Millis(); // Aktuelle Uhrzeit einstellen // Infrarot-Empfänger einrichten: irrecv.enableIRIn(); // Starten Sie den Empfänger} // setup void loop () { Int xMovement = analogRead (joyXPin); int yPos = analogRead(joyYPin); // Behandeln Sie die Joystick X-Bewegung unabhängig vom Timing: if (xMovement > minMoveHigh || xMovement current + wait) { currentSpeed = yPos > minMoveLow && yPos < minMoveHigh // Wenn nur ein wenig bewegt… ? currentSpeed // …nur die aktuelle Geschwindigkeit zurückgeben: getSpeed(yPos); // yPos nur ändern, wenn sich der Joystick deutlich bewegt //int distance =; Serial.print ((String) xPos + ", " + (String) yPos + ', ' + (String) currentSpeed + '\n'); Strom = Millis(); aufrechtzuerhalten unter 0 gehen return currentSpeed - speedIncrement < 0 ? 0: currentSpeed - speedIncrement; } } // getSpeed void jump() { buttonPressed = true; // Zeigt an, dass die Taste gedrückt wurde. } // jump // Wenn eine Taste auf dem. gedrückt wird remote, handhabe die richtige Antwort void translateIR (decode_results results) // ergreift Maßnahmen basierend auf dem empfangenen IR-Code { switch (results.value) { case 0xFF18E7: // Serial.println ("2"); currentSpeed += speedIncrement * 2; break; case 0xFF10EF: //Serial.println("4"); xPos = -900; break; case 0xFF38C7: //Serial.println("5"); jump(); break; case 0xFF5AA5: //Serial. println("6"); xPos = 900; break; case 0xFF4AB5: //Serial.println("8"); currentSpeed -= speedIncrement * 2; break; default: //Serial.println(" other button"); break; } // Endschalter } //END translateIR
Ich habe versucht, den Code weitgehend selbsterklärend zu erstellen, aber es gibt ein paar Dinge, die es wert sind, erwähnt zu werden. Eine Sache, die ich zu erklären versuchte, war in den folgenden Zeilen:
int minYMoveUp = 520;
int minYMoveDown = 500;
Wenn das Programm läuft, neigt der analoge Eingang vom Joystick dazu, herumzuspringen und bleibt normalerweise bei etwa 507. Um dies zu korrigieren, ändert sich der Eingang nicht, es sei denn, er ist größer als minYMoveUp oder kleiner als minYMoveDown.
pinMode (joySwitch, INPUT_PULLUP);
attachInterrupt(0, Sprung, FALLING);
Die Methode attachInterrupt() ermöglicht es uns, die normale Schleife jederzeit zu unterbrechen, um Eingaben wie das Drücken der Taste beim Klicken auf den Joystick entgegenzunehmen. Hier haben wir den Interrupt in der Zeile davor mit der Methode pinMode() angehängt. Ein wichtiger Hinweis hier ist, dass Sie zum Anschließen eines Interrupts am Arduino Uno entweder Pin 2 oder 3 verwenden müssen. Andere Modelle verwenden andere Interrupt-Pins, daher müssen Sie möglicherweise auf der Arduino-Website überprüfen, welche Pins Ihr Modell verwendet. Der zweite Parameter ist für die Callback-Methode, hier ISR oder "Interrupt Service Routine" genannt. Es sollte keine Parameter annehmen oder irgendetwas zurückgeben.
Seriendruck(…)
Dies ist die Zeile, die unsere Daten an das C#-Spiel sendet. Hier senden wir den X-Achsen-Messwert, den Y-Achsen-Messwert und eine Geschwindigkeitsvariable an das Spiel. Diese Messwerte können um andere Eingaben und Messwerte erweitert werden, um das Spiel interessanter zu machen, aber hier werden wir nur einige verwenden.
Wenn Sie bereit sind, Ihren Code zu testen, laden Sie ihn auf den Arduino hoch und drücken Sie [Shift] + [Strg] + [M], um den seriellen Monitor zu öffnen und zu sehen, ob Sie eine Ausgabe erhalten. Wenn Sie Daten vom Arduino erhalten, können wir zum C#-Teil des Codes übergehen…
Schritt 3: Erstellen Sie das C#-Projekt
Um unsere Grafiken anzuzeigen, habe ich zunächst ein Projekt in Processing gestartet, aber später entschieden, dass es zu langsam wäre, alle Objekte anzuzeigen, die wir anzeigen müssen. Also entschied ich mich für C#, was sich bei der Verarbeitung unserer Eingaben als viel reibungsloser und reaktionsschneller herausstellte.
Für den C#-Teil des Projekts ist es am besten, einfach die ZIP-Datei herunterzuladen, in einen eigenen Ordner zu extrahieren und dann zu ändern. Es gibt zwei Ordner in der Zip-Datei. Um das Projekt in Visual Studio zu öffnen, geben Sie den RunnerGame_CSharp-Ordner in Windows Explorer ein. Doppelklicken Sie hier auf die.sln-Datei (Lösung), und VS lädt das Projekt.
Es gibt ein paar verschiedene Klassen, die ich für das Spiel erstellt habe. Ich werde nicht auf alle Details zu jeder Klasse eingehen, aber ich werde einen Überblick darüber geben, wofür die Hauptklassen gedacht sind.
Die Box-Klasse
Ich habe die Box-Klasse erstellt, damit Sie einfache Rechteckobjekte erstellen können, die auf dem Bildschirm in einem Windows-Formular gezeichnet werden können. Die Idee ist, eine Klasse zu erstellen, die mit anderen Klassen erweitert werden kann, die möglicherweise eine Art von Grafiken zeichnen möchten. Das Schlüsselwort "virtual" wird verwendet, damit andere Klassen sie überschreiben können (unter Verwendung des Schlüsselworts "override"). Auf diese Weise können wir bei Bedarf das gleiche Verhalten für die Player-Klasse und die Platform-Klasse erzielen und die Objekte auch nach Bedarf ändern.
Machen Sie sich nicht zu viele Gedanken über alle Eigenschaften und zeichnen Sie Calls. Ich habe diese Klasse geschrieben, damit ich sie für jedes Spiel oder Grafikprogramm erweitern kann, das ich in Zukunft machen möchte. Wenn Sie einfach im Handumdrehen ein Rechteck zeichnen müssen, müssen Sie keine große Klasse wie diese schreiben. Die C#-Dokumentation enthält gute Beispiele dafür.
Ich werde jedoch einige der Logik meiner "Box" -Klasse darlegen:
public virtual bool IsCollidedX(Box otherObject) { … }
Hier prüfen wir auf Kollisionen mit Objekten in X-Richtung, da der Spieler nur dann auf Kollisionen in Y-Richtung (oben und unten) prüfen muss, wenn er damit auf dem Bildschirm ausgerichtet ist.
public virtual bool IsCollidedY(Box otherObject) { … }
Wenn wir uns über oder unter einem anderen Spielobjekt befinden, prüfen wir auf Y-Kollisionen.
public virtual bool IsCollided(Box otherObject) { … }
Dies kombiniert X- und Y-Kollisionen und gibt zurück, ob ein Objekt mit diesem kollidiert ist.
public virtual void OnPaint(Grafikgrafik) { … }
Mit der obigen Methode übergeben wir ein beliebiges Grafikobjekt und verwenden es, während das Programm läuft. Wir erstellen alle Rechtecke, die möglicherweise gezeichnet werden müssen. Dies könnte jedoch für eine Vielzahl von Animationen verwendet werden. Für unsere Zwecke reichen Rechtecke sowohl für die Plattformen als auch für den Spieler aus.
Die Charakterklasse
Die Character-Klasse erweitert meine Box-Klasse, so dass wir eine gewisse Physik out of the box haben. Ich habe die Methode "CheckForCollisions" erstellt, um alle von uns erstellten Plattformen schnell auf Kollisionen zu überprüfen. Die Methode "Jump" setzt die Aufwärtsgeschwindigkeit des Players auf die Variable JumpSpeed, die dann Frame für Frame in der MainWindow-Klasse modifiziert wird.
Kollisionen werden hier etwas anders behandelt als in der Box-Klasse. Ich habe in diesem Spiel entschieden, dass wir beim Aufwärtsspringen durch eine Plattform springen können, aber sie wird unseren Spieler auf dem Weg nach unten erwischen, wenn sie damit kollidiert.
Die Plattformklasse
In diesem Spiel verwende ich nur den Konstruktor dieser Klasse, der eine X-Koordinate als Eingabe verwendet und alle X-Positionen der Plattformen in der MainWindow-Klasse berechnet. Jede Plattform wird an einer zufälligen Y-Koordinate von 1/2 des Bildschirms bis 3/4 der Bildschirmhöhe aufgestellt. Höhe, Breite und Farbe werden ebenfalls zufällig generiert.
Die MainWindow-Klasse
Hier legen wir die gesamte Logik ab, die während des Spiels verwendet werden soll. Zuerst geben wir im Konstruktor alle COM-Ports aus, die dem Programm zur Verfügung stehen.
foreach(String-Port in SerialPort. GetPortNames())
Console. WriteLine("VERFÜGBARE PORTS: " + port);
Wir wählen aus, auf welchem Port wir die Kommunikation akzeptieren, je nachdem, welchen Port Ihr Arduino bereits verwendet:
SerialPort = neuer SerialPort (SerialPort. GetPortNames()[2], 9600, Parity. None, 8, StopBits. One);
Achten Sie genau auf den Befehl: SerialPort. GetPortNames()[2]. [2] gibt an, welcher serielle Port verwendet werden soll. Wenn das Programm beispielsweise "COM1, COM2, COM3" ausgibt, hören wir auf COM3, da die Nummerierung im Array bei 0 beginnt.
Auch im Konstruktor erstellen wir alle Plattformen mit halbzufälligem Abstand und Platzierung in Y-Richtung auf dem Bildschirm. Alle Plattformen werden einem List-Objekt hinzugefügt, was in C# einfach eine sehr benutzerfreundliche und effiziente Möglichkeit ist, eine Array-ähnliche Datenstruktur zu verwalten. Wir erstellen dann den Player, das unser Character-Objekt ist, setzen die Punktzahl auf 0 und setzen GameOver auf false.
privat statisch void DataReceived(Objektsender, SerialDataReceivedEventArgs e)
Dies ist die Methode, die aufgerufen wird, wenn Daten am seriellen Port empfangen werden. Hier wenden wir unsere gesamte Physik an, entscheiden, ob das Spiel angezeigt wird, die Plattformen verschoben werden usw. Wenn Sie jemals ein Spiel gebaut haben, haben Sie im Allgemeinen eine sogenannte "Spielschleife", die jedes Mal aufgerufen wird, wenn der Frame erfrischt. In diesem Spiel fungiert die DataReceived-Methode als Spielschleife und manipuliert nur die Physik, wenn Daten vom Controller empfangen werden. Es hätte vielleicht besser funktioniert, einen Timer im Hauptfenster einzurichten und die Objekte basierend auf den empfangenen Daten zu aktualisieren, aber da es sich um ein Arduino-Projekt handelt, wollte ich ein Spiel erstellen, das tatsächlich basierend auf den eingehenden Daten lief.
Zusammenfassend ist dieses Setup eine gute Grundlage, um das Spiel zu etwas Brauchbarem zu erweitern. Obwohl die Physik nicht ganz perfekt ist, funktioniert es für unsere Zwecke gut genug, nämlich den Arduino für etwas zu verwenden, das jeder mag: Spiele spielen!
Empfohlen:
Heimwerken -- Einen Spinnenroboter herstellen, der mit einem Smartphone mit Arduino Uno gesteuert werden kann – wikiHow
Heimwerken || Wie man einen Spider-Roboter herstellt, der mit einem Smartphone mit Arduino Uno gesteuert werden kann: Während man einen Spider-Roboter baut, kann man so viele Dinge über Robotik lernen. Wie die Herstellung von Robotern ist sowohl unterhaltsam als auch herausfordernd. In diesem Video zeigen wir Ihnen, wie Sie einen Spider-Roboter bauen, den wir mit unserem Smartphone (Androi
Platformer on Scratch erstellen – wikiHow
So erstellen Sie einen Platformer auf Scratch: Scratch ist eine Website, auf der Leute Spiele und andere Programme mit vorgefertigten Blöcken erstellen, die Sie per Drag & Drop in einen Arbeitsbereich ziehen. Heute zeige ich dir, wie du ein Jump'n'Run-Spiel von Grund auf neu erstellen kannst
Schnittstellentastatur mit Arduino. [Einzigartige Methode]: 7 Schritte (mit Bildern)
Schnittstellentastatur mit Arduino. [Einzigartige Methode]: Hallo, und willkommen zu meinem ersten instructable! :) In diesem instructables möchte ich eine fantastische Bibliothek für die Schnittstelle der Tastatur mit Arduino teilen - 'Password Library' einschließlich 'Keypad Library'. Diese Bibliothek enthält die besten Funktionen, die wir wi
SCARA-Roboter: Lernen über Vorwärts- und inverse Kinematik !!! (Plot Twist Erfahren Sie, wie Sie mit PROCESSING eine Echtzeitschnittstelle in ARDUINO erstellen !!!!): 5 Schritte (mit Bildern)
SCARA-Roboter: Lernen über Vorwärts- und inverse Kinematik !!! (Plot Twist Learn How to Make a Real Time Interface in ARDUINO Using PROCESSING !!!!): Ein SCARA-Roboter ist eine sehr beliebte Maschine in der Industriewelt. Der Name steht sowohl für Selective Compliant Assembly Robot Arm als auch für Selective Compliant Articulated Robot Arm. Es ist im Grunde ein Roboter mit drei Freiheitsgraden, da er die ersten beiden Displ
Einfaches BLE mit sehr geringem Stromverbrauch in Arduino Teil 3 - Nano V2-Ersatz - Rev 3: 7 Schritte (mit Bildern)
Einfaches BLE mit sehr geringem Stromverbrauch in Arduino Teil 3 - Nano V2-Ersatz - Rev 3: Update: 7. April 2019 - Rev 3 von lp_BLE_TempHumidity, fügt Datums- / Zeitdiagramme mit pfodApp V3.0.362+ hinzu und automatische Drosselung beim Senden von DatenUpdate: 24. März 2019 – Rev 2 von lp_BLE_TempHumidity, fügt weitere Plotoptionen hinzu und i2c_ClearBus, fügt GT832E