Arduino Retro igranje s OLED zaslonom

  • William Charles
  • 0
  • 2822
  • 693
Oglas

Jeste li se ikad zapitali koliko je potrebno da napišete svoje vlastite retro igre? Kako je Pong lako kodirati Arduino? Pridružite mi se dok vam pokazujem kako da napravite Arduino mini retro igraću konzolu i kako Pong odmah ispočetka. Evo krajnjeg rezultata:

Izgradite plan

Ovo je prilično jednostavan krug. potenciometar (lonac) će kontrolirati igru, a OLED zaslon će pokretati Arduino. Ovo će se proizvoditi na ploči, no možda biste željeli da to bude stalan krug i instalirate ga u kovčeg. Pisali smo o tome kako ponovo stvoriti pong kako obnoviti klasičnu igru ​​pong pomoću Arduino-a. Kako ponovno stvoriti klasičnu igru ​​pong pomoću Arduino pong-a prva je videoigrica koja je stigla na masovno tržište. Prvi put u povijesti pojam "video igre" uveden je u obiteljski dom, zahvaljujući Atari 2600 - ... prije, no danas ću vam pokazati kako napisati kôd od nule i razbijati svaki dio.

Što trebaš

Evo što vam treba:

  • 1 x Arduino (bilo koji model)
  • Potenciometar 1 x 10k
  • 1 x 0,96 "I2C OLED zaslon
  • 1 x krušna ploča
  • Različite muške> muške žice za spajanje

Bilo koji Arduino bi trebao raditi, pa pogledajte naš vodič za kupnju Arduino Vodič za kupnju: Koju ploču trebate nabaviti? Vodič za kupnju Arduinoa: Koji odbor trebate dobiti? Postoji toliko mnogo različitih Arduino ploča vani da bi vam bilo oprošteno što ste zbunjeni. Koje biste trebali kupiti za svoj projekt? Pomozite nam s ovim vodičem za kupovinu Arduino-a! ako niste sigurni koji model kupiti.

Ovi OLED zasloni su vrlo cool. Obično se mogu kupiti u bijeloj, plavoj, žutoj ili mješavini ove tri. Oni postoje u punoj boji, no to dodaje još jednu razinu složenosti i troškova ovog projekta.

Krug

Ovo je prilično jednostavan krug. Ako nemate puno iskustva s Arduinom, pogledajte ove projekte za početnike 15 Veliki Arduino projekti za početnike 15 Veliki Arduino projekti za početnike Zanimaju Arduino projekti, ali niste sigurni gdje započeti? Ovi početnički projekti naučit će vas kako započeti. prvi.

Evo ga:

Gledajući prednju stranu lonca, spojite lijevu iglu na +5V a desni pin na tlo. Spojite srednji pin na analogni pin 0 (A0).

OLED zaslon povezan je putem I2C protokola. Spojiti VCC i GND do Arduina +5V i tlo. Spojiti SCL do analogna petorka (A5). Spojiti SDA do analogni 4 (A4). Razlog zašto je ovo spojeno na analogne igle je jednostavan; ti pinovi sadrže sklop potreban za I2C protokol. Provjerite jesu li ti spojeni pravilno i nisu prekriženi. Točne iglice ovisit će ovisno o modelu, ali A4 i A5 koriste se na Nano i Uno. Provjerite dokumentaciju knjižnice žica za svoj model ako ne koristite Arduino ili Nano.

Pot test

Prenesite ovaj testni kôd (obavezno odaberite ispravnu ploču i priključak s alat > Odbor i alat > Luka izbornika):

void setup () // stavi ovdje svoj instalacijski kôd, pokreni se jednom: Serial.begin (9600); // setup serial void petlja () // stavi ovdje svoj glavni kôd, radi ponovnog pokretanja: Serial.println (analogRead (A0)); // ispisati vrijednost iz kašnjenja u pot (500); 

Sada otvorite serijski monitor (Gore desno > Serijski monitor) i okrenite lonac. Trebali biste vidjeti vrijednost prikazanu na serijskom monitoru. Potpuno treba biti u smjeru suprotnom od kazaljke na satu nula, i potpuno bi trebao biti u smjeru kazaljke na satu 1023:

To ćete naknadno prilagoditi, ali za sada je to u redu. Ako se ništa ne dogodi ili se vrijednost promijeni bez da išta poduzmete, isključite i dvaput provjerite krug.

OLED test

OLED zaslon je malo složeniji za konfiguriranje. Za pokretanje zaslona prvo morate instalirati dvije knjižnice. Preuzmite knjižnice Adafruit_SSD1306 i Adafruit-GFX s Github-a. Kopirajte datoteke u mapu knjižnica. To se razlikuje ovisno o vašem operativnom sustavu:

  • Mac OS: / Users / Ime / Dokumenti / Arduino / knjižnice
  • Linux: / Home / ime / crtanje
  • Windows: / Users / Arduino / knjižnice

Sada prenesite probnu skicu. Ići Datoteka > Primjeri > Adafruit SSD1306 > ssd1306_128x64_i2c. Ovo bi vam trebalo dati veliku skicu koja sadrži puno grafike:

Ako se ništa ne dogodi nakon prijenosa, isključite i dvaput provjerite veze. Ako primjeri nisu u izbornicima, možda ćete trebati ponovo pokrenuti Arduino IDE.

Kod

Sada je vrijeme za šifru. Objasnit ću vam svaki korak, pa preskočite do kraja ako ga želite samo pokrenuti. Ovo je prilična količina koda, pa ako se ne osjećate samopouzdano, pogledajte ovih 10 besplatnih izvora Saznajte kako kodirati: 10 besplatnih i fantastičnih internetskih resursa za ojačavanje vaših vještina Nauči se šifrirati: 10 besplatnih i fantastičnih internetskih resursa za oživljavanje Kodiranje vještina Tema koju mnogi izbjegavaju. Postoji obilje besplatnih resursa i alata, a svi su dostupni na mreži. Sigurno biste mogli održati neke tečajeve o toj temi u blizini ... da biste naučili šifrirati.

Započnite uključivanjem potrebnih knjižnica:

#include #include #include #include 

SPI i ŽICA su dvije Arduino knjižnice za upravljanje I2C komunikacijom. Adafruit_GFX i Adafruit_SSD1306 jesu knjižnice koje ste prethodno instalirali.

Zatim konfigurirajte zaslon:

Adafruit_SSD1306 zaslon (4);

Zatim postavite sve varijable potrebne za pokretanje igre:

int rezolucija [2] = 128, 64, kugla [2] = 20, (rezolucija [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'; boole inProgress = istina;

One pohranjuju sve podatke potrebne za pokretanje igre. Neki od njih pohranjuju mjesto lopte, veličinu zaslona, ​​lokaciju igrača i tako dalje. Primjetite kako su neki od ovih const što znači da su stalni i nikad se neće promijeniti. To omogućava da Arduino prevoditelj malo ubrza stvari.

Rezolucija zaslona i mjesto lopte su pohranjeni u nizovi. Nizovi su zbirka sličnih stvari, a za loptu spremite koordinate (x i Y). Pristup elementima u nizovima je jednostavan (ne uključuju ovaj kôd u vašu datoteku):

Rezolucija [1];

Kako nizovi počinju od nule, to će vratiti drugi element u rezolucijskom nizu (64). Ažuriranje elemenata je još lakše (opet, ne uključujejte taj kôd):

lopta [1] = 15;

U poništavanje (), konfigurirajte zaslon:

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

Prvi redak govori knjižnici Adafruit koje dimenzije i komunikacijski protokol koristi vaš zaslon (u ovom slučaju, 128 x 64 i I2C). Drugi redak (display.display ()) poručuje zaslonu da pokaže sve što je pohranjeno u međuspremniku (što nije ništa).

Stvorite dvije metode nazvane drawBall i eraseBall:

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); 

Ovi uzimaju x i y koordinate lopte i nacrtajte je na ekranu pomoću drawCircle metoda iz knjižnica prikaza. Za to se koristi konstanta BALL_SIZE definirano ranije. Pokušajte to promijeniti i pogledajte što će se dogoditi. Ova metoda drawCircle prihvaća boju piksela - CRNO ili BIJELA. Kako je ovo jednobojni prikaz (jedna boja), bijela se izjednačava s uključenim pikselom, a crna isključuje piksel.

Sada stvorite metodu koja se zove moveAi:

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

Ova metoda obrađuje premještanje Umjetna inteligencija ili AI igrač. Ovo je vrlo jednostavan protivnik računala - ako je lopta iznad vesla, pomaknite se prema gore. To je ispod vesla, pomakni se dolje. Sasvim jednostavno, ali djeluje dobro. Koriste se simboli prirasta i smanjenja (++aiPos i -aiPos) da biste dodali ili oduzeli jedan od aiPosicije. Možete dodati ili oduzeti veći broj da bi se AI kretao brže, a samim tim i teže pobijedio. Evo kako biste to učinili:

aiPos + = 2;

I:

aiPos - = 2;

Plus jednako i Minus jednak znakovi su skraćenica za dodavanje ili oduzimanje dva od / do trenutne vrijednosti aiPos. Evo još jednog načina da to učinite:

aiPos = aiPos + 2;

i

aiPos = aiPos - 1;

Primjetite kako ova metoda prvo briše veslo, a zatim ga ponovno crta. Ovo se mora učiniti ovako. Ako bi se crtao novi položaj vesla, na zaslonu bi se nalazila dva vesla koja se preklapaju.

drawNet koristi dvije petlje za crtanje mreže:

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);  

Ovo koristi WALL_WIDTH varijable za postavljanje njegove veličine.

Stvorite metode nazvane drawPixels i erasePixels. Baš kao i metode lopte, jedina razlika između ove dvije je boja piksela:

void drawPixel (int posX, int posY, int dimenzije) 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);   

Opet, obje ove metode koriste dvije za petlje za crtanje grupe piksela. Umjesto da crtamo svaki piksel pomoću knjižnica drawPixel metoda, petlje crtaju grupu piksela na temelju zadanih dimenzija.

drawScore metoda koristi tekstualne značajke biblioteke za pisanje igrača i AI ocjenu na zaslon. Oni su pohranjeni u playerScore i aiScore:

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

Ova metoda također ima eraseScore protuvrijednost, koja postavlja piksele na crno ili isključeno.

Posljednje četiri metode vrlo su slične. Oni crtaju i brišu igrače i AI vesla:

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

Primijetite kako ih nazivaju erasePixel metoda kreirati ranije. Ove metode crtaju i brišu odgovarajuće veslo.

U glavnoj petlji ima malo više logike. Evo cijelog koda:

#include #include #include #include Adafruit_SSD1306 zaslon (4); int rezolucija [2] = 128, 64, kugla [2] = 20, (rezolucija [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'; boole inProgress = istina; void setup () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display ();  void loop () if (aiScore> 9 || playerScore> 9) // provjeri stanje u igriProgress = false;  if (napredak) eraseScore (); eraseBall (lopta [0], kugla [1]); ako (ballDirectionVerti == 'U') // pomicanje lopte prema dijagonalno loptu [1] = lopta [1] - SPEED;  if (ballDirectionVerti == 'D') // pomicanje lopte dijagonalno lopta [1] = lopta [1] + SPEED;  if (lopta [1] = rezolucija [1]) // odskoči lopta od donje lopteDirectionVerti = 'U';  if (ballDirectionHori == 'R') lopta [0] = lopta [0] + SPEED; // pomaknite loptu ako je (lopta [0]> = (rezolucija [0] - 6)) // lopta je na AI rubu zaslona ako je ((aiPos + 12)> = lopta [1] && (aiPos - 12) (aiPos + 4)) // odbiti lopticu prema doljeDirectionVerti = 'D';  else if (lopta [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 ("DOBITIŠ!");  display.display ();  void moveAi () // premjestiti AI veslo eraseAiPaddle (aiPos); ako (lopta [1]> aiPos) ++ aiPos;  else if (lopta [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); 

Evo što završite:

Jednom kada ste sigurni da je kôd, možete izvršiti brojne izmjene:

  • Dodajte izbornik za razine težine (promijenite AI i brzinu lopte).
  • Dodajte neki slučajni pokret u loptu ili AI.
  • Dodajte još jedan lonac za dva igrača.
  • Dodajte gumb za zaustavljanje.

Sada pogledajte ove retro igrane Pi Zero projekte 5 Retro igraćih projekata s Raspberry Pi Zero 5 Retro igrališta s Raspberry Pi Zero Raspberry Pi Zero je olujom uzeo DIY i domaći svijet, omogućujući tako reviziju starih projekata i nadahnjuje pridošlice, posebno u užarenim umovima ljubitelja retro igara. .

Jeste li kodirali Pong koristeći ovaj kod? Koje ste izmjene napravili? Javite mi u komentarima ispod, volio bih da izgledaju neke slike!




Još ne komentari

O modernoj tehnologiji, jednostavnoj i pristupačnoj.
Vaš vodič u svijetu moderne tehnologije. Naučite kako koristiti tehnologije i uređaje koji nas okružuju svaki dan i naučite kako otkriti zanimljivosti na Internetu.