Inhaltsverzeichnis:

Arduino OLED Snake-Spiel - Gunook
Arduino OLED Snake-Spiel - Gunook

Video: Arduino OLED Snake-Spiel - Gunook

Video: Arduino OLED Snake-Spiel - Gunook
Video: Arduino Snake Game using an OLED display 2024, November
Anonim
Arduino OLED-Schlangenspiel
Arduino OLED-Schlangenspiel

Hallo und willkommen, zu unseren Anleitungen zur Herstellung und zum Arduino-OLED-Spiel, dieses Projekt entstand, als wir versuchten, unser erstes Spiel mit einem Arduino zu machen, soooo, wir dachten, wo wir besser anfangen könnten als der Nokia-Klassiker Snake (gut zumindest ein Schlangenklon:)).

Was wirst du brauchen

Lieferungen

Arduino UNO oder Klon

OLED-Display

4 Dioden

500-1k Widerstand

4 Controller-Tasten

Passiver Piezo-Summer

Optional

Lötfreies Brotbrett

Bitte beachten Sie, dass diese Links nur als Beispiel dienen

Schritt 1: Die Schaltung

Die Rennbahn
Die Rennbahn

Im obigen Bild können Sie unsere Schaltung sehen. Wir verwenden Pin d3 auf dem Arduino als Interrupt-Anforderungs-Pin, damit das Arduino dem Lesen der Controller-Eingänge, die d4 d5 d6 d7 sind, Priorität einräumt. Die Grundlage der Schaltung besteht darin, dass eine Richtungstaste gedrückt wird, die auf 5 V hoch geht. Dies aktiviert den Interrupt-Anforderungs-Pin (d3 lila Draht) und einen entsprechenden Richtungs-Pin, die Interrupt-Funktion ruft eine Update-Richtungsfunktion auf und dieser Code bewegt die Schlange entsprechend. Pin 9 wird als Sound-Pin verwendet, da es sich um eine PWM (~ Pulsweitenmodulation) handelt, die direkt mit einem 5 V-Piezo am + Pin verbunden ist und der - auf 0 V / Masse zurückgeht.

(FYI auf dem arduino uno und den Klonen können nur d2 und d3 als Interrupt-Request-Pins fungieren).

Richtungsstifte:

d4 nach oben ORANGE

d5 nach unten ROSA

d6 Links BLAU

d7 Rechts BRAUN

d9-Sound GRAU

Jede Taste hat einen 5-V-Anschlusseingang und einen Ausgang, der zuerst mit ihrem jeweiligen digitalen Eingang am Arduino verbunden ist. Dieser gleiche Ausgang jeder Taste wird dann mit einer eigenen Diode verbunden andere Schaltflächen und aktivieren Sie diese. Am Kathodenende (-) aller 4 Dioden verbinden wir sie, um eine Ausgangsverbindung zu schaffen, die mit d3 und dann über einen Widerstand mit 0 V / Erde verbunden ist, um die Arduino-Pins niedrig zu ziehen, um keine schwebenden Pins zu hinterlassen, wenn sie nicht sind aktiviert.

(FYI ein schwebender Pin kann Phantomspannung empfangen und ungewöhnliches Verhalten verursachen)

2 analoge Pins werden verwendet, um das Display anzusteuern, dies sind die Arduino-Hardware-i2c-Pins.

A5 ist mit SCL GELB verbunden

A4 ist mit SDA GRÜN verbunden

Der +5V- und 0V-(Erde-)Ausgang des Arduino wird als Stromquelle für den gesamten Stromkreis verwendet, der mit einem USB- oder Telefonladegerät betrieben werden kann.

Schritt 2: Der Code

//------------ ANJAWARE SNAKE Games Mit Hilfe der Netzvölker -------------- -------

#enthalten

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // Display-Set (Breite, Höhe) Adafruit_SSD1306 display(128, 64); // Eingangspins definieren Dies sind die Pins auf dem Arduino, die sich nie ändern DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // Definiere Richtungen #define DIRUP 1 // Diese Werte sind es, was die "Schlange" betrachtet, um zu entscheiden- #define DIRDOWN 2 // die Richtung, in die sich die Schlange bewegen wird # define DIRLEFT 3 #define DIRRIGHT 4

// Schaltflächenvariablen setzen

// flüchtig, weil wir es brauchen, um mit dem Interrupt zu aktualisieren, kann also ein beliebiger Zykluswert sein

// ist nie höher als 4, also brauche nur 8bit int, um Ressourcen zu sparen volatile uint8_t buttonpressed=0; bool butup=0; bool butdown=0; // Wir verwenden dies, um true zu setzen, um zu "erkennen", in welche Richtung gedrückt bool butleft=0; bool butright=0;

// Schlangen-Ints

Byte-SchlangePosX[30]; // Array zum Erstellen des Schlangenbytes snakePosY[30];

int SchlangeX=30; // Position des Schlangenkopfes

int SchlangeY=30; int Schlangengröße=1; // Anzahl der Schlangengröße begrenzt auf die Größe des Arrays

// Welt ints

uint8_t worldMinX=0; // diese setzen die Grenzen des Spielbereichs

uint8_t worldMaxX=128; uint8_t worldMinY=10; uint8_t worldMaxY=63;

// sammeln scran(food) und position von scran

bool scranAte = 0; uint8_t scranPosX=0; uint8_t scranPosY=0;

// bewertet Variablen

langer Spielstand=0; langer Highscore=30; // Highscore auf 3 setzen als Ausgangspunkt sammeln

//--------------------------- Dies führt der Interrupt bei Spannungsanstieg aus ------------ -------------

Void Interruptpressed () { Verzögerung (150); // leichte Verzögerung für den zusätzlichen "Bounce"-Schutz updatedirection(); } // ------------------ den Richtungswert vom Tastendruck aktualisieren ------------------ void updatedirection () { // Serial.println ("Aktualisierungsrichtung"); butup = digitalRead (UPPIN); // Überprüfen Sie, welcher Eingang hoch gegangen ist, und setzen Sie den entsprechenden bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // diese if-Anweisungen sehen sich an, welcher Eingang hoch gegangen ist und gibt den entsprechenden Wert in die Variable "buttonpressed" // ein, diese Variable bestimmt die Bewegungsrichtung if(butup==true) { buttonpressed=DIRUP; // Serial.println ("UP gedrückt"); // Serial.println (Taste gedrückt); butup=falsch; Ton (SND, 1500, 10); } if (butdown==true) { buttonpressed=DIRDOWN; // Serial.println ("DOWN gedrückt"); // Serial.println (Taste gedrückt); butdown=falsch; Ton (SND, 1500, 10); }

if(butleft==true)

{ buttonpressed=DIRLEFT; // Serial.println ("LINKS gedrückt"); // Serial.println (Taste gedrückt); aberlinks=falsch; Ton (SND, 1500, 10); } if (butright==true) { buttonpressed=DIRRIGHT; // Serial.println ("RECHTS gedrückt"); // Serial.println (Taste gedrückt); aberrichtig=falsch; Ton (SND, 1500, 10); } }

//-------------------------- Zeichnen der Anzeigeroutinen------------------ -----------------

void updateDisplay() // Punkte und Umrisse zeichnen

{//Serial.println ("Anzeige aktualisieren");

display.fillRect(0, 0, display.width()-1, 8, SCHWARZ);

display.setTextSize(0); display.setTextColor (WEISS); // Punktzahlen zeichnen display.setCursor(2, 1); display.print("Ergebnis:"); display.print (String (Playscore, DEC)); display.setCursor(66, 1); display.print("Hoch:"); display.print (String (Highscore, DEC)); // Spielbereich zeichnen // Pos 1x, 1y, 2x, 2y, Farbe display.drawLine(0, 0, 127, 0, WHITE); // ganz oben display.drawLine(63, 0, 63, 9, WEISS); // Punktetrenner display.drawLine(0, 9, 127, 9, WEISS); // unterhalb des Textrahmens display.drawLine (0, 63, 127, 63, WEISS); // unterer Rand display.drawLine (0, 0, 0, 63, WEISS); // linker Rand display.drawLine (127, 0, 127, 63, WEISS); //rechter Rand

}

//------------------------------------- Spielbereich aktualisieren ---------- --------------------

void updateGame() // dies aktualisiert die Anzeige des Spielbereichs

{display.clearDisplay();

display.drawPixel(scranPosX, scranPosY, WEISS);

scranAte = scranFood();

// Schlangenroutinen überprüfen

if (outOfArea()||selfCollision())

{ Spiel ist aus(); }

// Schlange anzeigen

for(int i=0;i0;i--) { snakePosX = snakePosX[i-1]; SchlangePosY = SchlangePosY[i-1]; } // füge der Schlange ein zusätzliches Pixel hinzu if (scranAte) { snakeSize + = 1; SnakePosX[snakeSize-1]=SchlangeX; SchlangePosY[snakeSize-1]=schlangeY; }

Schalter (Taste gedrückt) // war SnakeDirection

{ case DIRUP: SchlangeY-=1; brechen; case DIRDOWN: SchlangeY+=1; brechen; Fall DIRLEFT: SchlangeX-=1; brechen; Fall DIRRIGHT: SchlangeX+=1; brechen; } SchlangePosX[0] = SchlangeX; SchlangePosY[0] = SchlangeY; updateDisplay(); display.display(); // ------------------- Platziere den Scan -------------------

void placeScran()

{ scranPosX = zufällig (worldMinX+1, worldMaxX-1); scranPosY=zufällig(worldMinY+1, worldMaxY-1); } //------------------------ SCRAN ATE POINT UP ---------------- bool scranFood() { if(snakeX==scranPosX&&snakeY==scranPosY) { Playscore=Playscore+10; Ton (SND, 2000, 10); updateDisplay(); placeScran(); 1 zurückgeben; aufrechtzuerhalten. Sonst { 0 zurückgeben; } } //--------------------- außerhalb des Gebiets---------------------- bool outOfArea() { return snakeX =worldMaxX ||snakeY=worldMaxY; } //---------------------- Spiel ist aus----------------------- --- void gameOver() { uint8_t rectX1, rectY1, rectX2, rectY2; rechtX1=38; rechtY1=28; rectX2=58; rectY2=12; display.clearDisplay(); display.setCursor(40, 30); display.setTextSize(1); Ton (SND, 2000, 50); display.print("SPIEL"); Ton (SND, 1000, 50); display.print("ÜBER"); if(playscore>=highscore) //Überprüfen, ob die Punktzahl höher als die Highscore ist { highscore=playscore; // einzelne if-Anweisung zum Aktualisieren des Highscores} for(int i=0;i<=16;i++) // Dies ist das Zeichnen von Rechtecken um das Spiel herum { display.drawRect(rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("wenn Schleife"); display.display(); rectX1-=2; // um 2 Pixel verschieben rectY1-=2; geradeX2+=4; // Verschiebung um 2 Pixel vom letzten Punkt rectY2+=4; Ton (SND, i*200, 3); } display.display(); // Bildschirmlöschung nach Ruhm über rectX1 = 0; // Startposition der Zeile setzen rectY1=0; rectX2=0; rechtY2 = 63; für (int i = 0; i < = 127; i ++) { uint8_t cnt = 0; display.drawLine(rectX1, rectY1, rectX2, rectY2, SCHWARZ); rectX1++; rectX2++; display.display(); } display.clearDisplay(); Spielstand=0; // Schlange und Spielerdetails zurücksetzen snakeSize=1; SchlangeX=display.width()/2; SchlangeY=display.height()/2; waitForPress(); // warten, bis der Spieler das Spiel startet } //-------------------------wartet, bis die Schleife gedrückt wird ---------- --------------- void waitForPress() { bool wait=0; // Schleife endet, wenn dies wahr ist display.clearDisplay(); während (warten = = 0) { drawALineForMe (WEISS); // eine zufällige weiße Linie zeichnen drawALineForMe(BLACK); // eine zufällige schwarze Linie zeichnen, damit der Bildschirm nicht vollständig weiß ausfüllt display.fillRect(19, 20, 90, 32, BLACK); // leerer Hintergrund für Text display.setTextColor(WHITE); display.setCursor(35, 25); display.setTextSize(2); // größere Schrift display.println("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, WEISS); // Rahmen Schlange display.drawRect(19, 20, 90, 32, WEISS); // Rahmenbox - 3 display.setCursor(28, 42); display.setTextSize(0); // Schriftart zurück zum normalen display.println("beliebige Taste drücken"); display.display(); warten = digitalRead (INTPIN); // Überprüfen Sie, ob die gedrückte Taste beim Warten auf 1 endet, während buttonpressed=0; // Reset-Taste drücken } } //-------------------- ZEICHNE eine zufällige Zeile Eingabefarbe uint8_t------------- ----- void drawALineForMe (uint8_t clr) { uint8_t line1X, line1Y, line2X, line2Y=0; // setze zufällige Koordinaten für eine Linie und zeichne sie dann // variabel nicht weniger nicht mehr line1X = random(worldMinX+1, worldMaxX-1); line1Y = random(worldMinY+1, worldMaxY-1); line2X = random(worldMinX+1, worldMaxX-1); line2Y = random(worldMinY+1, worldMaxY-1); display.drawLine(line1X, line1Y, line2X, line2Y, clr); } //------------------------------------- Kollisionserkennung -------- ------------------------

for(byte i=4;i<snakeSize;i++) { if(snakeX==snakePosX&&snakeY==snakePosy) { return 1; Ton (SND, 2000, 20); Ton (SND, 1000, 20); } Rückgabe 0; }

//-------------------------------- ERSTELLEN--------------- ------------------------------------------

Void setup () { Verzögerung (100); // Gib dem Zeug einfach eine Chance zum "Booten" // Serial.begin (9600); // Deaktivieren Sie dies, wenn Sie die seriellen Ausgänge sehen möchten display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // starte mit einem sauberen Display display.setTextColor(WHITE); // setze die Rotationsgröße der Textfarbe usw. display.setRotation(0); display.setTextWrap(false); display.dim(0); // Stellen Sie die Displayhelligkeit ein PinMode (INTPIN, INPUT); // Stellen Sie die richtigen Ports auf die Eingänge ein PinMode (UPPIN, INPUT); pinMode (DWNPIN, EINGANG); pinMode (LFTPIN, EINGANG); pinMode (RHTPIN, EINGANG); // Dies ist der Interrupt-Befehl, der das Arduino "hält", um die Eingänge zu lesen // Befehlsfunktion-Pin-Funktion zum Ausführen der Bedingung für Pin AttachInterrupt (digitalPinToInterrupt (INTPIN), Interruptpressed, RISING); // Serial.println ("Setup bestanden"); waitForPress(); // Anzeige des Startbildschirms der Schlange placeScran (); // Platziere das erste Stück Essen } //---------------------MAIN LOOP----------------- ---------------------- Void Schleife () { updateGame (); // diese Funktion trägt den Hauptcode }

Schritt 3:

Empfohlen: