Mündəricat:

Arduino OLED Snake Oyunu: 3 addım
Arduino OLED Snake Oyunu: 3 addım

Video: Arduino OLED Snake Oyunu: 3 addım

Video: Arduino OLED Snake Oyunu: 3 addım
Video: Arduino Snake Game | 8X8 Matrix LED Display MAX7219 2024, Iyul
Anonim
Arduino OLED İlan Oyunu
Arduino OLED İlan Oyunu

Salam və xoş gəldiniz, OLED Oyununun necə qurulacağına dair göstərişlərimizə bu layihə, ilk oyunumuzu arduino, soooo ilə etməyə çalışdığımız vaxt gəldi, nokia klassik Snake -dən daha yaxşı başlayacağımızı düşündük. heç olmasa bir ilan klonu:)).

Ehtiyacınız olacaq

Təchizat

Arduino UNO və ya klon

OLED Ekran

4 diod

500-1k müqavimət

4 nəzarətçi düyməsi

Passiv Piezo siqnalı

isteğe bağlı

Lehimsiz çörək taxtası

Bu bağlantıların yalnız nümunə olduğunu unutmayın

Addım 1: Dövrə

Dövrə
Dövrə

Yuxarıdakı şəkildə dövranımızı görə bilərsiniz, arduinonun d4 d5 d6 d7 olan nəzarətçi girişlərini oxumağa üstünlük verməsi üçün arduino üzərindəki d3 pinini kəsmə sorğusu pin olaraq istifadə edirik. Dövrün əsasları, 5v -ə yüksələn bir istiqamət düyməsinə basılmasıdır ki, bu da kəsmə tələb pinini (d3 bənövşəyi tel) və müvafiq istiqamət pinini aktivləşdirir, kəsmə funksiyası bir yeniləmə istiqaməti funksiyasını çağırır və bu kod ilanı buna uyğun hərəkət etdirir. Pin 9, sancaq olaraq istifadə olunur, çünki bu, + pin üzərində 5v piezoya birbaşa bağlı olan PWM (~ nəbz eni modulyasiyası) və 0v/yerə geri qayıdır.

(Arduino uno və klonlardakı məlumat yalnız d2 və d3 -də kəsilmə istəyi pinləri kimi çıxış edə bilər).

İstiqamət pinləri:

d4 YÜKSƏK narıncı

d5 Aşağı PINK

d6 Sol MAVİ

d7 Sağ Qəhvəyi

d9 səs boz

Hər bir düymədə 5v -lik bir giriş girişi və əvvəlcə arduino üzərindəki müvafiq rəqəmsal girişə qoşulan bir çıxış var, hər bir düymənin eyni çıxışı daha sonra öz dioduna qoşulur, gərginliyi geri qaytarmağı dayandırmaq üçün diodlardan istifadə edirik. digər düymələr və onları aktivləşdirin. Bütün 4 diodun katotunun (-) ucunda, d3-ə bağlanan bir çıxış qovşağı yaratmaq üçün bir araya gələrək arduino sancaqlarını aşağı çəkmək üçün 0v/toprağa bir müqavimət vasitəsi ilə aşağıya çəkirik. aktivləşdirildi.

(FYI üzən pin xəyal gərginliyi qəbul edə bilər və qeyri -adi davranışa səbəb ola bilər)

Ekranı idarə etmək üçün 2 analog pin istifadə olunur, bunlar arduino hardware i2c pinləridir.

A5 SCL YELLOW -a bağlıdır

A4 SDA GREEN -ə qoşulub

Arduinodan +5v və 0v (torpaq) çıxışı, usb və ya telefon şarj cihazı ilə işləyə bilən bütün dövrə üçün enerji mənbəyi olaraq istifadə olunur.

Addım 2: Kod

// ------------------------ ANJAWARE YILAN Oyunları xalis insanların köməyi ilə --------------- -------

#daxil edin

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // ekran dəsti (en, hündürlük) Adafruit_SSD1306 ekran (128, 64); // giriş sancaqlarını təyin edin, bunlar heç vaxt dəyişmədikləri arduino -dakı sancaqlardır #təyin edin #INTPIN 3 -ü təyin edin // yalnız 2 və 3 -cü pinlər UNO -da kəsişən sancaqlar ola bilər #UPPIN 4 -ü təyin edin // bunlar müvafiq açarla əlaqəli pinlərdir #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // istiqamətləri təyin et #DIRUP 1i təyin et // bu dəyərlər "ilanın" qərar vermək üçün baxdığı şeydir- #DIRDOWN 2 təyin edin // ilanın gedəcəyi istiqamət # DIRLEFT 3 -ü təyin edin #DIRRIGHT 4 -ü təyin edin

// düymə dəyişənlərini təyin edin

// dəyişkən olduğu üçün hər hansı bir dövr dəyəri ola bilər

// heç vaxt 4 -dən yüksək deyil, buna görə də resursları saxlamaq üçün 8bit int lazımdır uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // bunu hansı istiqamətə basdığınızı "aşkar etmək" üçün true təyin etmək üçün istifadə edirik bool butleft = 0; bool butright = 0;

// ilan ints

bayt snakePosX [30]; // ilan bədəni etmək üçün array byte snakePosY [30];

int snakeX = 30; // ilanın baş mövqeyi

int ilanY = 30; int snakeSize = 1; // ilan ölçüsü sayı serialın ölçüsü ilə məhdudlaşır

// dünya ints

uint8_t worldMinX = 0; // bunlar oyun sahəsinin sərhədlərini təyin edir

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

// skran (yemək) və skranın mövqeyini toplayın

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

// dəyişənləri qiymətləndirir

uzun oyun skoru = 0; uzun yüksək bal = 30; // başlanğıc nöqtəsi olaraq yüksək bal toplamaq üçün 3 olaraq təyin edin

// --------------------------- gərginlik artımında interupt bunu edir ------------ -------------

void interruptpressed () {gecikmə (150); // əlavə "sıçrama" qorunması üçün kiçik gecikmə updatedirection (); } // ------------------ düyməni basaraq istiqamət dəyərini yeniləyin ----------------- void updatedirection () { // Serial.println ("istiqamətin yenilənməsi"); butup = digitalRead (UPPIN); // hansı girişin yüksək olduğunu yoxlayın və müvafiq bool true butdown = digitalRead (DWNPIN) təyin edin; butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // bunlar, statemeents hansı girişin yüksəldiyinə baxarsa və "buttonpressed" // dəyişənində müvafiq dəyəri daxil edərsə, bu dəyişən hərəkət istiqamətini diktə edərsə (butup == doğru) {buttonpressed = DIRUP; // Serial.println ("Yuxarı basıldı"); // Serial.println (düyməyə basıldı); butup = yalan; ton (SND, 1500, 10); } if (butdown == doğru) {buttonpressed = DIRDOWN; // Serial.println ("AŞAĞI basıldı"); // Serial.println (düyməyə basıldı); butdown = yalan; ton (SND, 1500, 10); }

əgər (sol == doğru)

{düyməyə basıldı = DIRLEFT; // Serial.println ("SOL basıldı"); // Serial.println (düyməyə basıldı); butleft = yalan; ton (SND, 1500, 10); } if (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("SAĞ basıldı"); // Serial.println (düyməyə basıldı); butright = yalan; ton (SND, 1500, 10); }}

// -------------------------- ekran rutinlərini çəkin ------------------ -----------------

void updateDisplay () // skorları və konturları çəkin

{// Serial.println ("Ekranı Yeniləyin");

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

display.setTextSize (0); display.setTextColor (BEYAZ); // skor çəkmək display.setCursor (2, 1); display.print ("Hesab:"); display.print (String (playscore, DEC)); display.setCursor (66, 1); display.print ("Yüksək:"); display.print (String (highscore, DEC)); // oyun sahəsi çəkin // pos 1x, 1y, 2x, 2y, rəngli display.drawLine (0, 0, 127, 0, BEYAZ); // çox üst sərhəd display.drawLine (63, 0, 63, 9, BEYAZ); // hesab ayırıcı ekran.drawLine (0, 9, 127, 9, BEYAZ); // mətn sərhədinin altında display.drawLine (0, 63, 127, 63, BEYAZ); // alt sərhəd display.drawLine (0, 0, 0, 63, BEYAZ); // sol haşiyə ekranı.drawLine (127, 0, 127, 63, BEYAZ); // sağ sərhəd

}

// ----------------------------------- oyun sahəsini yeniləyin ---------- --------------------

void updateGame () // bu oyun sahəsinin görüntüsünü yeniləyir

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, BEYAZ);

scranAte = scranFood ();

// ilan qaydalarını yoxlayın

if (outOfArea () || selfCollision ())

{ oyun bitdi(); }

// ilan göstər

for (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // ilana əlavə bir piksel əlavə edin, əgər (scranAte) {snakeSize+= 1; snakePosX [snakeSize-1] = snakeX; snakePosY [snakeSize-1] = ilanY; }

keçid (düyməyə basıldı) // ilan istiqamətidir

{dava DIRUP: ilanY- = 1; fasilə; dava DIRDOWN: snakeY+= 1; fasilə; DIRLEFT halda: snakeX- = 1; fasilə; dava DIRRIGHT: snakeX+= 1; fasilə; } snakePosX [0] = snakeX; snakePosY [0] = ilanY; updateDisplay (); display.display (); // --------------------- skrabı qoyun -------------------

boş yerScran ()

{scranPosX = təsadüfi (worldMinX+1, worldMaxX-1); scranPosY = təsadüfi (worldMinY+1, worldMaxY-1); } // ------------------------ NOKTAYA YÜKLƏYİN ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore+10; ton (SND, 2000, 10); updateDisplay (); yerScran (); qayıt 1; } başqa {qaytar 0; }} // --------------------- sahə xaricində ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- oyun bitdi----------------------- --- void gameOver () {uint8_t rectX1, rectY1, rectX2, rectY2; rectX1 = 38; düzY1 = 28; rectX2 = 58; düzY2 = 12; display.clearDisplay (); display.setCursor (40, 30); display.setTextSize (1); ton (SND, 2000, 50); display.print ("OYUN"); ton (SND, 1000, 50); display.print ("OVER"); if (playscore> = highscore) // hesabın yüksək hesabdan yüksək olub olmadığını yoxlayın {highscore = playscore; // single if statment for high score to}} (int i = 0; i <= 16; i ++) // bu, {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE) üzərində oyun ətrafında düzbucaqlı şəkillər çəkmək üçündür; Serial.println ("loop varsa"); display.display (); rectX1- = 2; // 2 pikseldən yuxarı keçmək rectY1- = 2; rectX2+= 4; // son nöqtədən 2 pikseldən yuxarı keçid rectY2+= 4; ton (SND, i*200, 3); } display.display (); // rectX1 = 0 üzərində şöhrətdən sonra Ekran Silmək; // rektY1 = 0 xəttinin başlanğıc mövqeyini təyin edin; rectX2 = 0; düzY2 = 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; // ilan və oyunçu detallarını sıfırlayın snakeSize = 1; snakeX = display.width ()/2; ilanY = ekran.height ()/2; waitForPress (); // oyunçunun oyuna başlamasını gözləyin} // ------------------------- mətbuat düyməsini gözləyin ---------- --------------- void waitForPress () {bool wait = 0; // döngə bu doğru olan zaman sona çatır display.clearDisplay (); isə (gözləmə == 0) {drawALineForMe (BEYAZ); // təsadüfi ağ xətt çəkməkALINFORMe (QARA); // ekranın ağ displeyi tamamilə doldurmaması üçün təsadüfi qara xətt çəkin.fillRect (19, 20, 90, 32, SİYAH); // mətnin göstərilməsi üçün boş fon.setTextColor (BEYAZ); display.setCursor (35, 25); display.setTextSize (2); // daha böyük font display.println ("İLAN"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, BEYAZ); // sərhəd İlan ekranı.drawRect (19, 20, 90, 32, BEYAZ); // sərhəd qutusu - 3 display.setCursor (28, 42); display.setTextSize (0); // yazı tipini normal display.println ("hər hansı bir düyməyə basın"); display.display (); gözləmə = digitalRead (INTPIN); // düyməyə basıldıqda gözləmə müddətinin 1 sona dəyişəcəyini yoxlamaq üçün yoxlayın = 0; // sıfırlama düyməsini sıxın}} // -------------------- Təsadüfi bir xətt giriş rəngini çəkin uint8_t -------------- ----- etibarsız drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // bir xəttin təsadüfi koordinatlarını təyin edin və sonra çəkin // dəyişəndən artıq olmayaraq line1X = təsadüfi (worldMinX+1, worldMaxX-1); line1Y = təsadüfi (worldMinY+1, worldMaxY-1); line2X = təsadüfi (worldMinX+1, worldMaxX-1); line2Y = təsadüfi (worldMinY+1, worldMaxY-1); display.drawLine (line1X, line1Y, line2X, line2Y, clr); } // ------------------------------------- toqquşma detecion -------- -----------------------

for (byte i = 4; i <snakeSize; i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {qayıt 1; ton (SND, 2000, 20); ton (SND, 1000, 20); } 0 qaytar; }

//-------------------------------- QURMAQ--------------- -------------------------------

void setup () {gecikmə (100); // sadəcə şeylərə "açma" şansı verin // Serial.begin (9600); // display.begin (SSD1306_SWITCHCAPVCC, 0x3C) seriyalı çıxışlarını görmək istəyirsinizsə bu işarəni silin; display.clearDisplay (); // təmiz bir ekranla başlayın display.setTextColor (BEYAZ); // mətn rəngi fırlanma ölçüsünü və s. display.setRotation (0) qurun; display.setTextWrap (yanlış); display.dim (0); // ekranın parlaqlığını təyin edin pinMode (INTPIN, INPUT); // pinMode (UPPIN, INPUT) girişlərinə doğru portları təyin edin; pinMode (DWNPIN, GİRİŞ); pinMode (LFTPIN, GİRİŞ); pinMode (RHTPIN, GİRİŞ); // bu girişləri oxumaq üçün arduino-nu "dayandıran" interupt əmridir. // Serial.println ("Quraşdırma keçdi"); waitForPress (); // ilanın başlanğıc ekranını göstərin placeScran (); // yeməklərin ilk hissəsini yerləşdirin} // --------------------- MAIN LOOP ----------------- ---------------------- void loop () {updateGame (); // bu kod əsas kodu daşıyan funksiyadır}

Addım 3:

Tövsiyə: