Cuprins:

Joc Arduino OLED Snake: 3 pași
Joc Arduino OLED Snake: 3 pași

Video: Joc Arduino OLED Snake: 3 pași

Video: Joc Arduino OLED Snake: 3 pași
Video: Игра змейка (snake) на Arduino 2024, Iulie
Anonim
Joc Arduino OLED Snake
Joc Arduino OLED Snake

Bună și bine ați venit, la instrucțiunile noastre despre cum să creăm și arduino joc OLED, acest proiect a apărut în timp ce încercam să facem primul nostru joc vreodată cu un arduino, așa că, ne-am gândit de unde să începem mai bine decât nokia clasic Snake (bine la cel puțin o clonă de șarpe:)).

Ce vei avea nevoie

Provizii

Arduino UNO sau clonă

Afișaj OLED

4 diode

500-1k rezistor

4 butoane ale controlerului

Buzzer Piezo pasiv

opțional

BreadBoard fără sudură

Vă rugăm să rețineți că aceste linkuri sunt doar de exemplu

Pasul 1: Circuitul

Circuitul
Circuitul

În imaginea de mai sus puteți vedea circuitul nostru, folosim pinul d3 pe arduino ca pin de solicitare a întreruperii, astfel încât arduino să acorde prioritate citirii intrărilor controlerului care sunt d4 d5 d6 d7. Elementul de bază al circuitului este acela că este apăsat un buton de direcție care crește 5v, acesta activează pinul de solicitare a întreruperii (firul violet d3) și un pin de direcție corespunzător, funcția de întrerupere apelează o funcție de direcție de actualizare și codul respectiv mută șarpele în consecință. Pinul 9 este utilizat ca pin de sunet, deoarece este un PWM (~ modulare a lățimii impulsului) care este conectat direct la un piezo 5v pe pinul + și - revine la 0v / masă.

(FYI pe arduino uno și clonele numai d2 și d3 pot acționa ca pini de solicitare a întreruperii).

Pinii de direcție:

d4 Sus ORANGE

d5 Jos PINK

d6 Stânga ALBASTRU

d7 Dreapta MARO

d9 sună GREY

Fiecare buton are o intrare de conectare în 5v și o ieșire care este conectată mai întâi la intrarea lor digitală respectivă pe arduino, aceeași ieșire a fiecărui buton este apoi conectată la propria diodă, folosim diodele pentru a opri alimentarea tensiunii înapoi prin alte butoane și activarea acestora. La capătul catodului (-) al tuturor celor 4 diode le unim pentru a crea o joncțiune de ieșire care se conectează la d3 și apoi prin rezistorul la 0v / pământ pentru a trage pinii arduino jos, astfel încât să nu lăsăm pinii plutitori atunci când nu sunt activat.

(FYI un pin plutitor poate primi tensiune fantomă și poate provoca un comportament neobișnuit)

2 pini analogici sunt folosiți pentru a conduce afișajul, aceștia sunt pini i2c hardware arduino.

A5 este conectat la SCL GALBEN

A4 este conectat la SDA GREEN

Ieșirea + 5v și 0v (pământ) de la arduino este utilizată ca sursă de alimentare pentru întregul circuit care poate fi alimentat de un încărcător USB sau telefon.

Pasul 2: Codul

// ------------------------ ANJAWARE SNAKE Jocuri Cu ajutorul poporului net --------------- -------

#include

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // afișaj set (lățime, înălțime) Adafruit_SSD1306 display (128, 64); // definesc pinii de intrare aceștia sunt pinii de pe arduino ei nu se schimbă niciodată așa că #define #define INTPIN 3 // doar pinii 2 și 3 pot fi interrupți pinii de pe UNO #define UPPIN 4 // aceștia sunt pinii conectați tp comutator relevant #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // define direcții #define DIRUP 1 // la aceste valori se uită „șarpele” pentru a decide- #define DIRDOWN 2 // direcția în care va călători șarpele # definește DIRLEFT 3 #define DIRRIGHT 4

// setează variabilele butonului

// volitile cos avem nevoie de el pentru a se actualiza cu interupt, astfel încât să poată fi orice bit de valoare a ciclului

// nu este niciodată mai mare de 4, deci aveți nevoie doar de 8 biți pentru a economisi resurse volatile uint8_t butonat = 0; bool butup = 0; bool butdown = 0; // folosim acest lucru pentru a seta true pentru a „detecta” în ce direcție apăsat butonul stâng = 0; bool butright = 0;

// șerpi ints

octet snakePosX [30]; // matrice pentru a face corpul de octepi de șarpe snakePosY [30];

șarpe int = 30; // poziția capului de șarpe

int snakeY = 30; int SnakeSize = 1; // Numărul de dimensiuni de șarpe limitat la dimensiunea matricei

// ints lume

uint8_t worldMinX = 0; // acestea stabilesc limitele zonei de joc

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

// colectează scranul (hrana) și poziția scranului

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

// marchează variabile

lung playcore = 0; scor mare lung = 30; // setați scorul maxim la 3 colectați ca punct de plecare

// --------------------------- Aceasta este ceea ce interupt execută la creșterea tensiunii ------------ -------------

void interruptpressed () {întârziere (150); // ușoară întârziere pentru protecția adăugată "bounce" updatedirection (); } // ------------------ actualizați valoarea direcției de la apăsarea butonului ----------------- anulați actualizarea direcției () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // verificați ce intrare a crescut și setați bool-ul relevant adevărat butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // acestea dacă statemeents se uită la ce intrare a crescut și introduce valoarea relevantă în variabila „apăsat pe buton” //, această variabilă dictează direcția de mișcare dacă (butup == adevărat) {buttonpressed = DIRUP; // Serial.println („UP apăsat”); // Serial.println (apăsat pe buton); butup = fals; ton (SND, 1500, 10); } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("JOS apăsat"); // Serial.println (apăsat pe buton); butdown = fals; ton (SND, 1500, 10); }

if (butleft == true)

{buttonpressed = DIRLEFT; // Serial.println ("STânga apăsat"); // Serial.println (apăsat pe buton); butleft = fals; ton (SND, 1500, 10); } if (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("DREAPTA apăsat"); // Serial.println (apăsat pe buton); butright = fals; ton (SND, 1500, 10); }}

// -------------------------- desenați rutinele de afișare ------------------ -----------------

void updateDisplay () // desenează scoruri și schițe

{// Serial.println („Actualizați afișajul”);

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

display.setTextSize (0); display.setTextColor (ALB); // desenează scoruri display.setCursor (2, 1); display.print ("Scor:"); display.print (String (playscore, DEC)); display.setCursor (66, 1); display.print ("Înalt:"); display.print (String (highscore, DEC)); // desenează zona de joc // poz 1x, 1y, 2x, 2y, display color.drawLine (0, 0, 127, 0, WHITE); // bordură foarte sus display.drawLine (63, 0, 63, 9, ALB); // seperator de scoruri display.drawLine (0, 9, 127, 9, ALB); // sub marginea textului display.drawLine (0, 63, 127, 63, WHITE); // marginea de jos display.drawLine (0, 0, 0, 63, ALB); // bordură stângă display.drawLine (127, 0, 127, 63, WHITE); // margine dreapta

}

// ----------------------------------- actualizează zona de joc ---------- --------------------

void updateGame () // actualizează afișarea zonei de joc

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, WHITE);

scranAte = scranFood ();

// verifică rutina șarpelui

if (outOfArea () || selfCollision ())

{ joc încheiat(); }

// afișează șarpe

for (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // adăugați un pixel suplimentar la șarpe dacă (scranAte) {snakeSize + = 1; snakePosX [snakeSize-1] = șarpeX; snakePosY [snakeSize-1] = șarpeY; }

comutator (apăsat pe buton) // a fost snakeDirection

{caz DIRUP: șarpeY- = 1; pauză; caz DIRDOWN: șarpeY + = 1; pauză; caz DIRLEFT: șarpeX- = 1; pauză; caz DIRECT: șarpeX + = 1; pauză; } snakePosX [0] = șarpeX; snakePosY [0] = șarpeY; updateDisplay (); display.display (); // --------------------- plasează scranul -------------------

void placeScran ()

{scranPosX = random (worldMinX + 1, worldMaxX-1); scranPosY = aleatoriu (worldMinY + 1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore + 10; ton (SND, 2000, 10); updateDisplay (); placeScran (); retur 1; } else {return 0; }} // --------------------- în afara zonei ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- joc încheiat----------------------- --- 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); ton (SND, 2000, 50); display.print ("JOC"); ton (SND, 1000, 50); display.print ("PESTE"); if (playscore> = highscore) // verificați dacă scor mai mare decât scor mare {highscore = playscore; // single if statment to update high score} for (int i = 0; i <= 16; i ++) // acesta este pentru a desena rectanlges în jurul jocului peste {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("if loop"); display.display (); rectX1- = 2; // comutați cu 2 pixeli rectY1- = 2; rectX2 + = 4; // deplasează peste 2 pixeli din ultimul punct rectY2 + = 4; ton (SND, i * 200, 3); } display.display (); // Șterge ecran după faimă peste rectX1 = 0; // setați poziția de început a liniei rectY1 = 0; rectX2 = 0; rectY2 = 63; for (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, BLACK); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); playscore = 0; // resetează șarpele și detaliile jucătorului snakeSize = 1; șarpeX = display.width () / 2; șarpeY = display.height () / 2; waitForPress (); // așteptați ca jucătorul să înceapă jocul} // ------------------------- așteptați apăsarea buclei ---------- --------------- void waitForPress () {bool waiting = 0; // bucla se termină când este adevărat display.clearDisplay (); while (așteaptă == 0) {drawALineForMe (WHITE); // desenați o linie albă aleatorie drawALineForMe (BLACK); // trasați o linie neagră aleatorie, astfel încât ecranul să nu umple complet afișajul alb.fillRect (19, 20, 90, 32, BLACK); // fundal gol pentru afișarea textului.setTextColor (ALB); display.setCursor (35, 25); display.setTextSize (2); // font mai mare display.println ("SNAKE"); // x y w h r r display.drawRoundRect (33, 22, 62, 20, 4, WHITE); // border Snake display.drawRect (19, 20, 90, 32, WHITE); // casetă de margine - 3 display.setCursor (28, 42); display.setTextSize (0); // fontul revine la afișajul normal.println („apăsați orice tastă”); display.display (); waiting = digitalRead (INTPIN); // verificați dacă tasta apăsată în așteptare se va schimba la sfârșitul 1 în timp ce butonul este apăsat = 0; // butonul de resetare apăsați}} // -------------------- DESENĂ o linie de intrare aleatorie culoare uint8_t -------------- ----- void drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // setați coordonate aleatorii pentru o linie apoi trageți-o // variabilă nu mai puțin nu mai mult 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); } // ------------------------------------- detecție de coliziune -------- -----------------------

for (octet i = 4; i <snakeSize; i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {return 1; ton (SND, 2000, 20); ton (SND, 1000, 20); } returnează 0; }

//-------------------------------- ÎNFIINȚAT--------------- -------------------------------

setare nulă () {întârziere (100); // oferă doar lucrurilor o șansă de a „porni” // Serial.begin (9600); // debifați acest lucru dacă doriți să vedeți ieșirile seriale display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // începeți cu un display curat display.setTextColor (WHITE); // configurați dimensiunea rotației culorii textului etc. display.setRotation (0); display.setTextWrap (fals); display.dim (0); // setați luminozitatea afișajului pinMode (INTPIN, INPUT); // setați porturile corecte la intrări pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // aceasta este comanda interupt, aceasta „oprește” arduino pentru a citi intrările // comandă- funcție- funcție-pin pentru a executa-condiție pe pin attachInterrupt (digitalPinToInterrupt (INTPIN), întrerupt, RISING); // Serial.println ("Setup Passed"); waitForPress (); // afișează ecranul de pornire șarpe placeScran (); // plasează primul pic de mâncare} // --------------------- BUCLA PRINCIPALĂ ----------------- ---------------------- bucla nulă () {updateGame (); // această funcție este cea care poartă codul principal}

Pasul 3:

Recomandat: