OLED Ekranlı Arduino Retro Oyun

  • Joseph Goodman
  • 0
  • 3096
  • 191
reklâm

Kendi retro oyunlarınızı yazmak için ne kadar çalışmanız gerektiğini hiç merak ettiniz mi? Pong, Arduino'yu kodlamak için ne kadar kolay? Arduino destekli mini retro oyun konsolu yapmayı ve Pong'u sıfırdan nasıl kodlayacağınızı size gösterdiğimde bana katılın. İşte sonuç:

Plan Oluştur

Bu oldukça basit bir devredir. bir potansiyometre (pot) oyunu kontrol edecek ve bir OLED ekran Arduino tarafından kullanılacak. Bu, bir breadboard üzerinde üretilecektir, ancak bunu kalıcı bir devre haline getirmek ve bir durumda monte etmek isteyebilirsiniz. Arduino'yu Kullanarak Klasik Pong Oyununu Yeniden Yaratma Arduino'yu Kullanarak Klasik Pong Oyununu Yeniden Oluşturma hakkında yazdık. Arduino Pong'u Kullanarak Klasik Pong Oyununu ilk kez kitlesel pazara ulaştı. Tarihte ilk kez, Atari 2600 - sayesinde, aile evine bir "video oyunu" kavramı getirildi -… daha önce, ancak bugün size kodu sıfırdan nasıl yazacağınızı ve her birini nasıl yıkacağınızı göstereceğim Bölüm.

Neye ihtiyacın var

İşte ihtiyacın olan şey:

  • 1 x Arduino (herhangi bir model)
  • 1 x 10k Potansiyometre
  • 1 x 0.96 "I2C OLED Ekran
  • 1 x Breadboard
  • Çeşitli erkek> erkek bağlantı telleri

Herhangi bir Arduino çalışmalıdır, bu yüzden satın alma kılavuzumuza bakın Arduino Satın Alma Rehberi: Hangi Kurulu Almalısınız? Arduino Satın Alma Rehberi: Hangi Kurulu Almalısınız? Dışarıda pek çok farklı Arduino tahtası var, kafanız karıştığı için affedilirsiniz. Projeniz için hangisini satın almalısınız? Bu Arduino satın alma rehberi ile yardım edelim! hangi modelden satın alınacağından emin değilseniz.

Bu OLED ekranlar çok havalı. Genellikle beyaz, mavi, sarı veya üçünün karışımı halinde satın alınabilirler. Tam renkli olarak varlar, ancak bunlar bu projenin karmaşıklığına ve maliyetine başka bir seviye katıyor..

Devre

Bu oldukça basit bir devredir. Arduino ile ilgili fazla tecrübeniz yoksa, bu yeni başlayanlar projelerine göz atın 15 Yeni Başlayanlar İçin Büyük Arduino Projeleri 15 Yeni Başlayanlar için Büyük Arduino Projeleri Arduino projelerine ilgi duyuyor ancak nereden başlayacağınızdan emin değil misiniz? Bu başlangıç ​​projeleri size nasıl başlanacağını öğretecektir. ilk.

İşte burada:

Tencerenin ön tarafına bakarak, sol pimi +5V ve doğru pin zemin. Orta pimi analog pim 0 (A0).

OLED ekranı, I2C protokolü kullanılarak bağlanır. bağlamak VCC ve GND Arduino'ya +5V ve zemin. bağlamak SCL için analog beş (A5). bağlamak SDA için analog 4 (A4). Bunun analog pimlere bağlanma nedeni basit; bu pinler, I2C Protokolü için gerekli devreleri içerir. Bunların doğru bağlandığından ve çapraz olmadıklarından emin olun. Kesin pimler modele göre değişir, ancak Nano ve Uno'da A4 ve A5 kullanılır. Arduino veya Nano kullanmıyorsanız, modeliniz için Wire kitaplığının belgelerine bakın.

Pot Testi

Bu test kodunu yükleyin (doğru pano ve bağlantı noktasını seçtiğinizden emin olun.). Araçlar > Yazı tahtası ve Araçlar > Liman menüler):

void setup () // bir kez çalıştırmak için kurulum kodunuzu buraya yerleştirin: Serial.begin (9600); // setup serial void loop () // tekrar tekrar çalıştırmak için ana kodunuzu buraya yerleştirin: Serial.println (analogRead (A0)); // değeri pot gecikmesinden yazdırın (500); 

Şimdi seri monitörü aç (Sağ üst > Seri monitör) ve kabı çevirin. Seri monitörde görüntülenen değeri görmelisiniz. Tamamen saat yönünün tersine sıfır, ve tamamen saat yönünde olmalıdır 1023:

Bunu daha sonra ayarlayacaksın, ama şimdilik sorun değil. Hiçbir şey olmazsa veya değer siz bir şey yapmadan değişirse, devreyi kesin ve iki kez kontrol edin.

OLED Testi

OLED ekranı yapılandırmak için biraz daha karmaşık. Önce ekranı görüntüleyebilmek için iki kitaplık yüklemeniz gerekir. Github'dan Adafruit_SSD1306 ve Adafruit-GFX kütüphanelerini indirin. Dosyaları kütüphaneler klasörünüze kopyalayın. Bu işletim sisteminize bağlı olarak değişir:

  • Mac os işletim sistemi: / Users / kullanıcı adı / Belgeler / Arduino / kütüphaneler
  • Linux: / Home / kullanıcı adı / Sketchbook
  • pencereler: / Users / Arduino / kütüphaneler

Şimdi bir test taslağı yükleyin. Git Dosya > Örnekler > Adafruit SSD1306 > ssd1306_128x64_i2c. Bu size çok sayıda grafik içeren büyük bir çizim sunmalıdır:

Yüklemeden sonra bir şey olmazsa, bağlantılarınızı kesin ve iki kez kontrol edin. Örnekler menülerde değilse, Arduino IDE'nizi yeniden başlatmanız gerekebilir.

Kod

Şimdi kod zamanı. Her adımı açıklayacağım, bu yüzden sadece çalışmasını istiyorsanız, sonuna kadar atlayın. Bu oldukça fazla miktarda bir koddur, bu yüzden kendinize güvende hissetmiyorsanız, bu 10 ücretsiz kaynağa göz atın Kodu Öğrenin: 10 Ücretsiz Ve Harika Çevrimiçi Kaynak Becerilerinizi Geliştirmek İçin Kodu Öğrenin: 10 Ücretsiz Ve Harika Çevrimiçi Kaynaklarınızı Öğrenin Beceri Kodlaması. Birçok kişi tarafından kaçınılan bir konu. Tamamı çevrimiçi olarak erişilebilen çok sayıda ücretsiz kaynak ve araç vardır. Kodlamayı öğrenmek için yakındaki bir konuyla ilgili bazı kurslar alabileceğinizden emin olun..

Gerekli kütüphaneleri ekleyerek başlayın:

#include #include #include #include 

SPI ve TEL I2C iletişimini yönetmek için kullanılan iki Arduino kütüphanesidir.. Adafruit_GFX ve Adafruit_SSD1306 daha önce kurduğunuz kütüphaneler.

Sonra, ekranı yapılandırın:

Adafruit_SSD1306 ekranı (4);

Ardından oyunu çalıştırmak için gereken tüm değişkenleri ayarlayın:

int çözünürlük [2] = 128, 64, top [2] = 20, (çözünürlük [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, HIZ = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = 'R', ballDirectionVerti = 'S'; boolean inProgress = true;

Bunlar oyunu çalıştırmak için gerekli tüm verileri depolar. Bunlardan bazıları topun konumunu, ekranın boyutunu, oynatıcının konumunu vb. Depolar. Bunlardan bazılarının ne olduğuna dikkat edin const sabit oldukları ve asla değişmeyecekleri anlamına gelir. Bu Arduino derleyicisinin işleri hızlandırmasını sağlar.

Ekran çözünürlüğü ve top konumu diziler. Diziler benzer şeylerin koleksiyonlarıdır ve top için koordinatları saklar (X ve Y). Dizilerdeki öğelere erişmek kolaydır (bu kodu dosyanıza eklemeyin):

çözünürlük [1];

Diziler sıfırdan başladığında, bu ikinci öğeyi çözünürlük dizisinde döndürür (64). Öğelerin güncellenmesi daha da kolaydır (yine, bu kodu eklemeyin):

top [1] = 15;

içeride geçersiz kurulum (), ekranı yapılandırın:

geçersiz kurulum () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display (); 

İlk satır Adafruit kütüphanesine ekranınızın hangi boyutları ve iletişim protokolünü kullandığını söyler (bu durumda, 128 x 64 ve I2C). İkinci satır (display.display ()), ekrana tamponda neyin saklandığını göstermesini söyler (bu hiçbir şey değildir).

Denilen iki yöntem oluşturun drawBall ve 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); 

Bunlar almak x ve y topun koordinatlarını ve ekranda kullanarak onu çizmek drawCircle ekran kitaplıklarından yöntem. Bu sabit kullanır BALL_SIZE daha önce tanımlanmış. Bunu değiştirmeyi deneyin ve ne olduğunu görün. Bu drawCircle yöntemi bir piksel rengini kabul eder - SİYAH veya BEYAZ. Bu tek renkli bir ekran (tek renk) olduğu için beyaz, bir piksele açık olana eşittir ve siyah, pikseli kapatır.

Şimdi denilen bir yöntem oluşturun moveAi:

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

Bu yöntem, hareketli hareket eder Yapay zeka veya AI oyuncu. Bu oldukça basit bir bilgisayar rakibi - Eğer top raketin üstünde ise, yukarı hareket ettirin. Raketin altında, aşağı doğru hareket edin. Oldukça basit, ama iyi çalışıyor. Artış ve azalış sembolleri kullanılır (++aiPos ve -aiPosaiPosition'dan bir tane eklemek veya çıkarmak. AI'yı daha hızlı hareket ettirmek için daha büyük bir sayı ekleyebilir veya çıkarabilirsiniz, bu nedenle atması daha zor olabilir. İşte bunu nasıl yaparsın:

aiPos + = 2;

Ve:

aiPos - = 2;

Artı Eşittir ve Eksi Eşittir işaretler, aiPos'un mevcut değerine / değerinden iki tane eklemek veya çıkarmak için kısa yoldur. İşte bunu yapmanın başka bir yolu:

aiPos = aiPos + 2;

ve

aiPos = aiPos - 1;

Bu yöntemin ilk önce raketi nasıl sildiğine ve sonra tekrar çizdiğine dikkat edin. Bu böyle yapılmalı. Raketin yeni konumu çizildiyse, ekranda iki üst üste binen kürek olacaktı.

DrawNet yöntemi net çekmek için iki döngü kullanır:

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

Bu kullanır WALL_WIDTH boyutunu ayarlamak için değişkenler.

Denilen yöntemleri oluşturun drawPixels ve erasePixels. Top yöntemlerinde olduğu gibi, bu ikisi arasındaki tek fark piksellerin rengidir:

boşluk drawPixel (int posX, int posY, int boyutlar) için (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);   

Yine, her iki yöntem de iki tane kullanır. için bir grup piksel çizmek için döngüler. Kütüphaneleri kullanarak her pikseli çizmek zorunda kalmak yerine drawPixel yöntemi, döngüler verilen boyutlara göre bir grup piksel çizer..

drawScore yöntem, oynatıcıyı ve AI puanını ekrana yazmak için kütüphanenin metin özelliklerini kullanır. Bunlar içinde saklanır playerScore ve aiScore:

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

Bu yöntem aynı zamanda bir eraseScore pikselleri siyah veya kapalı olarak ayarlayan meslektaşı.

Son dört yöntem çok benzer. Oynatıcı ve AI küreklerini çizer ve siler:

void erasePlayerPaddle (int satır) erasePixel (0, satır - (PADDLE_WIDTH * 2), PADDLE_WIDTH); erasePixel (0, satır - PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, satır, PADDLE_WIDTH); erasePixel (0, satır + PADDLE_WIDTH, PADDLE_WIDTH); erasePixel (0, satır + (PADDLE_WIDTH + 2), PADDLE_WIDTH); 

Nasıl çağırdıklarına dikkat edin. erasePixel yöntem daha önce oluştur. Bu yöntemler uygun raketi çizer ve siler.

Ana döngüde biraz daha mantık var. İşte bütün kod:

#include #include #include #include Adafruit_SSD1306 görüntüleme (4); int çözünürlük [2] = 128, 64, top [2] = 20, (çözünürlük [1] / 2); const int PIXEL_SIZE = 8, WALL_WIDTH = 4, PADDLE_WIDTH = 4, BALL_SIZE = 4, HIZ = 3; int playerScore = 0, aiScore = 0, playerPos = 0, aiPos = 0; char ballDirectionHori = 'R', ballDirectionVerti = 'S'; boolean inProgress = true; geçersiz kurulum () display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.display ();  void loop () if (aiScore> 9 || playerScore> 9) // Oyunun durumunu kontrol et Progress = false;  if (devam ediyor) eraseScore (); eraseBall (top [0], top [1]); if (ballDirectionVerti == 'U') // topu çapraz olarak top yukarı oynat [1] = top [1] - HIZ;  if (ballDirectionVerti == 'D') // topu çapraz olarak aşağı doğru hareket ettirin [1] = top [1] + HIZ;  if (ball [1] = özünürlük [1]) // topu alttan sektirerek toplayınDirectionVerti = 'U';  if (ballDirectionHori == 'R') top [0] = top [0] + HIZ; // eğer topu hareket ettir ((top [0]> = (çözünürlük [0] - 6)) // top ekranın AI kenarındaysa ((aiPos + 12)> = top [1] && (aiPos - 12) (aiPos + 4)) // topu yere doğru saptırmakDirectionVerti = 'D';  else eğer (top [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 ("SİZ KAZANIN!");  display.display ();  void moveAi () // AI paddle'ı hareket ettir eraseAiPaddle (aiPos); if (ball [1]> aiPos) ++ aiPos;  else eğer (top [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); 

İşte neyin peşinde olduğun:

Koddan emin olduğunuzda, yapabileceğiniz çok sayıda değişiklik var:

  • Zorluk seviyeleri için bir menü ekle (AI ve top hızını değiştir).
  • Topa veya AI'ya rasgele hareket ekleme.
  • İki oyuncu için başka pot ekle.
  • Duraklat düğmesi ekle.

Şimdi bu retro oyunlara göz atın Pi Zero projeleri Ahududu Pi Zero ile 5 Retro Oyun Projesi Ahududu Pi Zero ile 5 Retro Oyun Projesi Ahududu Pi Zero, DIY ve homebrew dünyasını fırtına ile ele geçirdi ve eski projelerin revize edilmesini mümkün kıldı ve özellikle yeni oyun meraklılarının ateşli zihninde yeni gelenlere ilham vermek. .

Bu kodu kullanarak Pong'u kodladın mı? Hangi değişiklikleri yaptınız? Aşağıdaki yorumlarda bana haber verin, bazı resimler görünmesini isterim!




Henüz no comments

Modern teknoloji hakkında basit ve uygun fiyatlı.
Modern teknoloji dünyasında rehberiniz. Her gün bizi çevreleyen teknolojileri ve araçları nasıl kullanacağınızı ve Internet'te ilginç şeyleri nasıl keşfedeceğinizi öğrenin.