İSTANBUL İÇİ SAAT 16:00'A KADAR VERECEĞİNİZ 2500₺ ve ÜZERİ SİPARİŞLERİNİZ AYNI GÜN KAPINIZDA 🏍️
500 TL üzeri ücretsiz kargo
İSTANBUL İÇİ SAAT 16:00'A KADAR VERECEĞİNİZ 2500₺ ve ÜZERİ SİPARİŞLERİNİZ AYNI GÜN KAPINIZDA 🏍️
500 TL üzeri ücretsiz kargo
Arduino ile Chrome Dino Oyunu Yapımı [Adım Adım Rehber]

Arduino ile Chrome Dino Oyunu Yapımı [Adım Adım Rehber]

Arduino ile Chrome Dino Oyunu Yapımı [Adım Adım Rehber]


Arduino ile Chrome Dino Oyunu


İnternetsiz kaldığımızda karşımıza çıkan Chrome Dino oyunu, artık Arduino ile de yapılabilir! Bu projede, Dino’yu buton ile kontrol ederek engellerden kaçmasını sağlayacağız. Skor sistemi, oyun bitti ekranı ve yeniden başlatma özellikleri de dahil.


Proje İçin Gerekli Malzemeler



Devre Kurulumu


LCD ekran I2C arayüzü ile bağlanmalı ve adresi kontrol edilmelidir. Buton dijital pine, buzzer ise ses efektleri için ayrı pine bağlanır. Tüm bağlantılar breadboard üzerinde yapılır.


I2c Lcd ile Dino Oyunu Devresi
I2c Lcd ile Dino Oyunu Devresi

I2C Adres Kontrolü


LCD ekranı kullanmadan önce I2C adresini tespit etmemiz gerekir. Bunun için aşağıdaki kod çalıştırılır ve Seri Monitör’den adres okunur.


#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("I2C adresleri taraniyor...");
}

void loop() {
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("Aygit bulundu! Adres: 0x");
      Serial.println(address, HEX);
    }
  }
  Serial.println("Tarama tamamlandi.");
  delay(5000); 
}

Arduino Kodları


Aşağıdaki kod, Dino karakterini ve engelleri LCD üzerinde gösterir. Butona basıldığında Dino zıplar, engellerden kaçmaya çalışır. Skor artar ve çarpışma durumunda oyun biter.


Devre Kodu

#include <Wire.h> //I2C haberleşme için gerekli kütüphane
#include <LiquidCrystal_I2C.h> // I2C uyumlu LCD ekran kütüphanesi

LiquidCrystal_I2C lcd(0x27, 16, 2);  // LCD ekran nesnesi tanımlanıyor (I2C Adresi, Sütun Sayısı, Satır Sayısı)

const int buttonPin = 2;  // Butonun bağlı olduğu pin
const int buzzerPin = 3;  // Buzzer'ın bağlı olduğu pin

int buttonState = 0; //buttonState değişkeni tanımlanıp 0 değeri veriliyor
int lastButtonState = 0; //lastButtonState değişkeni tanımlanıp 0 değeri veriliyor

//Karakterlerin ve engellerin bit dizilimleri
byte dino[8] = {
  0b00000,
  0b00111,
  0b00111,
  0b10110,
  0b11111,
  0b01010,
  0b01010,
  0b00000
};

byte smallCactus[8] = {
  B00000,
  B00000,
  B00000,
  B00100,
  B00101,
  B10111,
  B11100,
  B00100
};

byte mediumCactus[8] = {
  B00000,
  B00000,
  B00100,
  B00101,
  B00111,
  B10110,
  B11100,
  B00100
};

byte largeCactus[8] = {
  B00100,
  B00101,
  B10101,
  B11101,
  B00111,
  B00110,
  B11100,
  B00100
};

byte bird[8] = {
  0b00000, 
  0b00100, 
  0b01100, 
  0b11110, 
  0b00111, 
  0b00110, 
  0b00100, 
  0b00000
};

int dinoPos = 1;  // Dino'nun y pozisyonu (0: zıplıyor, 1: yerde)
int obstaclePos = 16; //Engel konumu değişkeni belirleniyor
int obstacleType = 0;  // 0: küçük kaktüs, 1: orta kaktüs, 2: büyük kaktüs, 3: kuş
unsigned long lastMoveTime = 0;
int score = 0;
bool gameOver = false;
int jumpCounter = 0;
int gameSpeed = 300;  // Başlangıç hızı (ms)
int levelCounter = 0;

void setup() {
  lcd.init(); //LCD başlatılıyor
  lcd.backlight(); //LCD arka ışıkları açılıyor
  //Belirlenen bitler ile özel karakterler yaratılıyor
  lcd.createChar(0, dino);
  lcd.createChar(1, smallCactus);
  lcd.createChar(2, mediumCactus);
  lcd.createChar(3, largeCactus);
  lcd.createChar(4, bird);
  
  pinMode(buttonPin, INPUT_PULLUP); //Dijital pindeki dahili direnç aktifleştirilerek buton girişi tanımlanıyor
  pinMode(buzzerPin, OUTPUT);
  
  lcd.setCursor(0, 0); //LCD imleci 1. satır, 1. sütuna getiriliyor
  lcd.print("Dino Game");
  lcd.setCursor(0, 1); //LCD imleci 2. satır, 1. sütuna getiriliyor
  lcd.print("Press to start");
  
  while (digitalRead(buttonPin) == HIGH) { //Buton basılı olmadığı sürece 50 ms bekle
    delay(50);
  }
  //Butona basıldığında while döngüsünden çıkılır
  playStartSound(); //playStartSound fonksiyonu çağrılıyor
  lcd.clear(); //LCD temizleniyor
}

void loop() {
  if (!gameOver) { //Oyun bitmiş değilse
    unsigned long currentTime = millis();
    
    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW && lastButtonState == HIGH && dinoPos == 1) { //Butona basılmış, butonun önceki durumu basılmamış ve Dino yerde ise
      dinoPos = 0;  // Zıpla
      jumpCounter = 3;  // 3 kare boyunca zıplamada kal
      playJumpSound(); //playJumpSound fonksiyonu çağrılıyor
    }
    lastButtonState = buttonState; //Mevcut buton durumu lastButtonState değişkenine atanır
    
    if (currentTime - lastMoveTime > gameSpeed) { // Geçen süre oyun hızından büyükse (yani hareket zamanı geldiyse)
      lastMoveTime = currentTime; //Son hareket zamanını güncelle
      
      lcd.clear();
      
      if (jumpCounter > 0) { Zıplama sayacı 0'dan büyük (devam ediyor) ise
      jumpCounter--; //Değişkenin değerini bir azalt
      } else if (dinoPos == 0) { //Zıplama sayacı 0'dan büyük değil ve Dino havadaysa
        dinoPos = 1;  // Yere in
      }
      
      lcd.setCursor(2, dinoPos); //LCD imleci Dino'nun konumuna getiriliyor
      lcd.write(byte(0));  // Dino konumuna yazdırılıyor
      
      obstaclePos--; //Engel bir sütun sola kaydırılıyor
      if (obstaclePos < 0) { //Engel konumu 1. satırdan solda (0'dan küçük) ise
        obstaclePos = 16; //obstaclePos değişkenine 16 değerini ata
        score++; //Skoru bir arttır
        levelCounter++; //Seviye sayacını bir arttır
        
        // Her 10 puanda bir hızı arttır
        if (levelCounter % 10 == 0 && gameSpeed > 100) {
          gameSpeed -= 20; // Hız 20 ms artırılıyor (hareket bekleme süresi azalıyor)
        }
        
        // Engel seçimi
        int randomObstacle = random(100); //0-99 arası rastgele sayı üretiliyor
        if (score > 10 && randomObstacle < 30) {  // %30 ihtimalle kuş
          obstacleType = 3;
        } else if (randomObstacle < 50) {  // %20 ihtimalle küçük kaktüs
          obstacleType = 0;
        } else if (randomObstacle < 80) {  // %30 ihtimalle orta kaktüs
          obstacleType = 1;
        } else {  // %20 ihtimalle büyük kaktüs
          obstacleType = 2;
        }
      }
      
      if (obstacleType == 3) {  // Engel kuş ise
        lcd.setCursor(obstaclePos, 0); //LCD imleci üst satıra getiriliyor
        lcd.write(byte(4)); //Kuş karakteri yazdırılıyor
      } else {  // Engel kuş değilse (kaktüsler)
        lcd.setCursor(obstaclePos, 1); //LCD imleci alt satıra getiriliyor
        lcd.write(byte(obstacleType + 1)); //Özel karakterler ile engel türleri eşleşmediği için 1 ekleyerek özel karakter dizinini yazdırıyoruz
      }
      
      lcd.setCursor(12, 0);
      lcd.print(score);
      
      // Çarpışma kontrolü
      bool collision = false; // Çarpışma durumunu kontrol etmek için değişken (false: çarpışma yok, true: çarpışma)
      if (obstaclePos == 2) { // Engel 2. sütunda ise (Dino'nun bulunduğu sütun)
        if (obstacleType == 3 && dinoPos == 0) {  // Engel kuş ise ve Dino havada ise
          collision = true; 
        } else if (obstacleType < 3 && dinoPos == 1) {  //Engel kaktüs ise ve Dino yerde ise
          collision = true;
        }
      }
      
      if (collision) { //collision değişkeni true ise (çarpışma varsa)
        gameOver = true; 
        playGameOverSound(); //playGameOverSound fonksiyonu çağrılıyor
      }
    }
  } else { //Oyun bitmişse
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Game Over!");
    lcd.setCursor(0, 1);
    lcd.print("Score: ");
    lcd.print(score);
    
    delay(3000);
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Press to restart");
    
    while (digitalRead(buttonPin) == HIGH) { //Butona basılmadıkça 50 ms bekle
      delay(50);
    }
    //Butona basıldığında while döngüsünden çıkılır ve değişken değerleri ilk duruma getirilir
    gameOver = false;
    dinoPos = 1;
    obstaclePos = 16;
    obstacleType = 0;
    score = 0;
    gameSpeed = 300;
    levelCounter = 0;
    playStartSound();
    lcd.clear();
  }
}

void playStartSound() {
  tone(buzzerPin, 523, 100); // Buzzer'ı 523 Hz (Do) frekansında 100 ms çal
  delay(100);
  tone(buzzerPin, 659, 100); // Buzzer'ı 659 Hz (Mi) frekansında 100 ms çal
  delay(100);
  tone(buzzerPin, 784, 100); // Buzzer'ı 784 Hz (Sol) frekansında 100 ms çal
  delay(100);
}

void playJumpSound() {
  tone(buzzerPin, 1000, 50);
}

void playGameOverSound() {
  tone(buzzerPin, 200, 200);
  delay(200);
  tone(buzzerPin, 150, 200);
  delay(200);
  tone(buzzerPin, 100, 400);
}

Projenin Çalışma Mantığı


  • Dino butona basıldığında zıplar.
  • Kaktüs ve kuş engelleri rastgele belirir.
  • Her engel geçildiğinde skor artar.
  • Çarpışma olduğunda Game Over ekranı çıkar.
  • Butona basarak oyun yeniden başlatılabilir.

Sonuç


Bu proje sayesinde Arduino ile eğlenceli bir mini oyun yapmayı öğrendik. Hem LCD ekran kullanımı hem de buton-buzzer gibi giriş/çıkış elemanlarını bir arada deneyimlemek için harika bir örnektir.

Daha fazla Arduino projesi için Arduino kategorimize göz atabilirsiniz.


Hazırlayan: Kirpilab | Maker topluluğu için Arduino projeleri