Dino-Jumpingspiel über Arduino
Ein interaktives Jumpingspiel mithilfe von Arduino, einem LCD und einer Druckplatte entwickeln.
Part 1 | Der LCD
Im ersten Schritt wird das Arduino mit einem schreibbasiertem LCD Bildschirm sowie einem Button, welcher später durch die Druckplatte ersetzt wird, verbunden. Hierzu schauen wir uns zunächst einmal die Pins des LCD an.
Pin (insgesamt 16) | Funktion |
---|---|
1 | GND 2 | VDD 3 | VO 4 | RS 5 | RW 6 | E 7-14 | DB0-DB7 15 | BL1 16 | BL2 |
Stromzufuhr - Stromzufuhr + Anschluss des Potentiometers Read Send; sendet Daten und Befehle Read Write; schreibt Daten und Befehle Enable; Daten und Befehle werden abgenommen Datenpins des LCDs Backlight; Hintergrundbeleuchtung + Backlight; Hintergrundbeleuchtung - |
Entsprechend dieser Pins, wird das Arduino wie folgt mit dem LCD verbunden:
Mithilfe der Pin 1&2, VCC und GRND wird hierbei der LCD an den Strom angeschlossen. Das Hintergrundlicht, welches mithilfe von BL1 & BL2 angeschlossen wird, kann durch das bei VO angeschlossene Potentiometer gedimmt werden.
Über RS, RW und E wird der Datenfluss über die Pins 11&12 des Arduinos geregelt. Die angeschlossenen Pins auf dem Arduino (2-5), initialisieren über die Pins DB4-DB7 das LCD im Code. Die übrigen Pins auf dem Arduino können hierbei für weitere Datenabfragen genutzt werden, dementsprechend schließen wir hier im nächsten Schritt einen Button an, der zunächst als Platzhalter für die spätere Druckplatte dient.
Um das Spiel zum Laufen zu bringen, wird im nächsten Schritt der passende Code geschrieben.
Part 2 | Der Code
Natürlich stellt man sich erst einmal die Frage: Was muss der Code überhaupt können, um den gewünschten Effekt auf unserem Arduino auszulösen?
An sich brauchen wir einen Startbildschirm, einen Zustand, in welchem sich unser "Cursor" oder eben Dino bewegt und auf ihn kommenden Kakteen ausweichen kann, während ein Score hoch gezählt wird, sowie einen Ending Screen, der unser Game Over anzeigt und durch welchen wir eventuell ein neues Spiel starten können.
Um das LCD überhaupt nutzen zu können, muss dieses zunächst einmal initialisiert und die passende LCD Library eingebunden werden:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Initialisierung LCD & Backlight
Im Anschluss folgt das Einbinden erster Variablen, die später in den Funktionen genutzt werden:
int switchState=0;
int switchFirstPress=9;
bool buttonPressed=0;
int jumpButton=7 ; // Anschlusspin des Buttons auf dem Arduino
bool dinoLast=0;
int j;
int score=0;
unsigned int number=16;
unsigned long t;
unsigned long t1;
unsigned long t2;
unsigned long t3; // werden später für das Movement benötigt
int objectDelay=200; // ursprüngliche Geschwindigkeit der Kakteen
int objectDecrease=40; // Kakteen folgen schneller aufeinander
bool dinoUp=0;
Bevor diese angewendet werden, werden allerdings zunächst noch die Grafiken erstellt, um auf externe Bitmaps verzichten zu können:
//Grafiken Dino & Kakteen
byte cactus[8] = { //cactus
B00101,
B10101,
B10101,
B10101,
B10110,
B01100,
B00100,
B00100,
};
byte dino[8] = { //dino
B01110,
B10111,
B11110,
B11111,
B11000,
B11111,
B11010,
B10010,
};
byte dinoPositionTwo[8] = { //dino 2nd position
B01110,
B10111,
B11110,
B11111,
B11000,
B11111,
B11010,
B10010,
};
Nach dieser Vorbereitung, folgt die erste auszuführende Anweisung, die unseren Startbildschirm initialisiert und durch welche sich das Spiel ebenfalls starten lässt:
//Start
void text() {
lcd.print("PULL TO START");
delay(500);
lcd.clear();
lcd.print(" ");
delay(500);
lcd.clear();
}
void setup() {
lcd.begin(16, 2);
lcd.createChar(7, cactus);
lcd.createChar(6, dino);
lcd.createChar(5, dinoPositionTwo);
j=15;
t=millis();
t1=millis();
t2=millis();
t3=millis();
Serial.begin(9600);
switchFirstPress = digitalRead(jumpButton);
while(switchFirstPress == LOW) {
lcd.setCursor(2, 1);
lcd.write(6);
delay(500);
lcd.setCursor(0, 0);
lcd.print("PULL TO START");
delay(500);
lcd.print(" ");
lcd.clear();
switchFirstPress = digitalRead(jumpButton);
if (switchFirstPress == HIGH) {
break;
}
}
delay(500);
}
Im Spiel angekommen, soll der Dino sich nicht nur durch betätigen des "Buttons", beziehungsweise auslösen der Druckplatte,nach oben und unten bewegen. Zusätzlich möchten wir einen Score darstellen und die Schnelligkeit der Kakteen, beziehungsweise deren Abstand, soll sich immer weiter erhöhen/verkleinern:
// Ingame
void dinoRunMovement() {
}
void loop() {
switchState = digitalRead(jumpButton);
if((millis()-t)>=objectDelay) { // Kakteen folgen schneller aufeinander
t=millis();
lcd.clear();
lcd.setCursor(j, 1);
lcd.write(7);
j=j-1;
if(j == -1) {
j=15;
}
byte digits = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1;
lcd.setCursor(number-digits, 0);
lcd.print(score); // Zählen des Scores
}
if((millis()-t1)>=50) {
t1=millis();
if (switchState == HIGH && dinoUp == false) {
lcd.setCursor(2, 0);
lcd.write(6);
dinoUp = true;
t2=millis();
}
else if(dinoUp == true) {
lcd.setCursor(2, 0);
lcd.write(6);
}
else if(dinoUp == false) {
lcd.setCursor(2, 0);
lcd.print(" ");
lcd.setCursor(2, 1);
lcd.write(6);
}
}
if((millis()-t2)>=500 && dinoUp == true) {
t2=millis();
lcd.setCursor(2, 1);
lcd.write(6);
lcd.setCursor(2, 0);
lcd.print(" ");
dinoUp = false;
}
if(((millis()-t3)>=1000) && (j == 1)) {
t3=millis();
if (dinoUp == true) {
score=score+1;
if (score%2 == 0) {
objectDelay=objectDelay-objectDecrease;
if(objectDelay <= 200) { // Kakteen werden nicht schneller als 200
objectDecrease=0; // kein weiteres Verschnellern
}
}
}
Sobald der Dino einen der Kakteen berührt, ist das Spiel verloren. Dies wird durch folgenden Code ausgelöst:
// Game verloren
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("GAME OVER :(");
delay(1000); // Delay, bis Retrymöglichkeit erscheint
lcd.setCursor(0, 1);
lcd.print("JUMP TO RETRY");
score=0; // Zurücksetzen des Scores auf 0
j=15;
objectDelay=500; //toggles back to basic speed
switchState = digitalRead(jumpButton);
while(switchState == LOW) {
switchState = digitalRead(jumpButton);
}
delay(500);
}
}
}
Part 3 | Die Druckplatte
Für die Druckplatte konstruierten wir zunächst einen Prototypen, bestehend aus einem Deckel einer Dose, einem Schaschlik-Spieß, Aluminium und den Kabeln, welche mit dem Arduino verbunden sind.
Durch etwas Druck auf die obere Fläche berührte diese die untere Aluminiumfläche, der Kreislauf schloss sich und der kleine Dino sprang in die Luft. Da dies aber zu klein war, um darauf springen zu können, mussten wir den Mechanismus vergrößern.

Hierfür nutzten wir eine Erhöhung, auf welcher die obere Fläche aufliegt. Die untere Fläche sollte, sobald man in die Luft springt, nach oben gedrückt werden, damit der Kontakt zur oberen Fläche hergestellt wird und Strom fließen kann. Dafür bastelten wir aus Karton eine “Hexentreppe“, welche durch das Gewicht zusammengedrückt wird, sobald man sich darauf stellt, sich selbst jedoch wieder aufrichtet, wenn sie nicht belastet wird.

Der Stromkreislauf

Durch Beschweren der unteren Fläche, mit Füßen oder Händen, wird diese von der oberen Alufläche getrennt. Dadurch wird der Stromkreis nicht geschlossen und der Dino läuft gerade aus weiter.

Wenn die Platte durch nichts mehr runter gedrückt wird, drücken die Hexentreppen die Platte nach oben, gegen die andere Alufolie. Durch die entstehende Berührung der beiden Flächen wird der Stromkreis geschlossen und der Dino springt über das Hindernis.
Die Verkleidung
Um zum einen die Aluflächen für Sicherheit zu verdecken, aber auch die Druckplatte etwas schöner zu gestalten, beklebten wir die Flächen mit passenden Elementen, wie Dino-Fußabdrücke an die Stelle wo man seine Füße platzieren sollte und einen kleinen Dino auf der obigen Fläche um das ganze Konstrukt durch sein Aussehen ansprechender und verlockend zum Spielen aussehen zu lassen.

Fazit
Abschließend lässt sich sagen dass dieses Projekt vor allem gegen Ende sehr Spaß gemacht hat. Der Anfang bestand aus viel Recherchieren und Infomieren, da wir beide kaum Erfahrung mit Arduino hatten und nach einer Möglichkeit suchten, welche das Springen des Spielers auf den Dino überträgt. Beide Teile, Programmieren und das Herstellen einer funktionierender Druckplatte waren anfänglich viel Probieren und experimentieren. Schlussendlich hat sich dies doch alles gelohnt für ein funktionierendes Spiel.