Innholdsfortegnelse:

Arduino OLED Snake Game: 3 trinn
Arduino OLED Snake Game: 3 trinn

Video: Arduino OLED Snake Game: 3 trinn

Video: Arduino OLED Snake Game: 3 trinn
Video: Arduino Snake Game on an OLED display. 2024, Juli
Anonim
Arduino OLED Snake Game
Arduino OLED Snake Game

Hei og velkommen, til våre instruktører om hvordan du lager og arduino OLED Game, dette prosjektet ble til da vi prøvde å lage vårt første spill noensinne med en arduino. minst en slangeklone:)).

Hva du trenger

Rekvisita

Arduino UNO eller klon

OLED -skjerm

4 dioder

500-1k motstand

4 kontrollknapper

Passiv Piezo -summer

valgfri

Loddefritt brødbrett

Vær oppmerksom på at disse linkene bare er for eksempel

Trinn 1: Kretsen

Kretsen
Kretsen

På bildet ovenfor kan du se kretsen vår, vi bruker pin d3 på arduinoen som en avbruddsforespørselsstift, slik at arduinoen vil prioritere å lese kontrollerinngangene som er d4 d5 d6 d7. Det grunnleggende i kretsen er at det trykkes på en retningsknapp som går høyt 5v, dette aktiverer avbruddsforespørselstappen (d3 lilla ledning) og en tilsvarende retningspinne, avbryterfunksjonen kaller en oppdateringsretningsfunksjon og den koden beveger slangen tilsvarende. Pinne 9 brukes som lydpinne da det er en PWM (~ pulsbreddemodulering) som er koblet direkte til en 5v piezo på + pinnen og - går tilbake til 0v/bakken.

(FYI på arduino uno og kloner bare d2 og d3 kan fungere som avbruddsforespørselstapper).

Retningspinner:

d4 Opp ORANGE

d5 Ned PINK

d6 Venstre BLÅ

d7 Høyre BRUN

d9 lyd GRÅ

Hver knapp har en in 5v tilkoblingsinngang og en utgang som først er koblet til sin respektive digitale inngang på arduinoen, den samme utgangen til hver knapp blir deretter koblet til sin egen diode, vi bruker dioder for å stoppe spenningen som går tilbake til andre knapper og aktivere dem. På katoden (-) enden av alle 4 dioder slår vi dem sammen for å lage et utgangskryss som kobles til d3 og deretter gjennom en motstand til 0v/jord for å trekke arduino-pinnene lavt for ikke å forlate flytende pinner når de ikke er aktivert.

(FYI en flytende pinne kan motta fantomspenning og forårsake uvanlig oppførsel)

2 analoge pinner brukes til å drive skjermen, dette er arduino hardware i2c -pinner.

A5 er koblet til SCL GUL

A4 er koblet til SDA GREEN

+5v og 0v (jord) utgang fra arduino brukes som strømkilde for hele kretsen som kan drives av usb eller telefonlader.

Trinn 2: Koden

// ------------------------ ANJAWARE SNAKE Games Med hjelp fra nettfolkene --------------- -------

#inkludere

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // display set (bredde, høyde) Adafruit_SSD1306 display (128, 64); // definere inngangspinner dette er pinnene på arduinoen de endrer seg aldri, så #define #define INTPIN 3 // bare pinner 2 og 3 kan være interupt -pins på UNO #define UPPIN 4 // disse er pins tilkoblet tp relevant switch #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // definere retninger #define DIRUP 1 // disse verdiene er det "slangen" ser på for å bestemme- #define DIRDOWN 2 // retningen slangen skal bevege seg # definere DIRLEFT 3 #define DIRRIGHT 4

// sett knappvariabler

// volitile fordi vi trenger den for å oppdatere med avbruddet, så det kan være en hvilken som helst syklusverdi

// er aldri høyere enn 4 så trenger bare 8bit int for å spare ressurser volatile uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // vi bruker dette til å sette true til å "oppdage" hvilken retning som trykkes bool butleft = 0; bool butright = 0;

// slange ints

byte snakePosX [30]; // array for å lage kroppen av slange byte snakePosY [30];

int slangeX = 30; // slangehodeposisjon

int slangeY = 30; int snakeSize = 1; // antall slangestørrelser begrenset til størrelsen på matrisen

// world ints

uint8_t worldMinX = 0; // disse setter grensene for lekeområdet

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

// samle inn scran (mat) og posisjonen til scran

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

// scorer variabler

lang spillescore = 0; lang poengsum = 30; // sette høy score til 3 samle som et utgangspunkt

// --------------------------- dette er hva interuptet utfører ved spenningsstigning ------------ -------------

