Indholdsfortegnelse:

Arduino OLED Snake Game: 3 trin
Arduino OLED Snake Game: 3 trin

Video: Arduino OLED Snake Game: 3 trin

Video: Arduino OLED Snake Game: 3 trin
Video: Arduino Project - Star Wars Game #oled #arduinoproject #starwars 2024, Juli
Anonim
Arduino OLED Snake Game
Arduino OLED Snake Game

Hej og velkommen til vores instruktører om, hvordan man laver og arduino OLED -spil, dette projekt opstod, da vi forsøgte at lave vores første spil nogensinde med en arduino, sååå, vi tænkte på, hvor bedre at starte end nokia classic Snake (godt kl. mindst en slangeklon:)).

Hvad du får brug for

Forbrugsvarer

Arduino UNO eller klon

OLED Display

4 dioder

500-1k modstand

4 controller knapper

Passiv Piezo -summer

valgfri

Loddefri brødbræt

Bemærk venligst, at disse links kun er f.eks

Trin 1: Kredsløbet

Kredsløbet
Kredsløbet

På billedet ovenfor kan du se vores kredsløb, vi bruger pin d3 på arduinoen som en afbrydelsesanmodningsstift, så arduino'en prioriterer læsning af controllerindgange, der er d4 d5 d6 d7. Det grundlæggende i kredsløbet er, at der trykkes på en retningsknap, der går højt 5v, dette aktiverer afbrydelsesanmodningspinden (d3 lilla ledning) og en tilsvarende retningspind, afbrydelsesfunktionen kalder en opdateringsretningsfunktion, og den kode bevæger slangen i overensstemmelse hermed. Pin 9 bruges som lydnål, da det er en PWM (~ pulsbreddemodulation), der er forbundet direkte til en 5v piezo på + pin og - går tilbage til 0v/jord.

(FYI på arduino uno og kloner kan kun d2 og d3 fungere som afbrydelsesanmodningsnåle).

Retningsnåle:

d4 Op ORANGE

d5 Ned PINK

d6 Venstre BLÅ

d7 Højre BRUN

d9 lyd GRÅ

Hver knap har en in 5v tilslutningsindgang og en udgang, der først er tilsluttet deres respektive digitale indgang på arduinoen, den samme udgang fra hver knap er derefter forbundet til sin egen diode, vi bruger dioderne til at stoppe spændingstilførsel tilbage til andre knapper og aktivere dem. På katode (-) enden af alle 4 dioder forbinder vi dem med hinanden for at skabe et udgangskryds, der forbinder til d3 og derefter gennem a-modstanden til 0v/jord for at trække arduino-benene lavt for ikke at efterlade flydende stifter, når de ikke er aktiveret.

(FYI en flydestift kan modtage fantomspænding og forårsage usædvanlig adfærd)

2 analoge ben bruges til at drive displayet, det er arduino hardware i2c benene.

A5 er forbundet til SCL GUL

A4 er forbundet til SDA GREEN

+5v og 0v (jord) output fra arduino bruges som strømkilde til hele kredsløbet, som kan drives af usb eller telefon oplader.

Trin 2: Koden

// ------------------------ ANJAWARE SNAKE-spil Med hjælp fra netfolkene --------------- -------

#omfatte

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // displaysæt (bredde, højde) Adafruit_SSD1306 display (128, 64); // definer input -pins disse er pins på arduino de ændrer aldrig, så #define #define INTPIN 3 // kun pins 2 og 3 kan være afbrudte pins på UNO #define UPPIN 4 // disse er pins forbundet tp relevant switch #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // definere retninger #define DIRUP 1 // disse værdier er, hvad "slangen" ser på for at bestemme- #define DIRDOWN 2 // retningen slangen vil bevæge sig # definer DIRLEFT 3 #define DIRRIGHT 4

// indstil knapvariabler

// volitile cos vi har brug for det til at opdatere med afbrydelsen, så det kan være en hvilken som helst cyklusværdi

// er aldrig højere end 4, så kun brug for 8bit int for at spare ressourcer volatile uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // vi bruger dette til at indstille true til at "registrere" hvilken retning der trykkes bool butleft = 0; bool butright = 0;

// slange ints

byte snakePosX [30]; // array til at lave krop af slange byte snakePosY [30];

int slangeX = 30; // slangehovedstilling

int slangeY = 30; int snakeSize = 1; // antallet af slangestørrelser begrænset til matrixens størrelse

// world ints

uint8_t worldMinX = 0; // disse sætter grænserne for legeområdet

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

// saml scran (mad) og position af scran

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

// scorer variabler

lang playcore = 0; lang highscore = 30; // sæt høj score til 3 indsamling som udgangspunkt

// --------------------------- dette er hvad interuptet udfører ved spændingsstigning ------------ -------------

void interruptpressed () {delay (150); // let forsinkelse for tilføjet "bounce" beskyttelse opdateret retning (); } // ------------------ Opdater retningsværdien ved at trykke på knappen ----------------- ugyldig opdateret retning () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // tjek hvilket input der gik højt og indstil relevant bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // disse hvis statemeents ser på hvilket input der gik højt og indtaster den relevante værdi i "buttonpressed" // variabel, denne variabel dikterer bevægelsesretningen hvis (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP trykket"); // Serial.println (tryk på knappen); butup = falsk; tone (SND, 1500, 10); } hvis (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("NED presset"); // Serial.println (knappetrykket); butdown = falsk; tone (SND, 1500, 10); }

hvis (butleft == true)

{buttonpressed = DIRLEFT; // Serial.println ("VENSTRE presset"); // Serial.println (tryk på knappen); butleft = falsk; tone (SND, 1500, 10); } hvis (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("HØJRE trykket"); // Serial.println (knappetrykket); butright = falsk; tone (SND, 1500, 10); }}

// -------------------------- tegne visningsrutinerne ------------------ -----------------

void updateDisplay () // tegne scoringer og konturer

{// Serial.println ("Opdateringsvisning");

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

display.setTextSize (0); display.setTextColor (HVID); // draw scores display.setCursor (2, 1); display.print ("Score:"); display.print (String (playscore, DEC)); display.setCursor (66, 1); display.print ("Høj:"); display.print (String (highscore, DEC)); // tegne afspilningsområde // pos 1x, 1y, 2x, 2y, farvedisplay.drawLine (0, 0, 127, 0, WHITE); // meget øverste kantdisplay.drawLine (63, 0, 63, 9, WHITE); // score separator display.drawLine (0, 9, 127, 9, WHITE); // under tekstgrænsen display.drawLine (0, 63, 127, 63, WHITE); // nederste kant display.drawLine (0, 0, 0, 63, WHITE); // venstre grænse display.drawLine (127, 0, 127, 63, WHITE); // højre kant

}

// ----------------------------------- opdater afspilningsområde ---------- --------------------

void updateGame () // dette opdaterer visningen af spilområdet

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, WHITE);

scranAte = scranFood ();

// tjek slange rutiner

hvis (outOfArea () || selfCollision ())

{gameOver (); }

// vis slange

for (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // tilføj en ekstra pixel til slangen hvis (scranAte) {snakeSize+= 1; snakePosX [snakeSize-1] = snakeX; snakePosY [snakeSize-1] = snakeY; }

switch (tryk på knappen) // var snakeDirection

{sag DIRUP: snakeY- = 1; pause; sag DIRDOWN: snakeY+= 1; pause; sag DIRLEFT: snakeX- = 1; pause; sag DIRRIGHT: snakeX+= 1; pause; } snakePosX [0] = snakeX; snakePosY [0] = snakeY; updateDisplay (); display.display (); // --------------------- placer scranen -------------------

void placeScran ()

{scranPosX = random (worldMinX+1, worldMaxX-1); scranPosY = random (worldMinY+1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranMad () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore+10; tone (SND, 2000, 10); updateDisplay (); placeScran (); return 1; } else {return 0; }} // --------------------- uden for området ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } // ---------------------- game 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); tone (SND, 2000, 50); display.print ("GAME"); tone (SND, 1000, 50); display.print ("OVER"); hvis (playcore> = highscore) // tjek for at se om score er højere end high score {highscore = playscore; // single if statment to update high score} for (int i = 0; i <= 16; i ++) // dette er for at tegne rektangler rundt om spillet over {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("if loop"); display.display (); rectX1- = 2; // skift med 2 pixels rectY1- = 2; rectX2+= 4; // skift over 2 pixels fra sidste punkt rectY2+= 4; tone (SND, i*200, 3); } display.display (); // Screen Wipe efter berømmelse over rectX1 = 0; // sæt startposition for linje rectY1 = 0; rectX2 = 0; rectY2 = 63; for (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, SORT); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); playcore = 0; // nulstil slange og spiller detaljer snakeSize = 1; snakeX = display.width ()/2; slangeY = display.højde ()/2; waitForPress (); // vent på, at spilleren starter spillet} // ------------------------- vent på tryk på loop ---------- --------------- void waitForPress () {bool waiting = 0; // loop ender, når dette er sandt display.clearDisplay (); mens (venter == 0) {drawALineForMe (WHITE); // tegne en tilfældig hvid streg drawALineForMe (SORT); // tegne en tilfældig sort linje, så skærmen ikke fylder helt hvidt display.fillRect (19, 20, 90, 32, SORT); // blank baggrund til tekstvisning.setTextColor (HVID); display.setCursor (35, 25); display.setTextSize (2); // større font display.println ("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, WHITE); // border Snake display.drawRect (19, 20, 90, 32, WHITE); // kantboks - 3 display.setCursor (28, 42); display.setTextSize (0); // skrifttype tilbage til normal display.println ("tryk på en vilkårlig tast"); display.display (); venter = digitalRead (INTPIN); // tjek for at se om tasten der trykkes venter ændres til 1 slutning mens knappen trykkes = 0; // nulstil knap tryk}} // -------------------- TEGN en tilfældig linje input farve uint8_t -------------- ----- void drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // indstil tilfældige koordinater for en linje, og tegn derefter den // variabel ikke mindre ikke mere line1X = random (worldMinX+1, worldMaxX-1); line1Y = random (worldMinY+1, worldMaxY-1); line2X = tilfældig (worldMinX+1, worldMaxX-1); line2Y = random (worldMinY+1, worldMaxY-1); display.drawLine (linje1X, linje1Y, linje2X, linje2Y, clr); } // ------------------------------------- påvisning af kollision -------- -----------------------

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

//-------------------------------- OPSÆTNING--------------- -------------------------------

ugyldig opsætning () {forsinkelse (100); // bare giv tingene en chance for at "starte" // Serial.begin (9600); // fjern markeringen i dette, hvis du vil se de serielle udgange blive vist. begynder (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // start med en ren skærm display.setTextColor (WHITE); // opsæt tekststørrelsesrotationsstørrelse osv display.setRotation (0); display.setTextWrap (falsk); display.dim (0); // indstil displayets lysstyrke pinMode (INTPIN, INPUT); // indstil de korrekte porte til input pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // dette er interupt-kommandoen, dette "stopper" arduinoen for at læse input // kommando- funktion- pin-funktion for at udføre-tilstand på pin attachInterrupt (digitalPinToInterrupt (INTPIN), interruptpressed, RISING); // Serial.println ("Opsætning bestået"); waitForPress (); // vis startskærmen for slangen placeScran (); // placer første bid mad} // --------------------- MAIN LOOP ----------------- ---------------------- void loop () {updateGame (); // denne funktion er det, der bærer hovedkoden}

Trin 3:

Anbefalede: