Arduino Retro Gaming Z wyświetlaczem OLED

  • Lesley Fowler
  • 0
  • 1081
  • 131
Reklama

Czy zastanawiałeś się kiedyś, ile pracy zajmuje napisanie własnych gier retro? Jak łatwo kodować Pong dla Arduino? Dołącz do mnie, gdy pokażę ci, jak zbudować mini konsolę do gier retro z zasilaniem Arduino i jak kodować Ponga od podstaw. Oto wynik końcowy:

Plan kompilacji

To dość prosty obwód. ZA potencjometr (pot) kontroluje grę, a wyświetlacz OLED będzie sterowany przez Arduino. Zostanie on utworzony na płytce ściennej, jednak możesz chcieć zrobić z niego stały obwód i zainstalować go w skrzynce. Pisaliśmy o odtwarzaniu Ponga Jak odtworzyć klasyczną grę w ponga za pomocą Arduino Jak odtworzyć grę w ponga za pomocą Arduino Pong była pierwszą grą wideo, która dotarła na rynek masowy. Po raz pierwszy w historii koncepcja „gry wideo” została wprowadzona do domu rodzinnego dzięki Atari 2600 -… wcześniej, jednak dzisiaj pokażę wam, jak napisać kod od zera i rozkładać każdy część.

Czego potrzebujesz

Oto czego potrzebujesz:

  • 1 x Arduino (dowolny model)
  • 1 x potencjometr 10k
  • 1 x wyświetlacz OLED I2C 0,96 "
  • 1 x deska do krojenia chleba
  • Różne przewody męskie> męskie

Każde Arduino powinno działać, więc zapoznaj się z naszym przewodnikiem zakupów Przewodnik zakupu Arduino: Którą płytę powinieneś dostać? Poradnik kupujący Arduino: Którą deskę powinieneś dostać? Jest tak wiele różnych rodzajów tablic Arduino, że wybaczono by ci, że jesteś zdezorientowany. Który powinieneś kupić dla swojego projektu? Pomóż nam, korzystając z tego przewodnika zakupów Arduino! jeśli nie jesteś pewien, jaki model kupić.

Te wyświetlacze OLED są bardzo fajne. Zazwyczaj można je kupić w kolorze białym, niebieskim, żółtym lub mieszance tych trzech. Istnieją w pełnym kolorze, jednak dodają one zupełnie innego poziomu do złożoności i kosztów tego projektu.

Obwód

To dość prosty obwód. Jeśli nie masz dużego doświadczenia z Arduino, sprawdź te projekty dla początkujących 15 Wielkich projektów Arduino dla początkujących 15 Wielkich projektów Arduino dla początkujących Zainteresowane projektami Arduino, ale nie wiesz, od czego zacząć? Te projekty dla początkujących nauczą Cię, jak zacząć. pierwszy.

Oto on:

Patrząc na przód doniczki, podłącz lewy pin do +5 V. i odpowiedni pin do ziemia. Podłącz środkowy pin do pin analogowy 0 (A0).

Wyświetlacz OLED jest podłączony za pomocą protokołu I2C. Połączyć VCC i GND do Arduino +5 V. i ziemia. Połączyć SCL do analog pięć (A5). Połączyć SDA do analog 4 (A4). Powód podłączenia do pinów analogowych jest prosty; te piny zawierają obwody wymagane dla protokołu I2C. Upewnij się, że są one prawidłowo podłączone, a nie skrzyżowane. Dokładne styki będą się różnić w zależności od modelu, ale A4 i A5 są używane w Nano i Uno. Sprawdź dokumentację biblioteki Wire dla swojego modelu, jeśli nie korzystasz z Arduino lub Nano.

Test doniczkowy

Prześlij ten kod testowy (upewnij się, że wybrałeś właściwą płytkę i port z Przybory > Deska i Przybory > Port menu):

void setup () // wstaw tutaj swój kod instalacyjny, aby uruchomić raz: Serial.begin (9600); // setup serial void loop () // wstaw tutaj swój główny kod, aby uruchamiał się wielokrotnie: Serial.println (analogRead (A0)); // wypisz wartość z puli opóźnienia (500); 

Teraz otwórz monitor szeregowy (W prawym górnym rogu > Monitor szeregowy) i obróć pulę. Powinieneś zobaczyć wartość wyświetlaną na monitorze szeregowym. Powinno być całkowicie przeciwnie do ruchu wskazówek zegara zero, i powinien być całkowicie zgodny z ruchem wskazówek zegara 1023:

Dostosujesz to później, ale na razie jest w porządku. Jeśli nic się nie wydarzy lub wartość zmieni się bez twojej pomocy, odłącz i dwukrotnie sprawdź obwód.

Test OLED

Wyświetlacz OLED jest nieco bardziej skomplikowany w konfiguracji. Musisz najpierw zainstalować dwie biblioteki, aby najpierw sterować wyświetlaczem. Pobierz biblioteki Adafruit_SSD1306 i Adafruit-GFX z Github. Skopiuj pliki do folderu bibliotek. Zależy to od systemu operacyjnego:

  • System operacyjny Mac: / Users / Nazwa użytkownika / Documents / Arduino / libraries
  • Linux: / home / Nazwa użytkownika / Sketchbook
  • Windows: / Users / Arduino / libraries

Teraz prześlij szkic testowy. Iść do Plik > Przykłady > Adafruit SSD1306 > ssd1306_128x64_i2c. To powinno dać ci duży szkic zawierający dużo grafiki:

Jeśli nic się nie stanie po przesłaniu, odłącz i sprawdź dwa razy swoje połączenia. Jeśli przykładów nie ma w menu, może być konieczne zrestartowanie Arduino IDE.

Kod

Teraz czas na kod. Wyjaśnię każdy krok, więc przejdź do końca, jeśli chcesz po prostu uruchomić. To niezła ilość kodu, więc jeśli nie czujesz się pewnie, sprawdź 10 darmowych zasobów Naucz się kodować: 10 darmowych i fantastycznych zasobów online, aby doskonalić swoje umiejętności Naucz się kodować: 10 darmowych i fantastycznych zasobów online, aby doskonalić swoje Kodowanie umiejętności. Temat, którego wielu omija. Istnieje mnóstwo bezpłatnych zasobów i narzędzi, z których wszystkie są dostępne online. Na pewno możesz wziąć udział w kursach na ten temat w pobliskim…, aby nauczyć się kodować.

Zacznij od dołączenia niezbędnych bibliotek:

#include #include #include #include 

SPI i DRUT to dwie biblioteki Arduino do obsługi komunikacji I2C. Adafruit_GFX i Adafruit_SSD1306 to biblioteki, które wcześniej zainstalowałeś.

Następnie skonfiguruj wyświetlacz:

Wyświetlacz Adafruit_SSD1306 (4);

Następnie skonfiguruj wszystkie zmienne potrzebne do uruchomienia gry:

int rozdzielczość [2] = 128, 64, piłka [2] = 20, (rozdzielczość [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, SPEED = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = „R”, ballDirectionVerti = „S”; boolean inProgress = true;

Przechowują one wszystkie dane niezbędne do uruchomienia gry. Niektóre z nich przechowują położenie piłki, rozmiar ekranu, lokalizację gracza i tak dalej. Zwróć uwagę, jak niektóre z nich są const co oznacza, że ​​są stałe i nigdy się nie zmienią. To pozwala kompilatorowi Arduino nieco przyspieszyć.

Rozdzielczość ekranu i położenie kulki są przechowywane w tablice. Tablice to zbiory podobnych rzeczy, a dla piłki przechowuj współrzędne (X i Y). Dostęp do elementów w tablicach jest łatwy (nie dołączaj tego kodu do pliku):

rozdzielczość [1];

Gdy tablice zaczynają się od zera, zwróci to drugi element w tablicy rozdzielczości (64). Aktualizacja elementów jest jeszcze łatwiejsza (ponownie nie dołączaj tego kodu):

piłka [1] = 15;

Wewnątrz void setup (), skonfiguruj wyświetlacz:

void setup () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display (); 

Pierwszy wiersz informuje bibliotekę Adafruit, jakich wymiarów i protokołu komunikacyjnego używa Twój wyświetlacz (w tym przypadku, 128 x 64 i I2C). Druga linia (display.display ()) informuje ekran, aby pokazywał wszystko, co jest przechowywane w buforze (co jest niczym).

Utwórz dwie metody o nazwie drawBall i eraseBall:

void drawBall (int x, int y) display.drawCircle (x, y, ROZMIAR PIŁKI, BIAŁY);  void eraseBall (int x, int y) display.drawCircle (x, y, BALL_SIZE, BLACK); 

Te biorą x i y współrzędne piłki i narysuj ją na ekranie za pomocą drawCircle metoda z bibliotek wyświetlania. To używa stałej BALL_SIZE zdefiniowane wcześniej. Spróbuj to zmienić i zobacz, co się stanie. Ta metoda drawCircle akceptuje kolor pikseli - CZARNY lub BIAŁY. Ponieważ jest to wyświetlacz monochromatyczny (jeden kolor), biały odpowiada włączonemu pikselowi, a czarny wyłącza piksel.

Teraz utwórz metodę o nazwie moveAi:

void moveAi () eraseAiPaddle (aiPos); if (ball [1]> aiPos) ++ aiPos;  else if (ball [1] < aiPos)  --aiPos;  drawAiPaddle(aiPos); 

Ta metoda obsługuje przenoszenie Sztuczna inteligencja lub AI gracz. To dość prosty komputerowy przeciwnik - jeśli piłka znajduje się nad wiosłem, przesuń się w górę. Jest poniżej wiosła, zejdź w dół. Całkiem proste, ale działa dobrze. Używane są symbole przyrostu i zmniejszenia (++aiPos i -aiPos), aby dodać lub odjąć jedną z aiPosition. Możesz dodać lub odjąć większą liczbę, aby ruch AI był szybszy, a zatem trudniejszy do pokonania. Oto jak to zrobiłbyś:

aiPos + = 2;

I:

aiPos - = 2;

The Plus równa się i Minus jest równy znaki są skrótem do dodawania lub odejmowania dwóch od / do bieżącej wartości aiPos. Oto inny sposób, aby to zrobić:

aiPos = aiPos + 2;

i

aiPos = aiPos - 1;

Zauważ, jak ta metoda najpierw usuwa wiosło, a następnie rysuje go ponownie. Trzeba to zrobić w ten sposób. Gdyby narysowano nową pozycję wiosła, na ekranie byłyby dwie nakładające się łopatki.

The drawNet Metoda używa dwóch pętli do narysowania siatki:

void drawNet () for (int i = 0; i < (resolution[1] / WALL_WIDTH); ++i)  drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH);  

Wykorzystuje to WALL_WIDTH zmienne, aby ustawić jego rozmiar.

Utwórz metody o nazwie drawPixels i erasePixels. Podobnie jak w przypadku metod kulkowych, jedyną różnicą między tymi dwoma jest kolor pikseli:

void drawPixel (int posX, int posY, int Dimensions) for (int x = 0; x < dimensions; ++x)  for (int y = 0; y < dimensions; ++y)  display.drawPixel((posX + x), (posY + y), WHITE);    void erasePixel(int posX, int posY, int dimensions)  for (int x = 0; x < dimensions; ++x)  for (int y = 0; y < dimensions; ++y)  display.drawPixel((posX + x), (posY + y), BLACK);   

Ponownie, obie te metody używają dwóch dla pętle do narysowania grupy pikseli. Zamiast rysować każdy piksel za pomocą bibliotek drawPixel Metoda powoduje, że pętle rysują grupę pikseli na podstawie podanych wymiarów.

The drawScore Metoda korzysta z funkcji tekstowych biblioteki, aby zapisać odtwarzacz i wynik AI na ekranie. Są one przechowywane w playerScore i aiScore:

void drawScore () display.setTextSize (2); display.setTextColor (WHITE); display.setCursor (45, 0); display.println (playerScore); display.setCursor (75, 0); display.println (aiScore); 

Ta metoda ma również eraseScore odpowiednik, który ustawia piksele na czarne lub wyłączone.

Ostatnie cztery metody są bardzo podobne. Rysują i usuwają wiosła gracza i AI:

void erasePlayerPaddle (int row) erasePixel (0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel (0, wiersz - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, wiersz, PADDLE_WIDTH); erasePixel (0, wiersz + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, wiersz + (PADDLE_WIDTH + 2), PADDLE_WIDTH); 

Zauważ, jak nazywają erasePixel Metoda tworzenia wcześniej. Te metody rysują i usuwają odpowiednią wiosło.

W głównej pętli jest nieco więcej logiki. Oto cały kod:

#include #include #include #include Adafruit_SSD1306 display (4); int rozdzielczość [2] = 128, 64, piłka [2] = 20, (rozdzielczość [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, SPEED = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = „R”, ballDirectionVerti = „S”; boolean inProgress = true; void setup () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display ();  void loop () if (aiScore> 9 || playerScore> 9) // sprawdź stan gry inProgress = false;  if (inProgress) eraseScore (); eraseBall (piłka [0], piłka [1]); if (ballDirectionVerti == 'U') // przesuń piłkę w górę po przekątnej piłkę [1] = piłka [1] - SPEED;  if (ballDirectionVerti == 'D') // przesuń piłkę w dół po przekątnej piłki [1] = piłka [1] + SPEED;  if (ball [1] = rozdzielczość [1]) // odbija piłkę od dolnej piłkiDirectionVerti = 'U';  if (ballDirectionHori == 'R') ball [0] = ball [0] + SPEED; // porusz piłkę jeśli (piłka [0]> = (rozdzielczość [0] - 6)) // piłka jest na krawędzi AI ekranu, jeśli ((aiPos + 12)> = piłka [1] i& (aiPos - 12) (aiPos + 4)) // odbija piłkę w dół ballDirectionVerti = „D”;  else if (ball [1] < (aiPos - 4))  // deflect ball up ballDirectionVerti = 'U';  else  // deflect ball straight ballDirectionVerti = 'S';  // change ball direction ballDirectionHori = 'L';  else  // GOAL! ball[0] = 6; // move ball to other side of screen ballDirectionVerti = 'S'; // reset ball to straight travel ball[1] = resolution[1] / 2; // move ball to middle of screen ++playerScore; // increase player score    if (ballDirectionHori == 'L')  ball[0] = ball[0] - SPEED; // move ball if (ball[0] = ball[1] && (playerPos - 12)  (playerPos + 4))  // deflect ball down ballDirectionVerti = 'D';  else if (ball[1]  playerScore)  display.println("YOU LOSE!");  else if (playerScore > aiScore) display.println („YOU WIN!”);  display.display ();  void moveAi () // przenieś wiosło AI eraseAiPaddle (aiPos); if (ball [1]> aiPos) ++ aiPos;  else if (ball [1] < aiPos)  --aiPos;  drawAiPaddle(aiPos);  void drawScore()  // draw AI and player scores display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(45, 0); display.println(playerScore); display.setCursor(75, 0); display.println(aiScore);  void eraseScore()  // erase AI and player scores display.setTextSize(2); display.setTextColor(BLACK); display.setCursor(45, 0); display.println(playerScore); display.setCursor(75, 0); display.println(aiScore);  void drawNet()  for (int i = 0; i < (resolution[1] / WALL_WIDTH); ++i)  drawPixel(((resolution[0] / 2) - 1), i * (WALL_WIDTH) + (WALL_WIDTH * i), WALL_WIDTH);   void drawPixel(int posX, int posY, int dimensions)  // draw group of pixels for (int x = 0; x < dimensions; ++x)  for (int y = 0; y < dimensions; ++y)  display.drawPixel((posX + x), (posY + y), WHITE);    void erasePixel(int posX, int posY, int dimensions)  // erase group of pixels for (int x = 0; x < dimensions; ++x)  for (int y = 0; y < dimensions; ++y)  display.drawPixel((posX + x), (posY + y), BLACK);    void erasePlayerPaddle(int row)  erasePixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(0, row, PADDLE_WIDTH); erasePixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH);  void drawPlayerPaddle(int row)  drawPixel(0, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); drawPixel(0, row - PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(0, row, PADDLE_WIDTH); drawPixel(0, row + PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(0, row + (PADDLE_WIDTH + 2), PADDLE_WIDTH);  void drawAiPaddle(int row)  int column = resolution[0] - PADDLE_WIDTH; drawPixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); drawPixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(column, row, PADDLE_WIDTH); drawPixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH); drawPixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH);  void eraseAiPaddle(int row)  int column = resolution[0] - PADDLE_WIDTH; erasePixel(column, row - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel(column, row - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(column, row, PADDLE_WIDTH); erasePixel(column, row + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel(column, row + (PADDLE_WIDTH * 2), PADDLE_WIDTH);  void drawBall(int x, int y)  display.drawCircle(x, y, BALL_SIZE, WHITE);  void eraseBall(int x, int y)  display.drawCircle(x, y, BALL_SIZE, BLACK); 

Oto, co kończysz:

Gdy masz pewność co do kodu, możesz wprowadzić wiele modyfikacji:

  • Dodaj menu poziomów trudności (zmień AI i prędkość piłki).
  • Dodaj losowy ruch do piłki lub AI.
  • Dodaj kolejną pulę dla dwóch graczy.
  • Dodaj przycisk pauzy.

Teraz spójrz na te retro projekty gier Pi Zero 5 projektów gier retro z Raspberry Pi Zero 5 projektów gier retro z Raspberry Pi Zero Raspberry Pi Zero podbiło świat DIY i homebrew, umożliwiając przegląd starych projektów i inspirujących nowoprzybyłych, szczególnie w gorących umysłach fanów gier retro. .

Czy kodowałeś Ponga za pomocą tego kodu? Jakie modyfikacje wprowadziłeś? Daj mi znać w komentarzach poniżej, chciałbym wydać się trochę zdjęć!




Jeszcze bez komentarzy

O nowoczesnej technologii, prostej i niedrogiej.
Twój przewodnik w świecie nowoczesnych technologii. Dowiedz się, jak korzystać z technologii i gadżetów, które nas otaczają każdego dnia i dowiedz się, jak odkrywać ciekawe rzeczy w Internecie.