void interruptpressed () {delay (150); // liten forsinkelse for ekstra "sprett" beskyttelse updatedirection (); } // ------------------ oppdater retningsverdien fra knappetrykk ----------------- ugyldig oppdatert retning () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // sjekk hvilken input som gikk høyt og angi relevant bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // disse hvis statemeents ser på hvilken input som gikk høyt og angir den relevante verdien i "buttonpressed" // variabel, denne variabelen dikterer bevegelsesretningen hvis (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP trykket"); // Serial.println (knappetrykket); butup = false; tone (SND, 1500, 10); } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("NED presset"); // Serial.println (knappetrykket); butdown = false; tone (SND, 1500, 10); }

hvis (butleft == true)

{buttonpressed = DIRLEFT; // Serial.println ("VENSTRE presset"); // Serial.println (knappetrykket); butleft = false; tone (SND, 1500, 10); } hvis (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("HØYRE presset"); // Serial.println (knappetrykket); butright = false; tone (SND, 1500, 10); }}

// -------------------------- tegne visningsrutinene ------------------ -----------------

void updateDisplay () // tegne score og konturer

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

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

display.setTextSize (0); display.setTextColor (HVIT); // draw scores display.setCursor (2, 1); display.print ("Poengsum:"); display.print (streng (spillescore, DEC)); display.setCursor (66, 1); display.print ("Høy:"); display.print (String (highscore, DEC)); // tegne lekeområde // pos 1x, 1y, 2x, 2y, fargedisplay.drawLine (0, 0, 127, 0, WHITE); // meget topp kantlinje. draLine (63, 0, 63, 9, HVIT); // score separator display.drawLine (0, 9, 127, 9, WHITE); // under tekstgrensen display.drawLine (0, 63, 127, 63, WHITE); // nederste kantlinje display.drawLine (0, 0, 0, 63, WHITE); // venstre grense display.drawLine (127, 0, 127, 63, WHITE); // høyre kant

}

// ----------------------------------- oppdater avspillingsområdet ---------- --------------------

void updateGame () // dette oppdaterer visningen av spillområdet

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, WHITE);

scranAte = scranFood ();

// sjekk slangerutiner

hvis (outOfArea () || selfCollision ())

{ spillet er over(); }

// vis slange

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

switch (knappetrykket) // var snakeDirection

{sak DIRUP: snakeY- = 1; gå i stykker; sak DIRDOWN: snakeY+= 1; gå i stykker; sak DIRLEFT: snakeX- = 1; gå i stykker; sak DIRRIGHT: snakeX+= 1; gå i stykker; } snakePosX [0] = snakeX; snakePosY [0] = snakeY; updateDisplay (); display.display (); // --------------------- plasser skanningen -------------------

ugyldig stedScran ()

{scranPosX = tilfeldig (worldMinX+1, worldMaxX-1); scranPosY = tilfeldig (worldMinY+1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranMat () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore+10; tone (SND, 2000, 10); updateDisplay (); placeScran (); retur 1; } annet {return 0; }} // --------------------- utenfor området ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- spillet er 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"); if (playscore> = highscore) // sjekk om score er høyere enn high score {highscore = playscore; // single if statment to update high score} for (int i = 0; i <= 16; i ++) // dette er for å tegne rektangler rundt spillet over {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("if loop"); display.display (); rectX1- = 2; // skift med 2 piksler rectY1- = 2; rectX2+= 4; // skift over 2 piksler fra siste punkt rectY2+= 4; tone (SND, i*200, 3); } display.display (); // Screen Wipe etter berømmelse over rectX1 = 0; // angi startposisjon 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, SVART); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); spillescore = 0; // tilbakestill slange og spiller detaljer snakeSize = 1; snakeX = display.width ()/2; slangeY = display.height ()/2; waitForPress (); // vent på at spilleren skal starte spillet} // ------------------------- vent på pressekrets ---------- --------------- void waitForPress () {bool waiting = 0; // loop ender når dette er sant display.clearDisplay (); mens (venter == 0) {drawALineForMe (WHITE); // tegne en tilfeldig hvit linje drawALineForMe (SVART); // tegne en tilfeldig svart linje slik at skjermen ikke fyller helt hvitt display.fillRect (19, 20, 90, 32, SVART); // blank bakgrunn for tekstvisning.setTextColor (WHITE); 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); // font tilbake til normal display.println ("trykk på hvilken som helst tast"); display.display (); venter = digitalRead (INTPIN); // sjekk om tasten trykkes venter vil endres til 1 slutter mens knappetrykk = 0; // tilbakestillingsknapp trykk}} // -------------------- TEGN en tilfeldig linjeinngangsfarge uint8_t -------------- ----- void drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // angi tilfeldige koordinater for en linje og deretter tegne den // variabel ikke mindre ikke mer line1X = random (worldMinX+1, worldMaxX-1); line1Y = tilfeldig (worldMinY+1, worldMaxY-1); line2X = tilfeldig (worldMinX+1, worldMaxX-1); line2Y = tilfeldig (worldMinY+1, worldMaxY-1); display.drawLine (linje1X, linje1Y, linje2X, linje2Y, clr); } // ------------------------------------- påvisning av kollisjon -------- -----------------------

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

// -------------------------------- OPPSETT --------------- -------------------------------

ugyldig oppsett () {forsinkelse (100); // bare gi ting en sjanse til å "starte" // Serial.begin (9600); // fjern merket for dette hvis du vil se serielle utganger display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // start med en ren skjerm display.setTextColor (WHITE); // sette opp tekstfargerotasjonsstørrelse etc display.setRotation (0); display.setTextWrap (false); display.dim (0); // angi displayets lysstyrke pinMode (INTPIN, INPUT); // sett de riktige portene til innganger pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // dette er interupt-kommandoen, dette "stopper" arduinoen for å lese inngangene // command- function- pin-function to execute-condition on pin attachInterrupt (digitalPinToInterrupt (INTPIN), interruptpressed, RISING); // Serial.println ("Oppsett bestått"); waitForPress (); // vise startskjermen for slangen placeScran (); // legg første bit mat} // --------------------- MAIN LOOP ----------------- ---------------------- void loop () {updateGame (); // denne funksjonen er det som bærer hovedkoden}

Trinn 3:

Anbefalt: