Inhoudsopgave:

Arduino OLED Snake-spel - Ajarnpa
Arduino OLED Snake-spel - Ajarnpa

Video: Arduino OLED Snake-spel - Ajarnpa

Video: Arduino OLED Snake-spel - Ajarnpa
Video: Arduino Snake Game Project - LED Matrix + Joystick 2024, November
Anonim
Arduino OLED-slangspel
Arduino OLED-slangspel

Hallo en welkom, bij onze instructables over het maken en arduino OLED-spel, dit project kwam tot stand toen we probeerden onze allereerste game met een arduino te maken, zoooo, we dachten waar we beter konden beginnen dan de nokia-klassieker Snake (goed bij tenminste een slangenkloon:)).

Wat je nodig zult hebben

Benodigdheden

Arduino UNO of kloon

OLED-scherm

4 Diodes

500-1k weerstand

4 bedieningsknoppen

Passieve piëzo-zoemer

optioneel

Soldeerloze Broodplank

Let op: deze links zijn bijvoorbeeld alleen

Stap 1: Het circuit

Het circuit
Het circuit

In de bovenstaande afbeelding kun je ons circuit zien, we gebruiken pin d3 op de Arduino als een interruptverzoekpin, zodat de Arduino prioriteit zal geven aan het lezen van de controller-ingangen die d4 d5 d6 d7 zijn. De basis van het circuit is dat een richtingsknop wordt ingedrukt die 5v hoog gaat, dit activeert de interruptverzoekpin (d3 paarse draad) en een bijbehorende richtingspin, de interruptfunctie roept een update-richtingsfunctie aan en die code beweegt de slang dienovereenkomstig. Pin 9 wordt gebruikt als de geluidspin omdat het een PWM is (~ pulsbreedtemodulatie) die rechtstreeks is aangesloten op een 5v piëzo op de + pin en de - gaat terug naar 0v/aarde.

(Ter info op de arduino uno en klonen kunnen alleen d2 en d3 fungeren als interruptverzoekpinnen).

Richting pinnen:

d4 Omhoog ORANJE

d5 Omlaag ROZE

d6 Links BLAUW

d7 Rechts BRUIN

d9 geluid GRIJS

Elke knop heeft een in 5v-verbindingsingang en een uitgang die eerst is verbonden met hun respectieve digitale ingang op de Arduino, dezelfde uitgang van elke knop is vervolgens verbonden met zijn eigen diode, we gebruiken de diodes om te stoppen met het terugvoeren van spanning naar de andere knoppen en deze te activeren. Aan het kathode (-) uiteinde van alle 4 diodes voegen we ze samen om een uitgangsjunctie te creëren die verbinding maakt met d3 en vervolgens via de a-weerstand naar 0v / aarde om de arduino-pinnen laag te trekken om geen zwevende pinnen te verlaten wanneer ze niet zijn geactiveerd.

(Ter info: een zwevende pin kan fantoomspanning ontvangen en ongewoon gedrag veroorzaken)

Er worden 2 analoge pinnen gebruikt om het display aan te sturen, dit zijn de arduino hardware i2c-pinnen.

A5 is aangesloten op SCL GEEL

A4 is aangesloten op SDA GREEN

De +5v en 0v (aarde) uitgang van de arduino wordt gebruikt als de stroombron voor het hele circuit dat kan worden gevoed door een usb- of telefoonoplader.

Stap 2: De code

//------------------------ ANJAWARE SNAKE Games Met hulp van de internetmensen --------------- -------

#erbij betrekken

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // weergaveset (breedte, hoogte) Adafruit_SSD1306 display(128, 64); // definieer invoerpinnen dit zijn de pinnen op de arduino ze veranderen nooit dus #define #define INTPIN 3 // alleen pinnen 2 en 3 kunnen pinnen op UNO onderbreken #define UPPIN 4 // dit zijn pinnen verbonden met relevante schakelaar #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // definieer richtingen #define DIRUP 1 // deze waarden is waar de "slang" naar kijkt om te beslissen- #define DIRDOWN 2 // de richting waarin de slang zal reizen # definieer DIRLEFT 3 #define DIRRIGHT 4

// stel knopvariabelen in

// vluchtig omdat we het nodig hebben om te updaten met de onderbreking, dus het kan elk beetje cycluswaarde zijn

// is nooit hoger dan 4, dus heb alleen 8bit int nodig om vluchtige bronnen te besparen uint8_t buttonpressed=0; bool butup=0; bool butdown=0; // we gebruiken dit om true in te stellen om "detect" in welke richting bool butleft=0 te drukken; bool butright=0;

