Inhoudsopgave:
Video: Arduino OLED Snake-spel - Ajarnpa
2024 Auteur: John Day | [email protected]. Laatst gewijzigd: 2024-01-30 11:16
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
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:
Arduino OLED-displaymenu met optie om te selecteren: 8 stappen
Arduino OLED-displaymenu met optie om te selecteren: in deze tutorial leren we hoe we een menu met een selectieoptie kunnen maken met behulp van OLED-display en Visuino.Bekijk de video
Hoe maak je een babygewichtmachine met Arduino Nano, HX-711 Load Cell en OLED 128X64 -- Kalibratie van HX-711: 5 stappen
Hoe maak je een babygewichtmachine met Arduino Nano, HX-711 Load Cell en OLED 128X64 || Kalibratie van HX-711: Hallo Instructables, een paar dagen geleden werd ik vader van een schattige baby?. Toen ik in het ziekenhuis lag, ontdekte ik dat het gewicht van de baby zo belangrijk is om de groei van de baby te volgen. Dus ik heb een idee? om een babygewichtmachine van mezelf te maken. in deze Instructable I
NeoPixels Matrix (Snake Game: 4 stappen)
NeoPixels Matrix:Snake Game: Herinner je je nog het slangenspel dat we in onze kindertijd op onze gamebox of mobiel speelden? Vandaag gaan we leren hoe we een slangenspel kunnen maken met 8*8 NeoPixels Matrix. We kiezen Arduino uno als controlecentrum en Joystick breakout-module om samen te werken
Game of Snake in C: 8 stappen
Game of Snake in C: Snake-spel was populair in oude mobiele telefoons die heel gemakkelijk kunnen worden ontwikkeld met behulp van het c-programma. Om dit project te bouwen, hebt u basiskennis van de c-syntaxis nodig. Voorbeeld: voor lus, terwijl lus, enz. Met het bouwen van dit type spelproject worden je prog
Arduino Snake op een VGA-monitor: 5 stappen
Arduino Snake op een VGA-monitor: Nou… ik heb een Arduino gekocht. Aanvankelijk was de investering gemotiveerd met iets waardoor mijn dochter geïnteresseerd zou raken in programmeren. Het bleek echter dat dit ding voor mij leuker was om mee te spelen. Na wat spelen met het maken van LED's