Levels (Seviyeler)

Breakout maalesef yalnızca tek bir mutlu yeşil yüzden ibaret değil; çok sayıda renkli tuğlayla dolu seviyeleri olan bir oyun. Bu seviyelerin herhangi sayıda satır ve/veya sütunu destekleyecek şekilde yapılandırılabilir olmasını, yıkılamayan sağlam tuğlalar içermesini, birden fazla tuğla rengine sahip olmasını ve (metin) dosyalarında harici olarak saklanmasını istiyoruz.

Bu bölümde çok sayıda tuğlayı yönetmek için kullanılan bir oyun seviyesi nesnesinin koduna kısaca bakacağız. Öncelikle bir tuğlanın ne olduğunu tanımlamamız gerekiyor.

Oyundaki bir nesnenin temel temsilcisi olarak hareket eden oyun nesnesi (game object) adlı bir bileşen oluşturuyoruz. Böyle bir oyun nesnesi konum, boyut ve hız gibi durum verilerini tutar. Renk, döndürme bileşeni, solid ve/veya yıkılmış olup olmadığı ile sprite olarak bir Texture2D değişkeni içerir.

Oyundaki her nesne GameObject sınıfının bir örneği veya türevi olarak temsil edilir. GameObject sınıfının kaynak kodu: başlıkarrow-up-right, kodarrow-up-right.

Breakout'taki bir seviye tamamen tuğlalardan oluşur; bu nedenle bir seviyeyi tam olarak bu şekilde temsil edebiliriz: tuğlalar koleksiyonu. Bir tuğla, oyun nesnesiyle aynı duruma ihtiyaç duyduğundan seviyedeki her tuğlayı GameObject olarak temsil ediyoruz. GameLevel sınıfının bildirimi şöyle görünür:

class GameLevel
{
public:
    // seviye durumu
    std::vector<GameObject> Bricks;
    // kurucu
    GameLevel() { }
    // seviyeyi dosyadan yükle
    void Load(const char *file, unsigned int levelWidth, unsigned int levelHeight);
    // seviyeyi çiz
    void Draw(SpriteRenderer &renderer);
    // seviyenin tamamlanıp tamamlanmadığını kontrol et (yıkılabilir tüm tuğlalar yıkıldı mı)
    bool IsCompleted();
private:
    // seviyeyi kutucuk verisinden başlat
    void init(std::vector<std::vector<unsigned int>> tileData, 
              unsigned int levelWidth, unsigned int levelHeight);
};

Seviye harici bir (metin) dosyasından yüklendiğinden bir tür seviye yapısı önermeliyiz. Seviyenin metin dosyasında nasıl görünebileceğine dair örnek:

Seviye, her sayının bir tuğla türünü temsil ettiği ve her birinin boşlukla ayrıldığı matris benzeri bir yapıda saklanır. Seçtiğimiz temsil:

  • 0: Tuğla yok, seviyede boş alan.

  • 1: Sağlam tuğla, yıkılamaz.

  • 1'den büyük her sayı: Yıkılabilir tuğla; her sayı yalnızca renk bakımından farklılık gösterir.

Yukarıdaki örnek seviye GameLevel tarafından işlendikten sonra şöyle görünür:

Seviye örneği

GameLevel sınıfı, seviyeyi dosyadan üretmek için iki fonksiyon kullanır. İlk olarak Load fonksiyonunda tüm sayılar iki boyutlu bir vektöre yüklenir; ardından init fonksiyonu bu sayıları işler:

Yüklenen tileData, oyun seviyesinin init fonksiyonuna iletilir:

init fonksiyonu yüklenen her sayıyı yineler ve işlenen sayıya göre seviyenin Bricks vektörüne bir GameObject ekler. Her tuğlanın boyutu (unit_width ve unit_height), toplam tuğla sayısına göre otomatik hesaplanır; böylece her tuğla ekran sınırlarına mükemmel biçimde sığar.

İki yeni doku ile oyun nesnelerini yüklüyoruz: bir blockarrow-up-right dokusu ve bir solid blockarrow-up-right dokusu.

Tuğla dokuları

Güzel bir numara: bu dokular tamamen gri tonlamadır. Bu sayede oyun kodundaki gri tonlamalı renkleri tanımlanmış renk vektörüyle çarptığımızda renkleri düzgünce değiştirebiliriz; tıpkı SpriteRenderer'da yaptığımız gibi.

GameLevel sınıfının kaynak kodu: başlıkarrow-up-right, kodarrow-up-right.


Oyun İçinde

Breakout oyununda birden fazla seviyeyi desteklemek istediğimizden, oyun sınıfını GameLevel türünde değişkenler barındıran bir vektör ekleyerek biraz genişletmemiz gerekiyor. Aktif seviyeyi de depoluyoruz:

Bu serinin Breakout oyunu toplam 4 seviye içeriyor:

Dokular ve seviyeler oyun sınıfının Init fonksiyonunda başlatılır:

Şimdi geriye kalan, seviyeyi gerçekten çizmek. Bunu mevcut aktif seviyenin Draw fonksiyonunu çağırarak yapıyoruz; bu da her GameObject'in Draw fonksiyonunu çağırır. Seviyenin yanı sıra güzel bir arka plan görüntüsüylearrow-up-right sahneyi de çiziyoruz:

Sonuç, oyunu gerçekten daha canlı hissettiren güzelce çizilmiş bir seviye:

Seviye renderı

Oyuncu Paddle'ı

Fırsatı kaçırmamak için sahnenin alt kısmına oyuncu tarafından kontrol edilen bir paddle ekleyelim. Paddle yalnızca yatay harekete izin verir ve sahnenin herhangi bir kenarına dokunduğunda hareketi durmalıdır. Paddle için şu dokuyuarrow-up-right kullanacağız:

Paddle dokusu

Paddle nesnesinin bir konumu, boyutu ve sprite dokusu olacağından paddle'ı da GameObject olarak tanımlamak mantıklı:

Oyunun ProcessInput fonksiyonuna da giriyoruz; kullanıcı A veya D tuşuna bastığında paddle'ı yatay olarak hareket ettiriyoruz:

x değerinin 0'dan küçük olması durumunda sol kenara taşmış olacağından, paddle'ı yalnızca sol tarafta x değeri 0.0'dan büyük olduğunda sola taşırız. Sağ kenar için de aynı karşılaştırmayı yapıyoruz; paddle'ın genişliğini sağ kenarın x konumundan çıkarmamız gerekiyor.

Oyunu çalıştırdığınızda hem seviyeyi hem de sahnenin alt kenarına hizalanmış bir paddle görürsünüz:

Seviye + paddle

Güncellenmiş Game sınıfı kaynak kodu: başlıkarrow-up-right, kodarrow-up-right.

Last updated