// snake ints

byte snakePosX[30]; // array om body van snake-byte snakePosY[30] te maken;

int slangX=30; // positie slangkop

int slangY=30; int snakeSize=1; // aantal slangen beperkt tot de grootte van de array

// wereld ints

uint8_t worldMinX=0; // deze bepalen de grenzen van het speelgebied

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

// verzamel scran (voedsel) en positie van scran

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

// scores variabelen

lange speelscore=0; lange hoge score=30; // stel hoge score in op 3 verzamelen als startpunt

//--------------------------- dit is wat de onderbreking uitvoert bij spanningsstijging ------------ -------------

void interruptpressed() { delay(150); // kleine vertraging voor toegevoegde "bounce" bescherming updatedirection(); } // ------------------ werk de richtingswaarde bij door op de knop te drukken ----------------- void updatedirection() { // Serial.println ("bijwerkrichting"); butup=digitalRead (UPPIN); // controleer welke invoer hoog ging en stel relevante bool true butdown=digitalRead(DWNPIN); butleft=digitalRead(LFTPIN); butright=digitalRead (RHTPIN); // deze if statemeents kijken welke input hoog ging en voeren de relevante waarde in "buttonpressed" // variabele, deze variabele dicteert de bewegingsrichting if(butup==true) { buttonpressed=DIRUP; // Serial.println ("UP ingedrukt"); // Serial.println (knop ingedrukt); butup=fals; toon (SND, 1500, 10); } if(butdown==true) { buttonpressed=DIRDOWN; // Serial.println ("DOWN ingedrukt"); // Serial.println (knop ingedrukt); butdown=false; toon (SND, 1500, 10); }

if(butleft==true)

{ buttonpressed=DIRLEFT; // Serial.println ("LINKS ingedrukt"); // Serial.println (knop ingedrukt); maarlinks=onwaar; toon (SND, 1500, 10); } if(butright==true) { buttonpressed=DIRRIGHT; // Serial.println ("RECHTS ingedrukt"); // Serial.println (knop ingedrukt); butright=false; toon (SND, 1500, 10); } }

//-------------------------- teken de weergaveroutines ------------------ -----------------

void updateDisplay() // teken scores en contouren

{ // Serial.println ("Weergave bijwerken");

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

display.setTextSize(0); display.setTextColor(WIT); // teken scores display.setCursor (2, 1); display.print("Score:"); display.print(String(playscore, DEC)); display.setCursor(66, 1); display.print("Hoog:"); display.print(String(hoge score, DEC)); // speelgebied tekenen // pos 1x, 1y, 2x, 2y, kleurendisplay.drawLine(0, 0, 127, 0, WIT); // zeer bovenste rand display.drawLine (63, 0, 63, 9, WIT); // partituurscheider display.drawLine (0, 9, 127, 9, WIT); // onder tekstrand display.drawLine (0, 63, 127, 63, WIT); // onderste rand display.drawLine (0, 0, 0, 63, WIT); // linkerrand display.drawLine (127, 0, 127, 63, WIT); //rechterrand

}

//----------------------------------- speelgebied bijwerken ---------- --------------------

void updateGame() // dit werkt de weergave van het spelgebied bij

{ display.clearDisplay();

display.drawPixel(scranPosX, scranPosY, WIT);

scranAte = scranFood();

// controleer slangenroutines

if (outOfArea()||selfCollision())

{ spel is over(); }

// toon slang

for(int i=0;i0;i--) { snakePosX = snakePosX[i-1]; snakePosY = snakePosY[i-1]; } // voeg een extra pixel toe aan de snake if(scranAte) { snakeSize+=1; snakePosX[snakeSize-1]=snakeX; snakePosY[snakeSize-1]=snakeY; }

schakelaar (knop ingedrukt) // was snakeDirection

{ geval DIRUP: snakeY-=1; pauze; geval DIRDOWN: snakeY+=1; pauze; case DIRLEFT: snakeX-=1; pauze; hoofdletters DIRRIGHT: snakeX+=1; pauze; } snakePosX[0] = snakeX; snakePosY[0] = snakeY; updateDisplay(); weergave.weergave(); // --------------------- plaats de scran -------------------

lege plaatsScran()

{ scranPosX=willekeurig (worldMinX+1, worldMaxX-1); scranPosY=willekeurig (worldMinY+1, worldMaxY-1); } //------------------------ SCRAN ATE PUNT OMHOOG ---------------- bool scranFood() {if(snakeX==scranPosX&&snakeY==scranPosY) { playscore=playscore+10; toon (SND, 2000, 10); updateDisplay(); plaatsScran(); retour 1; } anders { retourneer 0; } } //--------------------- buiten het gebied---------------------- bool outOfArea() { return snakeX =worldMaxX ||snakeY=worldMaxY; } //---------------------- spel is over----------------------- --- void gameOver() { uint8_t rectX1, rectY1, rectX2, rectY2; rectX1=38; rectY1=28; rectX2=58; rectY2=12; display.clearDisplay(); display.setCursor(40, 30); display.setTextSize(1); toon (SND, 2000, 50); display.print("GAME"); toon (SND, 1000, 50); display.print("OVER"); if(playscore>=highscore) //controleer of de score hoger is dan de highscore { highscore=playscore; //single if-verklaring om de hoge score bij te werken} for(int i=0;i<=16;i++) // dit is om rechthoeken rond game over te tekenen {display.drawRect(rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println("if lus"); weergave.weergave(); rectX1-=2; // verschuiven met 2 pixels rectY1-=2; rectX2+=4; // shift over 2 pixels vanaf het laatste punt rectY2+=4; toon (SND, i*200, 3); } weergave.weergave(); // Scherm wissen na roem over rectX1=0; // stel startpositie van lijn in rectY1=0; rectX2=0; rectY2=63; voor (int i =0;i<=127;i++) { uint8_t cnt=0; display.drawLine (rectX1, rectY1, rectX2, rectY2, ZWART); rectX1++; rectX2++; weergave.weergave(); } display.clearDisplay(); speelscore=0; // reset snake en spelerdetails snakeSize=1; snakeX=weergave.breedte()/2; snakeY=display.height()/2; waitForPress(); // wacht tot de speler het spel start } //-------------------------wacht tot de lus wordt ingedrukt ---------- --------------- void waitForPress() { bool wait=0; // lus eindigt wanneer dit waar is display.clearDisplay(); while(wachten==0) { drawAlineForMe(WIT); // teken een willekeurige witte lijn drawAlineForMe(BLACK); // teken een willekeurige zwarte lijn zodat het scherm de witte display.fillRect(19, 20, 90, 32, BLACK); // lege achtergrond voor tekst display.setTextColor (WHITE); display.setCursor(35, 25); display.setTextSize(2); // groter lettertype display.println ("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, WIT); // border Snake display.drawRect (19, 20, 90, 32, WIT); // grensvak - 3 display.setCursor (28, 42); display.setTextSize(0); // lettertype terug naar normaal display.println ("druk op een willekeurige toets"); weergave.weergave(); wachten = digitalRead (INTPIN); // controleer om te zien of het wachten op de toets zal veranderen in 1 die eindigt terwijl de knop ingedrukt is = 0; // druk op reset-knop } } //-------------------- TEKEN een willekeurige lijninvoerkleur uint8_t-------------- ----- void drawAlineForMe (uint8_t clr) { uint8_t line1X, line1Y, line2X, line2Y=0; // stel willekeurige coördinaten in voor een lijn en teken deze dan // variabel niet minder niet meer line1X = willekeurig (worldMinX+1, worldMaxX-1); regel1Y = willekeurig (wereldMinY+1, wereldMaxY-1); line2X = willekeurig (worldMinX+1, worldMaxX-1); regel2Y = willekeurig (wereldMinY+1, wereldMaxY-1); display.drawLine(line1X, line1Y, line2X, line2Y, clr); } //------------------------------------- botsingsdetectie -------- -----------------------

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

//-------------------------------- OPSTELLING--------------- -------------------------------

void setup () { vertraging (100); // geef dingen gewoon een kans om te "booten" // Serial.begin (9600); // schakel dit uit als u de seriële uitgangen wilt zien.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // begin met een schoon display display.setTextColor (WHITE);// stel de rotatiegrootte van de tekstkleur in, enz. display.setRotation (0); display.setTextWrap(false); display.dim(0); // stel de schermhelderheid pinMode (INTPIN, INPUT) in; // stel de juiste poorten in op pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode(LFTPIN, INGANG); pinMode (RHTPIN, INPUT); // dit is het interrupt-commando dit "stopt" de arduino om de ingangen te lezen //command-functie-pin-functie om uit te voeren-conditie op pin attachInterrupt(digitalPinToInterrupt(INTPIN), interruptpressed, RISING); // Serial.println ("Setup geslaagd"); waitForPress(); // toon het opstartscherm van de slang placeScran(); // plaats het eerste stukje eten } //--------------------- HOOFDLUS----------------- --------------------- void loop() { updateGame(); // deze functie is wat de hoofdcode draagt}

Stap 3:

Aanbevolen: