Başa dön
arduino oyun yapımı projeleri

Arduino LCD Ekran ile Oyun Yapımı – Flappy Bird

Merhaba arkadaşlar, bu yazımız da birlikte Arduino oyun yapımı “Flappy Bird” benzeri “Birduino” yapacağız 🙂 Arduino lcd ekran ile oyun yapımı projeleri, akıllı telefonlar için popüler bu oyunun da yapılabileceğini göstermiş oldu. Projenin nasıl çalıştığını aşağıdaki videoyu izleyerek ve aşağıdaki yazılı metni okuyarak öğrenebilirsiniz.

Arduino LCD Ekran ile Oyun Yapımı Projeleri – Birduino


Oyun oldukça basit ama ciddi bağımlılık yapabilir:) Dokunmatik ekranı kullanarak kuşu kontrol ediyoruz ve ilerledikçe hızlanan hareketli direklerin arasından, altından, üstünden geçmeye çalışıyoruz. Ayrıca, güç kesilse bile oyun en yüksek skorunuzu kaydedebilir.

 

Arduino TFT Eğitimi TFT Dokunmatik Ekranların bir Arduino ile nasıl kullanılacağını detaylı olarak öğrenmeniz için inceleyebilirsiniz. Şimdi, önceki yazılarımız da olduğu gibi, Arduino Oyun yapımı projesi arkasındaki kodlara adım adım göz atalım.

Arduino Zıplama Oyunu Yapımı Kaynak kodu


Kod biraz uzun olduğu için ve daha iyi anlaşılması adına programın kaynak kodunu her bölümün açıklamasını içeren bölümlere kaydedeceğiz. Ve bu yazının sonunda kaynak kodun tamamını bulacaksınız.

Arduino Flappy Bird Birduino Oyunu Projesi için Henning Karlsen tarafından hazırlanan UTFT ve URTouch kütüphanelerini kullanacağız. Bu kütüphaneleri indirmek için isimlerine tıklayabilirsiniz. Ayrıca EEPROM kütüphanesinde en yüksek oyun skorunu saklamak için EEPROM kütüphanesini kullanacağız. EEPROM, kart kapalıyken bile veri depolayabilen bir hafızadır.

 

Kütüphaneleri ekledikten sonra, UTFT ve URTouch nesnelerini açmamız ve oyun için gerekli değişkenleri tanımlamamız gerekir. Kurulum bölümünde, ekranı ve dokunmayı başlatmamız, EEPROM’dan en yüksek puanı okumamız ve oyunu startateGame () özel işlevini kullanarak başlatmamız gerekiyor.

 #include <UTFT.h> 
#include <URTouch.h>
#include <EEPROM.h>
//==== Creating Objects
UTFT    myGLCD(SSD1289,38,39,40,41); //Parameters should be adjusted to your Display/Schield model
URTouch  myTouch( 6, 5, 4, 3, 2);
//==== Defining Fonts
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern unsigned int bird01[0x41A]; // Bird Bitmap
int x, y; // Variables for the coordinates where the display has been pressed
// Floppy Bird
int xP = 319;
int yP = 100;
int yB = 50;
int movingRate = 3;
int fallRateInt = 0;
float fallRate = 0;
int score = 0;
int lastSpeedUpScore = 0;
int highestScore;
boolean screenPressed = false;
boolean gameStarted = false;
void setup() {
  // Initiate display
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myTouch.InitTouch();
  myTouch.setPrecision(PREC_MEDIUM);
  
  highestScore = EEPROM.read(0); // Read the highest score from the EEPROM
  
  initiateGame(); // Initiate the game
}

startateGame () özel işlevi ile oyunun başlangıcını oluşturacağız. Önce ekranı temizlememiz, sonra mavi arka planı çizmemiz, alt bölümü çizmemiz, metni eklememiz ve kuşu çizmek için drawBird () özel işlevini çağırmamız gerekmektedir. Bundan sonra, ekrana dokunana kadar oyunun başlamasını önleyen bir süre döngüsüne ihtiyacımız var. Yani biz bu durumdayken, sağ üst köşeye basarsak, en yüksek puanı sıfıra ayarlayabiliriz ve ekranda başka bir yere basarsak süre döngüsünden çıkar ve kodun ana döngüsüne gireriz. Tap To Start.

Birduino --- Arduino-Oyun-Proje-Example1

// ===== initiateGame - Custom Function
void initiateGame() {
  myGLCD.clrScr();
  // Blue background
  myGLCD.setColor(114, 198, 206);
  myGLCD.fillRect(0,0,319,239);
  // Ground
  myGLCD.setColor(221,216,148);
  myGLCD.fillRect(0, 215, 319, 239);
  myGLCD.setColor(47,175,68);
  myGLCD.fillRect(0, 205, 319, 214);
  // Text
  myGLCD.setColor(0, 0, 0);
  myGLCD.setBackColor(221, 216, 148);
  myGLCD.setFont(BigFont);
  myGLCD.print("Score:",5,220);
  myGLCD.setFont(SmallFont);
  myGLCD.print("HowToMechatronics.com", 140, 220); 
  myGLCD.setColor(0, 0, 0);
  myGLCD.setBackColor(114, 198, 206);
  myGLCD.print("Highest Score: ",5,5);
  myGLCD.printNumI(highestScore, 120, 6);
  myGLCD.print(">RESET<",255,5);
  myGLCD.drawLine(0,23,319,23);
  myGLCD.print("TAP TO START",CENTER,100);
  
  drawBird(yB); // Draws the bird
  
  // Wait until we tap the sreen
  while (!gameStarted) {
    if (myTouch.dataAvailable()) {
    myTouch.read();
    x=myTouch.getX();
    y=myTouch.getY();        
    // Reset higest score
    if ((x>=250) && (x<=319) &&(y>=0) && (y<=28)) {
    highestScore = 0;
    myGLCD.setColor(114, 198, 206);
    myGLCD.fillRect(120, 0, 150, 22);
    myGLCD.setColor(0, 0, 0);
    myGLCD.printNumI(highestScore, 120, 5);
    } 
    if ((x>=0) && (x<=319) &&(y>=30) && (y<=239)) {
    gameStarted = true;
    myGLCD.setColor(114, 198, 206);
    myGLCD.fillRect(0, 0, 319, 32);
    }   
  }
  }
  // Clears the text "TAP TO START" before the game start
  myGLCD.setColor(114, 198, 206);
  myGLCD.fillRect(85, 100, 235, 116);
  
}

Ana döngü bölümünde, sütunların çizilmesi için kullanılan xP değişkeninin yanı sıra yP değişkenine de sahibiz. Başlangıçta, xP değişkeni, ekran boyutu olarak 319 değerine sahiptir ve yP değişkeni, ilk sütununun yüksekliği olan 100 değerine sahiptir. Her yineleme ile xP değişkeninin değeri, başlangıçta 3 değerine sahip olan movingRate değişkeninin değeriyle azalır ve oyun ilerledikçe artar.
 
// The Main Loop Section
void loop() {
    xP=xP-movingRate; // xP - x coordinate of the pilars; range: 319 - (-51)   
    drawPilars(xP, yP); // Draws the pillars 
    
    // yB - y coordinate of the bird which depends on value of the fallingRate variable
    yB+=fallRateInt; 
    fallRate=fallRate+0.4; // Each inetration the fall rate increase so that we can the effect of acceleration/ gravity
    fallRateInt= int(fallRate);
    
    // Checks for collision
    if(yB>=180 || yB<=0){ // top and bottom
      gameOver();
    }
    if((xP<=85) && (xP>=5) && (yB<=yP-2)){ // upper pillar
      gameOver();
    }
    if((xP<=85) && (xP>=5) && (yB>=yP+60)){ // lower pillar
      gameOver();
    }
    
    // Draws the bird
    drawBird(yB);
    // After the pillar has passed through the screen
    if (xP<=-51){
      xP=319; // Resets xP to 319
      yP = rand() % 100+20; // Random number for the pillars height
      score++; // Increase score by one
    }
    //==== Controlling the bird
    if (myTouch.dataAvailable()&& !screenPressed) {
       fallRate=-6; // Setting the fallRate negative will make the bird jump
       screenPressed = true;
    }
    // Doesn't allow holding the screen / you must tap it
    else if ( !myTouch.dataAvailable() && screenPressed){
      screenPressed = false;
    }
    
    // After each five points, increases the moving rate of the pillars
    if ((score - lastSpeedUpScore) == 5) {
      lastSpeedUpScore = score;
      movingRate++;
    }
}

Arduino zıplama oyunun çalışma prensibi: Sağdan sola hareket eden 50 piksel genişliğinde sütunlarımız var ve sonraki her sütun farklı bir rastgele yüksekliğe sahip. Mantıksal olarak hareket etmelerini sağlamak için, her yinelemeden sonra ekranı temizlememiz ve grafiği yeni pozisyonlarındaki sütunlarla yeniden çizmemiz gerekir. Ancak, ekranın düşük yenileme hızı nedeniyle bunu yapamayız, bu da grafiklerin titremesine neden olur. Tüm piksellerini aktive etmek için ekranın biraz daha zamana ihtiyacı var, bu yüzden sadece hareket eden şeyleri doğaçlama ve yeniden çizmeliyiz.

Birduino --- Arduino-Oyun-Proje-Example1

drawPilars () özel işlevi, xP ve yP değişkenlerini alır ve fillRect () işlevini kullanarak sütun çizer. Bu yüzden her yineleme, sütunları solda ve sağ taraflarından ek mavi dikdörtgenler ile yeni konumlarına çeker, önceki çizilen sütunu temizler ve bu şekilde hareket eden sütunları sadece yeniden doğaçlama çizmiş oluruz. Burada if ifadeleri ek bir doğaçlamadır, çünkü bir nedenden dolayı fillRect () işlevi, eğer ‘x2’ parametresi ekran boyutunun dışında bir değere sahipse işe yaramaz. Ayrıca, bu özel fonksiyonun sonunda ulaşılan puanı yazdırmamız gerekir.

// ===== drawPlillars - Custom Function
void drawPilars(int x, int y) {
    if (x>=270){
      myGLCD.setColor(0, 200, 20);
      myGLCD.fillRect(318, 0, x, y-1);
      myGLCD.setColor(0, 0, 0);
      myGLCD.drawRect(319, 0, x-1, y);
      myGLCD.setColor(0, 200, 20);
      myGLCD.fillRect(318, y+81, x, 203);
      myGLCD.setColor(0, 0, 0);
      myGLCD.drawRect(319, y+80, x-1, 204); 
    }
    else if( x<=268) {
      // Draws blue rectangle right of the pillar
      myGLCD.setColor(114, 198, 206);
      myGLCD.fillRect(x+51, 0, x+60, y);
      // Draws the pillar
      myGLCD.setColor(0, 200, 20);
      myGLCD.fillRect(x+49, 1, x+1, y-1);
      // Draws the black frame of the pillar
      myGLCD.setColor(0, 0, 0);
      myGLCD.drawRect(x+50, 0, x, y);
      // Draws the blue rectangle left of the pillar
      myGLCD.setColor(114, 198, 206);
      myGLCD.fillRect(x-1, 0, x-3, y);
      // The bottom pillar
      myGLCD.setColor(114, 198, 206);
      myGLCD.fillRect(x+51, y+80, x+60, 204);
      myGLCD.setColor(0, 200, 20);
      myGLCD.fillRect(x+49, y+81, x+1, 203);
      myGLCD.setColor(0, 0, 0);
      myGLCD.drawRect(x+50, y+80, x, 204);
      myGLCD.setColor(114, 198, 206);
      myGLCD.fillRect(x-1, y+80, x-3, 204);
  }
  // Draws the score
  myGLCD.setColor(0, 0, 0);
  myGLCD.setBackColor(221, 216, 148);
  myGLCD.setFont(BigFont);
  myGLCD.printNumI(score, 100, 220);
}

Döngü bölümünde, kuşun y konumu olan yB değişkenine sahibiz ve her yinelemeden sonra yükselen düşme hızına bağlı olarak hızlanma veya yerçekimi etkisini elde ederiz. Ayrıca, burada çarpışmaları kontrol ediyoruz ve kuşu sınırlandırmak için if ifadelerini kullanıyoruz, böylece oyun en üst ve zemin arasında sınırlanacak.

Birduino --- Arduino-Oyun-Proje-Example1

İkincisi, drawBird () özel işlevidir ve nasıl çalıştığını görelim. Kuş aslında Henning Karlsen tarafından üretilen ImageConverter565 aracı kullanılarak bir bitmap haline dönüştürülmüş bir fotoğraftır. Aracı kullanarak oluşturulan “.c” dosyasının, taslak çizilirken yüklenebilmesi için dizine dahil edilmesi gerekir. Ayrıca bitmap’i bu şekilde tanımlamalı ve drawBitmap () işlevini kullanarak fotoğrafı ekranda çizeceğiz. Kuş sabit bir X koordinatına ve yP değişkeni Y – koordinatına sahiptir. Sütunlara benzer şekilde, kuşun üstünde ve altında iki mavi dikdörtgen çizerek kuşun önceki durumunu temizleyeceğiz.

//====== drawBird() - Custom Function
void drawBird(int y) {
  // Draws the bird - bitmap
  myGLCD.drawBitmap (50, y, 35, 30, bird01);
  // Draws blue rectangles above and below the bird in order to clear its previus state
  myGLCD.setColor(114, 198, 206);
  myGLCD.fillRoundRect(50,y,85,y-6);
  myGLCD.fillRoundRect(50,y+30,85,y+36);
}

Döngüye döndüğümüzde, kolonun ekrandan geçmesinden sonra, xP değişkeninin 319’a sıfırlanacağını, yP‘nin sütunların yüksekliği için 20’den 100’e kafar rastgele bir değer alacağını ve puanın bir puan artacağını görebiliyoruz. Bir sonraki ififadesinde kuşu kontrol ederiz. Ekrana dokunduğumuzda, düşme oranını negatife ayarlayacağız. Son if ifadesi oyunun zorluğuna yöneliktir ve her ince noktadan sonra sütunların hareket hızını arttırır.

Şimdi geriye gameOver () özel işlevinin nasıl çalıştığını görmek kaldı. Bir saniyelik gecikmeden sonra ekran yenilenir, oyun puanı ve bir metin çıkar. Eğer puan en yüksek puandan yüksekse EEPROM’a yazacaktır, tüm değişkenleri başlangıç ​​konum değerlerine sıfırlayacaktır. Oyunu yeniden başlatmak için startateGame () özel işlevini çağırır.

Birduino --- Arduino-Oyun-Proje-Example1

//======== gameOver() - Custom Function
void gameOver() {
  delay(1000); // 1 second
  // Clears the screen and prints the text
  myGLCD.clrScr();
  myGLCD.setColor(255, 255, 255);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.setFont(BigFont);
  myGLCD.print("GAME OVER", CENTER, 40);
  myGLCD.print("Score:", 100, 80);
  myGLCD.printNumI(score,200, 80);
  myGLCD.print("Restarting...", CENTER, 120);
  myGLCD.setFont(SevenSegNumFont);
  myGLCD.printNumI(2,CENTER, 150);
  delay(1000);
  myGLCD.printNumI(1,CENTER, 150);
  delay(1000);
  
  // Writes the highest score in the EEPROM
  if (score > highestScore) {
    highestScore = score;
    EEPROM.write(0,highestScore);
  }
  // Resets the variables to start position values
  xP=319;
  yB=50;
  fallRate=0;
  score =</