Tartalomjegyzék:

Arduino OLED kígyójáték: 3 lépés
Arduino OLED kígyójáték: 3 lépés

Videó: Arduino OLED kígyójáték: 3 lépés

Videó: Arduino OLED kígyójáték: 3 lépés
Videó: 3D snake in led cube 2024, November
Anonim
Arduino OLED kígyó játék
Arduino OLED kígyó játék

Üdvözöljük és üdvözöljük! Az OLED játék arduino készítéséről és oktatásáról szóló oktatóanyagunkhoz ez a projekt akkor jött létre, amikor megpróbáltuk megteremteni első játékunkat egy arduino -val, szóval úgy gondoltuk, hol kezdjük jobban, mint a nokia classic Snake (hát legalább egy kígyó klón:)).

Amire szüksége lesz

Kellékek

Arduino UNO vagy klón

OLED kijelző

4 dióda

500-1 ezer ellenállás

4 vezérlőgomb

Passzív Piezo hangjelző

választható

Forrasztás nélküli kenyértábla

Kérjük, vegye figyelembe, hogy ezek a hivatkozások csak példák

1. lépés: Az áramkör

Az áramkör
Az áramkör

A fenti képen láthatjuk az áramkörünket, az arduino d3 -as érintkezőjét használjuk megszakító kérésként, így az arduino elsőbbséget ad a vezérlő bemeneteinek olvasásához, amelyek d4 d5 d6 d7. Az áramkör alapjai az, hogy megnyomnak egy iránygombot, amely 5V magasra emelkedik, ez aktiválja a megszakításkérő csapot (d3 lila vezeték) és a megfelelő irányú tűt, a megszakítás funkció frissítési irányfüggvényt hív, és ez a kód ennek megfelelően mozgatja a kígyót. A 9 -es csapot hangtűként használják, mivel ez egy PWM (~ impulzusszélesség -moduláció), amely közvetlenül a + -csap 5 V -os piezo -jához van csatlakoztatva, és a - 0 V/földre megy vissza.

(FYI az arduino uno -n és a klónokon csak a d2 és d3 működhet megszakító kérésként).

Iránycsapok:

d4 fel NARANCS

d5 Le PINK

d6 Bal KÉK

d7 Jobb BARNA

d9 szürke hang

Minden gombnak van egy 5 V -os csatlakozó bemenete és egy kimenete, amelyet először a megfelelő digitális bemenetükhöz csatlakoztatnak az arduino -n, majd mindegyik gomb ugyanazt a kimenetét a saját diódájához csatlakoztatják, a diódákkal megállítjuk a feszültséget a tápellátáshoz. más gombokat, és aktiválja őket. Mind a 4 dióda katód (-) végén összekapcsoljuk őket, hogy létrehozzunk egy kimeneti csomópontot, amely a d3-hoz csatlakozik, majd az ellenálláson keresztül a 0v/földre, hogy lehúzza az arduino csapokat, hogy ne hagyjon úszó csapokat, amikor nem aktív.

(FYI: egy úszó csap fantomfeszültséget kaphat, és szokatlan viselkedést okozhat)

A kijelző meghajtásához 2 analóg érintkezőt használnak, ezek az arduino hardver i2c tűi.

Az A5 csatlakozik az SCL YELLOW -hoz

Az A4 csatlakozik az SDA GREEN -hez

Az arduino +5v és 0v (föld) kimenete az egész áramkör áramforrásaként szolgál, amelyet USB -ről vagy telefon töltőről lehet táplálni.

2. lépés: A kód

// ------------------------ ANJAWARE SNAKE Games A net népeinek segítségével --------------- -------

#befoglalni

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // kijelzőkészlet (szélesség, magasság) Adafruit_SSD1306 kijelző (128, 64); // definiálja a bemeneti csapokat, ezek az arduino csapjai, amelyeket soha nem változtatnak meg, így #define #define INTPIN 3 // csak a 2 -es és a 3 -as csapok lehetnek megszakított tűk az UNO #define UPPIN 4 -n // ezek a csatlakoztatott érintkezők DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // határozza meg az irányokat #define DIRUP 1 // ezeket az értékeket nézi a "kígyó", hogy eldöntse- #define DIRDOWN 2 // a kígyó haladási iránya # definiálja a DIRLEFT 3 #define DIRRIGHT 4 lehetőséget

// gombváltozók beállítása

// volitile cos szükségünk van arra, hogy frissítsük az interupt -tal, így bármilyen ciklusérték lehet

// soha nem magasabb 4 -nél, így csak 8 bites int kell az erőforrások megtakarításához illékony uint8_t buttonpressed = 0; bool butup = 0; bool butdown = 0; // ezt használjuk a true beállításához "észlelni", hogy melyik irányba nyomta a bool butleft = 0; bool butright = 0;

// kígyó ints

bájtos kígyóPosX [30]; // tömb kígyótest létrehozására byte snakePosY [30];

int kígyóX = 30; // kígyófej helyzet

int kígyóY = 30; int snakeSize = 1; // a kígyóméret a tömb méretére korlátozódik

// világ ints

uint8_t worldMinX = 0; // ezek határozzák meg a játszótér határait

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

// scran (étel) és scran helyzetének összegyűjtése

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

// pontozó változókat

hosszú playcore = 0; hosszú toplista = 30; // állítsa a magas pontszámot 3 -ra, gyűjtse ki kiindulópontként

// --------------------------- ezt hajtja végre a közbülső feszültség emelkedésekor ------------ -------------

void interruptpressed () {delay (150); // enyhe késleltetés a "visszapattanó" védelemhez frissített irány (); } // ------------------ frissítse az irányértéket a gomb megnyomásával ----------------- void updatedirection () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // ellenőrizze, hogy melyik bemenet ment magasra, és állítsa be a releváns bool true butdown = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = digitalRead (RHTPIN); // ezek, ha a paraméterek megvizsgálják, hogy melyik bemenet ment magasra, és a "buttonpressed" // változóba írja be a megfelelő értéket, ez a változó diktálja a mozgás irányát, ha (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP lenyomva"); // Soros.println (gombnyomva); butup = hamis; hang (SND, 1500, 10); } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("lenyomva"); // Soros.println (gombnyomva); butdown = hamis; hang (SND, 1500, 10); }

ha (butleft == igaz)

{gombnyomás = DIRLEFT; // Serial.println ("BALRA nyomva"); // Sorozat.println (gombnyomva); butleft = hamis; hang (SND, 1500, 10); } if (butright == igaz) {gombnyomás = DIRRIGHT; // Serial.println ("JOBBRA nyomva"); // Sorozat.println (gombnyomva); butright = hamis; hang (SND, 1500, 10); }}

// -------------------------- rajzolja ki a megjelenítési rutinokat ------------------ -----------------

void updateDisplay () // pontszámok és körvonalak rajzolása

{// Serial.println ("Kijelző frissítése");

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

display.setTextSize (0); display.setTextColor (FEHÉR); // pontszámok rajzolása display.setCursor (2, 1); display.print ("Pontszám:"); display.print (Karakterlánc (lejátszási eredmény, DEC)); display.setCursor (66, 1); display.print ("Magas:"); display.print (Karakterlánc (toplista, DEC)); // játékterület rajzolása // pos 1x, 1y, 2x, 2y, színes kijelző.drawLine (0, 0, 127, 0, WHITE); // nagyon felső szegély kijelző.drawLine (63, 0, 63, 9, WHITE); // pontszám elválasztó display.drawLine (0, 9, 127, 9, WHITE); // szöveghatár kijelzés alatt.drawLine (0, 63, 127, 63, WHITE); // alsó szegély display.drawLine (0, 0, 0, 63, WHITE); // bal szegély kijelző.drawLine (127, 0, 127, 63, WHITE); // jobb szegély

}

// ----------------------------------- frissítse a játszóteret ---------- --------------------

void updateGame () // ez frissíti a játékterület kijelzőjét

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, WHITE);

scranAte = scranFood ();

// ellenőrizze a kígyó rutinjait

if (outOfArea () || önütközés ())

{ játék vége(); }

// kijelző kígyó

for (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = kígyóPosY [i-1]; } // extra képpont hozzáadása a kígyóhoz, ha (scranAte) {snakeSize+= 1; snakePosX [snakeSize-1] = kígyóX; snakePosY [snakeSize-1] = kígyóY; }

switch (gombnyomva) // was snakeDirection

{eset DIRUP: kígyóY- = 1; szünet; eset DIRDOWN: kígyóY+= 1; szünet; DIRLEFT eset: kígyóX- = 1; szünet; eset DIRRIGHT: kígyóX+= 1; szünet; } snakePosX [0] = kígyóX; snakePosY [0] = kígyóY; updateDisplay (); display.display (); // --------------------- helyezze el a scran-t -------------------

üres helyScran ()

{scranPosX = véletlenszerű (worldMinX+1, worldMaxX-1); scranPosY = véletlen (worldMinY+1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playcore = lejátszási eredmény+10; hang (SND, 2000, 10); updateDisplay (); placeScran (); visszatérés 1; } else {return 0; }} // --------------------- a területen kívül ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- játék vége----------------------- --- 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); hang (SND, 2000, 50); display.print ("GAME"); hang (SND, 1000, 50); display.print ("OVER"); if (playcore> = toplista) // ellenőrizze, hogy a pontszám magasabb -e a magas pontszámnál {toplista = lejátszási eredmény; // single if statment to update high score} for (int i = 0; i <= 16; i ++) // ez a téglalapok rajzolása a játék körül a {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("if loop"); display.display (); rectX1- = 2; // eltolás 2 képponttal rectY1- = 2; rectX2+= 4; // eltolás 2 képpont felett az utolsó ponttól rectY2+= 4; hang (SND, i*200, 3); } display.display (); // Képernyőtörlés hírnév után rectX1 = 0; // a rectY1 vonal kezdőpozíciójának beállítása = 0; rectX2 = 0; rectY2 = 63; mert (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, BLACK); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); playcore = 0; // a kígyó és a játékos adatainak visszaállítása snakeSize = 1; kígyóX = display.width ()/2; kígyóY = kijelző.magasság ()/2; waitForPress (); // várja meg, amíg a játékos elkezdi a játékot} // ------------------------- várja a sajtó ciklusát ---------- --------------- void waitForPress () {bool wait = 0; // a ciklus véget ér, ha ez az igazi display.clearDisplay (); while (várakozás == 0) {drawALineForMe (WHITE); // véletlenszerű fehér vonal rajzolása drawALineForMe (BLACK); // húzzon egy véletlenszerű fekete vonalat, hogy a képernyő ne töltse ki teljesen a fehér kijelzőt.fillRect (19, 20, 90, 32, BLACK); // üres háttér a szöveg megjelenítéséhez.setTextColor (WHITE); display.setCursor (35, 25); display.setTextSize (2); // nagyobb betűtípus display.println ("SNAKE"); // x y w h r col display.drawRoundRect (33, 22, 62, 20, 4, WHITE); // szegély Snake display.drawRect (19, 20, 90, 32, WHITE); // szegélydoboz - 3 display.setCursor (28, 42); display.setTextSize (0); // font vissza a normál kijelzőre.println ("nyomja meg bármelyik gombot"); display.display (); várakozás = digitalRead (INTPIN); // ellenőrizze, hogy a gomb megnyomásával a várakozás 1 végűre változik -e, míg a gomb megnyomása = 0; // reset gomb megnyomása}} // -------------------- RAJZOLJON egy véletlenszerű sorbeviteli színt uint8_t -------------- ----- void drawALineForMe (uint8_t clr) {uint8_t line1X, line1Y, line2X, line2Y = 0; // állítson be véletlenszerű koordinátákat egy egyeneshez, majd rajzolja meg // változó nem kevesebb, nem több line1X = random (worldMinX+1, worldMaxX-1); line1Y = véletlen (worldMinY+1, worldMaxY-1); line2X = véletlen (worldMinX+1, worldMaxX-1); line2Y = véletlen (worldMinY+1, worldMaxY-1); display.drawLine (sor1X, sor1Y, sor2X, sor2Y, clr); } // ------------------------------------ ütközés észlelése -------- -----------------------

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

//-------------------------------- BEÁLLÍT--------------- -------------------------------

void setup () {delay (100); // csak adj egy esélyt a dolgoknak a "bootoláshoz" // Serial.begin (9600); // törölje a jelölést, ha látni szeretné a soros kimenetek megjelenítését.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // tiszta kijelzővel kezdje display.setTextColor (WHITE); // állítsa be a szöveg színforgatásának méretét stb display.setRotation (0); display.setTextWrap (hamis); display.dim (0); // a kijelző fényerejének beállítása pinMode (INTPIN, INPUT); // állítsa be a megfelelő portokat a bemenetekre pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // ez az interupt parancs, amely "leállítja" az arduino-t, hogy beolvassa a bemeneteket // command- function- pin-function to execute-condition on pin attachInterrupt (digitalPinToInterrupt (INTPIN), interruptpressed, RISING); // Serial.println ("Beállítás sikeres"); waitForPress (); // a kígyóindító képernyő megjelenítése placeScran (); // helyezze el az első ételdarabot} // --------------------- FŐ LOOP ----------------- ---------------------- void loop () {updateGame (); // ez a funkció hordozza a fő kódot}

3. lépés:

Ajánlott: