Spisu treści:

Gra w węża Arduino OLED: 3 kroki
Gra w węża Arduino OLED: 3 kroki

Wideo: Gra w węża Arduino OLED: 3 kroki

Wideo: Gra w węża Arduino OLED: 3 kroki
Wideo: Рецепт Храйме Пикантная Рыба По-Мароккански. Секрет приготовления 2024, Listopad
Anonim
Arduino OLED Gra w węża
Arduino OLED Gra w węża

Cześć i witaj, w naszych instrukcjach tworzenia i arduino OLED Game, ten projekt powstał, gdy próbowaliśmy stworzyć naszą pierwszą grę z arduino, baaardzo, pomyśleliśmy, od czego lepiej zacząć niż klasyczny Wąż Nokia (dobrze na przynajmniej klon węża:)).

Czego będziesz potrzebować

Kieszonkowe dzieci

Arduino UNO lub klon

Wyświetlacz OLED

4 diody

Rezystor 500-1k

4 przyciski kontrolera

Pasywny brzęczyk piezo

opcjonalny

Chlebak bez lutowania

Pamiętaj, że te linki są tylko na przykład

Krok 1: Obwód

Obwód
Obwód

Na powyższym obrazku widać nasz obwód, używamy pinu d3 na arduino jako pin żądania przerwania, aby arduino nadało priorytet odczytowi wejść kontrolera, które są d4 d5 d6 d7. Podstawą obwodu jest to, że wciśnięty jest przycisk kierunku, który przechodzi w stan wysoki 5 V, co aktywuje pin żądania przerwania (d3 fioletowy przewód) i odpowiedni pin kierunkowy, funkcja przerwania wywołuje funkcję kierunku aktualizacji, a ten kod odpowiednio przesuwa węża. Pin 9 jest używany jako pin dźwiękowy, ponieważ jest to PWM (modulacja szerokości impulsu ~), który jest podłączony bezpośrednio do 5V piezo na pinie +, a - wraca do 0v/masa.

(FYI na arduino uno i klonach tylko d2 i d3 mogą działać jako piny żądania przerwania).

Kołki kierunkowe:

d4 w górę POMARAŃCZOWY

d5 dół RÓŻOWY

d6 Lewy NIEBIESKI

d7 Prawo BRĄZOWY

d9 dźwięk SZARY

Każdy przycisk ma wejście połączenia 5 V i wyjście, które jest najpierw podłączone do odpowiedniego wejścia cyfrowego na arduino, to samo wyjście każdego przycisku jest następnie podłączone do własnej diody, używamy diod, aby zatrzymać napięcie z powrotem do inne przyciski i ich aktywowanie. Na końcu katody (-) wszystkich 4 diod łączymy je ze sobą, aby utworzyć złącze wyjściowe, które łączy się z d3, a następnie przez rezystor do 0v/ziemia, aby obniżyć piny arduino, aby nie pozostawiać pływających pinów, gdy nie są aktywowany.

(FYI pływający pin może odbierać napięcie fantomowe i powodować nietypowe zachowanie)

Do sterowania wyświetlaczem służą 2 piny analogowe, są to piny i2c sprzętowe arduino.

A5 jest podłączony do SCL ŻÓŁTY

A4 jest podłączony do SDA ZIELONY

Wyjście +5v i 0v (ziemia) z arduino służy jako źródło zasilania dla całego obwodu, który może być zasilany przez ładowarkę USB lub telefon.

Krok 2: Kodeks

//------------------------ Gry ANJAWARE SNAKE Z pomocą narodów sieci --------------- -------

#włączać

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // zestaw wyświetlania (szerokość, wysokość) Wyświetlacz Adafruit_SSD1306(128, 64); // zdefiniuj piny wejściowe to są piny na arduino, które nigdy się nie zmieniają, więc #define #define INTPIN 3 // tylko piny 2 i 3 mogą być pinami przerwanymi na UNO #define UPPIN 4 //są to piny podłączone tp odpowiedni przełącznik #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // zdefiniuj kierunki #define DIRUP 1 // na te wartości patrzy "wąż", aby zdecydować- #define DIRDOWN 2 // kierunek, w którym będzie się poruszał wąż # zdefiniuj W PRAWO 3 #zdefiniuj W PRAWO 4

// ustaw zmienne przycisku

// volitile, ponieważ potrzebujemy go do aktualizacji z przerwaniem, więc może to być dowolny bit wartości cyklu

// nigdy nie jest większa niż 4, więc wystarczy 8bit int, aby zaoszczędzić zasoby volatile uint8_t buttonpressed=0; bool butup=0; bool butdown=0; // używamy tego, aby ustawić true na "wykrywanie" kierunku naciśnięcia bool butleft=0; bool butright=0;

// wąż int

bajt snakePosX[30]; // tablica tworząca ciało węża bajt snakePosY[30];

int wążX=30; // pozycja głowy węża

int wążY=30; int snakeSize=1; // liczba rozmiarów węża ograniczona do rozmiaru tablicy

// int. świata

uint8_t światMinX=0; // te wyznaczają granice obszaru gry

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

// zbierz scran(jedzenie) i pozycję scran

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

// ocenia zmienne

długi wynik = 0; długi rekord=30; // jako punkt wyjścia ustaw wysoki wynik na 3, zbieraj

//--------------------------- oto co następuje przerwanie przy wzroście napięcia ------------ -------------

void przerwany wciśnięty () { delay(150); // niewielkie opóźnienie dla dodanej ochrony przed odbiciami updatedirection(); } // ------------------ aktualizacja wartości kierunku po naciśnięciu przycisku ------------------ void updatedirection() { // Serial.println("kierunek aktualizacji"); butup=odczyt cyfrowy (UPPIN); // sprawdź, które wejście stało się wysokie i ustaw odpowiednie bool true butdown=digitalRead(DWNPIN); butleft=odczyt cyfrowy(LFTPIN); butright=odczyt cyfrowy(RHTPIN); // jeśli komunikaty sprawdzają, który sygnał wejściowy osiągnął wysoki poziom i wpisują odpowiednią wartość w zmiennej "przyciśnięty przycisk" //, ta zmienna dyktuje kierunek ruchu if(butup==true) { buttonpressed=DIRUP; // Serial.println("naciśnięty W GÓRĘ"); // Serial.println(przycisk wciśnięty); butup=fałsz; ton(SND, 1500, 10); } if(butdown==true) { buttonpressed=DIRDOWN; // Serial.println("naciśnięty W DÓŁ"); // Serial.println(przycisk wciśnięty); butdown=fałsz; ton(SND, 1500, 10); }

if(butleft==prawda)

{ wciśnięty przycisk = W LEWO; // Serial.println("Wciśnięty W LEWO"); // Serial.println(przycisk wciśnięty); butleft=fałsz; ton(SND, 1500, 10); } if(butright==true) { buttonpressed=W PRAWO; // Serial.println("naciśnięty W PRAWO"); // Serial.println(przycisk wciśnięty); butright=fałsz; ton(SND, 1500, 10); } }

//-------------------------- narysuj procedury wyświetlania------------------ ------------------

void updateDisplay() // narysuj wyniki i kontury

{ // Serial.println("Aktualizuj wyświetlanie");

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

display.setTextSize(0); display.setTextColor (BIAŁY); // narysuj wyniki display.setCursor(2, 1); display.print("Wynik:"); display.print(String(playscore, DEC)); display.setCursor(66, 1); display.print("Wysoki:"); display.print(String(wyniki, DEC)); // narysuj obszar gry // poz 1x, 1y, 2x, 2y, color display.drawLine(0, 0, 127, 0, WHITE); // bardzo górna krawędź display.drawLine(63, 0, 63, 9, WHITE); // separator wyników display.drawLine(0, 9, 127, 9, WHITE); // poniżej granicy tekstu display.drawLine(0, 63, 127, 63, WHITE); // dolna granica display.drawLine(0, 0, 0, 63, WHITE); // lewa ramka display.drawLine(127, 0, 127, 63, WHITE); //prawa ramka

}

//----------------------------------- aktualizacja obszaru gry ---------- --------------------

void updateGame() // aktualizuje wyświetlanie obszaru gry

{ display.clearDisplay();

display.drawPixel(scranPosX, scranPosY, WHITE);

scranAte = scranFood();

// sprawdź procedury węża

if (outOfArea()||selfCollision())

{ koniec gry(); }

// wyświetl węża

for(int i=0;i0;i--) {PozycjaWężaX =PozycjaWężaX[i-1]; PozycjaWężaY = PozycjaWężaY[i-1]; } // dodaj dodatkowy piksel do węża if(scranAte) { snakeSize+=1; snakePosX[snakeSize-1]=wążX; wążPosY[RozmiarWęża-1]=wążY; }

przełącznik (przycisk wciśnięty) // był SnakeDirection

{ przypadek DIRUP: snakeY-=1; przerwa; przypadek DIRDOWN: wążY+=1; przerwa; przypadek DIRLEFT: snakeX-=1; przerwa; wielkość liter DIRRIGHT: snakeX+=1; przerwa; } snakePosX[0] = snakeX; wążPosY[0] = wążY; aktualizacjaWyświetlacz(); display.display(); // --------------------- umieść scran -------------------

void placeScran()

{ scranPosX=losowy(worldMinX+1, worldMaxX-1); scranPosY=losowy(worldMinY+1, worldMaxY-1); } //------------------------ SCRAN ATE POINT UP ---------------- bool scranFood() { if(snakeX==scranPosX&&snakeY==scranPosY) { playscore=playscore+10; ton(SND, 2000, 10); aktualizacjaWyświetlacz(); placeScran(); powrót 1; } else { return 0; } } //--------------------- poza obszarem---------------------- bool outOfArea() { return snakeX =worldMaxX ||snakeY=worldMaxY; } //---------------------- koniec gry----------------------- --- void gameOver() { uint8_t rectX1, rectY1, rectX2, rectY2; prostoX1=38; prostY1=28; prostokątX2=58; prost Y2=12; display.clearDisplay(); display.setCursor(40, 30); display.setTextSize(1); ton(SND, 2000, 50); display.print("GRA"); ton (SND, 1000, 50); display.print("PONAD"); if(playscore>=highscore) //sprawdź, czy wynik jest wyższy niż wysoki wynik { highscore=playscore; //pojedyncza instrukcja if aktualizująca wysoki wynik } for(int i=0;i<=16;i++) // jest to rysowanie prostokątów wokół gry nad { display.drawRect(rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println("pętla if"); display.display(); prostX1-=2; // przesunięcie o 2 piksele rectY1-=2; prostokątX2+=4; // przesunięcie o 2 piksele od ostatniego punktu rectY2+=4; ton(SND, i*200, 3); } display.display(); //Wymazywanie ekranu po sławie nad rectX1=0; // ustaw pozycję początkową linii rectY1=0; prostokątX2=0; prost Y2=63; for (int i =0;i<=127;i++) { uint8_t cnt=0; display.drawLine(rectX1, rectY1, rectX2, rectY2, CZARNY); prostokąt X1++; prostokątX2++; display.display(); } display.clearDisplay(); wynik odtworzeń=0; // resetowanie szczegółów węża i gracza snakeSize=1; snakeX=wyświetlacz.szerokość()/2; wążY=wyświetl.wysokość()/2; czekajnaprasę(); // czekaj na rozpoczęcie gry przez gracza } //-----------------------------czekaj na pętlę naciśnięć ---------- --------------- void waitForPress() { bool wait=0; // pętla kończy się, gdy jest to prawda display.clearDisplay(); while (czekanie==0) { drawALineForMe (BIAŁY); // narysuj losową białą linię drawAlineForMe(BLACK); // narysuj losową czarną linię, tak aby ekran nie wypełnił się całkowicie białym kolorem display.fillRect(19, 20, 90, 32, BLACK); // puste tło dla tekstu display.setTextColor(WHITE); display.setCursor(35, 25); display.setTextSize(2); // większa czcionka display.println("WĄŻ"); // x y w h r col display.drawRoundRect(33, 22, 62, 20, 4, WHITE); // border Snake display.drawRect(19, 20, 90, 32, WHITE); // ramka - 3 display.setCursor(28, 42); display.setTextSize(0); // czcionka z powrotem do normalnego display.println("naciśnij dowolny klawisz"); display.display(); czekanie = digitalRead(INTPIN); // sprawdź, czy po naciśnięciu klawisza czekanie zmieni się na 1 kończące się, gdy naciśnięty przycisk=0; // przycisk resetowania naciśnij } } //-------------- NArysuj losowy kolor linii wejściowej uint8_t-------------- ----- void drawAlineForMe(uint8_t clr) { uint8_t linia1X, linia1Y, linia2X, linia2Y=0; // ustaw losowe współrzędne dla linii, a następnie ją narysuj // zmienna nie mniej nie więcej line1X = random(worldMinX+1, worldMaxX-1); linia1Y = losowy(worldMinY+1, worldMaxY-1); line2X = losowy(worldMinX+1, worldMaxX-1); line2Y = random(worldMinY+1, worldMaxY-1); display.drawLine(linia1X, linia1Y, linia2X, linia2Y, clr); } //------------------------------------- wykrywanie kolizji -------- -----------------------

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

//-------------------------------- USTAWIAĆ--------------- -------------------------------

void setup() { opóźnienie (100); // po prostu daj rzeczy szansę na "boot" // Serial.begin(9600); // odznacz to, jeśli chcesz zobaczyć wyjścia szeregowe display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // zacznij od czystego wyświetlania display.setTextColor(WHITE);// ustaw rozmiar obrotu tekstu itp. display.setRotation(0); display.setTextWrap(false); display.dim(0); // ustaw jasność wyświetlacza pinMode(INTPIN, INPUT); // ustaw odpowiednie porty na wejścia pinMode(UPPIN, INPUT); pinMode(DWNPIN, WEJŚCIE); pinMode (LFTPIN, WEJŚCIE); pinMode(RHTPIN, WEJŚCIE); // to jest polecenie przerwania, które "zatrzymuje" arduino w celu odczytania danych wejściowych //polecenie-funkcja-funkcja-pin do wykonania-warunku na pinie attachInterrupt(digitalPinToInterrupt(INTPIN), przerwanie naciśnięte, WZNOSZENIE); // Serial.println("Instalacja zakończona"); czekajnaprasę(); // wyświetl ekran startowy węża placeScran(); // połóż pierwszy kawałek jedzenia } //---------------------MAIN LOOP----------------- ---------------------- void loop() { aktualizacjaGra(); // ta funkcja przenosi główny kod }

Krok 3:

Zalecana: