SDL ile Oyun Programlama
Faruk Erdem Öncel



İngilizce Kaynaklar


Diğer




Hoşgeldiniz

D ile 2D oyun programlama dersine hoşgeldiniz. Bu derste D dili kullanarak 2D oyun programlamaya bir başlangıç yapacağız.

Bir oyunun geliştirme aşamaları şu bölümlerden oluşuyor

Biz bunlardan programlama ile ilgileneceğiz. Bunu yaparken programlama dili olarak D kullanacağız.

Kullanacağımız grafik kütüphanesi ise SDL (Simple Direct Media Layer)

http://www.libsdl.org

Konuları takip edebilmek için sadece D programlama dilini bilmeniz yeterli. Her ne kadar SDL grafik kütüphanesi kullanıyor olsak da asıl amacım sadece 2D oyun programlama, oyun değişkenleri ile ilgili temel kavramları anlatmak olacak.

SDL ile ilgili konuları sadece gerektiğinde ve uzmanlar için bölümünde ek bilgi olarak anlatmayı düşünüyorum.

Haydi başlayalım

Başlamak için şu basit adımları izlemeniz yeterli:

  1. D derleyicisini kurun
  2. SDL için geliştirme kütüphanelerini kurun
  3. Örnek projeyi bilgisayarınıza indirin

gerekli araçları kuralım

1- D derleyicisi:

Ubuntu altında Digital Mars derleyicisinin son sürümünü

http://dlang.org/download.html

adresinden indirerek otomatik olarak yazılım merkezi ile kurabilirsiniz.

Windows altında Digital Mars derleyicisinin son sürümünü

http://dlang.org/download.html

adresinden otomatik olarak kurabilirsiniz.

2- SDL geliştirme kütüphaneleri:

SDL geliştirme kütüphanelerini kurmak için Ubuntu altında konsolda

$ sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev

komutunu vermeniz yeterli.

Windows altında, SDL geliştirme kütüphaneleri örnek proje ile beraber geliyor. Bu yüzden SDL ile ilgili kütüphaneleri indirmenize gerek yok.

Ancak kolaylık olması açısından bin dizininde bulunan *.dll uzantılı dosyaları C:\WINDOWS\system32 dizinine kopyalamak isteyebilirsiniz.

3- Örnek projeyi indirelim:

Örnek projeyi indirmek için tarayıcınızla

https://github.com/erdemoncel/oyun

adresini açıp sağ üst tarafta bulunan Downloads düğmesine tıklayıp Download .tar.gz ya da Download .zip seçerek projeyi indirmeniz yeterli

Ya da eğer github kullanımını biliyorsanız basitçe:

$ git clone git@github.com:erdemoncel/oyun.git

komutuyla projenin bir kopyasını bilgisayarınıza indirebilirsiniz.

Oyun döngüsü

Oyun Döngüsü Bir oyunun temel bileşeni bir oyun döngüsüdür. İster çok gelişmiş ya da basit bir oyun olsun her oyun bir oyun döngüsü kullanır. Şimdi bir oyun döngüsünün yapısını inceleyelim.

İlklendir :

Oyunda kullandığımız oyun değişkenlerinin ilk değerlerini burada veriyoruz.

İçeriği Yükle :

Oyunumuzun ihtiyaç duyduğu 2D hareketli grafikler texture, oyuncu modelleri, ses efektleri ve müzik gibi içeriği bu bölümde yüklüyoruz,

Güncelle :

Burada oyuncunun klavye, oyun çubuğu ya da başka bir donanımla girdiği girdileri kontrol ediyor ve oyunun her karesinde oyun değişkenlerini değiştiriyoruz.

Çiz :

Burada oyunumuza grafik kartına ne gönderileceğini ve ekrana nasıl çizileceğini söylüyoruz

Bir oyuncu oluşturmak

Ekranda bir görüntü oluşabilmesi için çeşitli bilgileri saklamalıyız. Bir oyuncunun konumu buna iyi bir örnek olabilir.

Şimdi kağıt üzerinde bir oyuncu oluşturmak için neler yapmamız gerektiğini düşünelim. Bunları kağıda yazın

İlklendir bölümüne oyuncumuzun ekran üzerinde başlangıç konumunu belirleyen bir işlev ekleyelim.

İlklendir
        oyuncuKonumunuBelirle()

Şimdi teknik olarak oyuncumuz mevcut. Oyunun ilklendir() metodunda sağladığımız bilgilerle artık oyun karakterimizi istediğimiz yere hareket ettirebiliriz.

Ama ekranda bir şey göremezsek bu iyi bir oyun sayılmaz

Ekrana bir şeyler çizebilmek için ilkönce çizeceğimiz animasyonu ya da grafiği yüklemeliyiz.

İçerik Yükle
       içerik.yükle(dosya)

Daha sonra oyunumuzu ekran kartının belleğinde çiziyoruz.

Çiz
        oyuncuyu.çiz()

Oldukça basit. Peki oyunun içinde sürekli değişiklikler olmasını istersek ne yapmamız lazım.

Burada işte güncelle() metodu karşımıza çıkıyor. Güncelle metodunu kullanarak ilk değerlerini verdiğimiz oyun değişkenlerini istediğimiz gibi değiştirebiliyoruz. Güncelle metoduna bazı kodlar ekleyerek oyun içinde tutulan istediğimiz bilgiyi değiştirebiliriz.

Güncelle
        if (sağTuşBasılıMı)
           konumuGüncelle & animasyonuGüncelle

Örneğin klavyenin sağ tuşuna basınca oyun karakterimizin sağa doğru hareket etmesini istiyorsak güncelle() metodunda sağ tuşun basılı olup olmadığını denetliyoruz ve animasyonu güncelliyoruz.

Burada animasyonuGüncelle() kısmına sağa doğru yürüyen bir oyuncu animasyonu koyabiliriz.

oyuncu.d dosyasının içinde

Artık oyunumuzu kodlamaya başlayabiliriz.

İlkönce daha önce indirmiş olduğunuz proje dosyalarını bir sıkıştırma programı ile açıp test klasörünün içine gelin. Burada herhangi bir editörle oyuncu.d isminde yeni bir dosya oluşturun. Ve içine şunları girin.

import sdl, vector2, cizici;

class Oyuncu
{
    // ilklendir
    this(Grafik2D grafik, Vector2 konum)
    {
    }

    void güncelle()
    {
    }

    void çiz(Çizici çizici)
    {

    }
}

Dikkat ederseniz biraz önce oyun döngüsünde bahsettiğimiz işlevlerin bazılarını Oyuncu sınıfımız için de yazmış olduk.

D derslerinden hatırlayacağınız gibi this() sınıfın kurucu işlevi ve sınıf üyelerine ilk değer ataması burada gerçekleşiyor. D'nin böyle bir özelliği olduğu için ekstradan bir ilklendir() işlevi yazmamıza gerek yok. Oyuncu sınıfının değişkenlerine ilk değer atamasını burada yapabiliriz.

Şimdi düşünelim. Bir oyun karakterinin ne gibi özellikleri olmalı?

Herşeyden önce ekrana çizebileceğimiz bir 2D grafiğe ya da bir animasyona sahip olmalı. Ayrıca konumunu belirten koordinatlara sahip olmalı.

İşte Oyuncu sınıfımız bu yüzden parametre olarak bir 2 boyutlu grafik ve konum bilgisi alıyor. Burada şimdilik Vector2 nin ekran üzerinde bir oyun nesnesinin x ve y koordinatlarını tutan basit bir yapı olduğunu bilmeniz yeterli.

Örneğin:

        auto oyuncuKonum = Vector2(6, 6);

diyerek aşağıdaki Calvin and Hobbes çizgi romanının sevimli karakteri Hobbes'un konumunu bir Vector2 yapısında tutabiliriz.

Burada hemen farkedebileceğiniz bir şey SDL'in y ekseni alıştığımız koordinat sisteminin tersine aşağı doğru bakıyor.

Ayrıca koordinat merkezi olarak oyuncu grafiğinin sol üst köşesini alıyoruz. (resimdeki kırmızı nokta ile işaretlenmiş kısım)

class Oyuncu'nun altındaki ilk { den sonra bunları girin.

    // her oyuncunun bir 2D grafiği olmalı
    Grafik2D oyuncuGrafik;

    // oyuncunun ekranın sol üst köşesine göre göreceli konumu
    Vector2 konum;

    // oyuncunun durum
    bool aktif;

    // oyuncunun sağlık puanı
    int sağlık;

    // oyuncunun genişliği ve yüksekliği
    int genişlik;
    int yükseklik;

Vector2 yapısıyla bir nesnenin konumunun x ve y koordinatlarını tutabileceğimizi söylemiştik. Grafik2D ise grafik bilgisini tutan ve ekrana çizilebilen özel bir veri türü.

Oyuncumuzu çizdireceğimiz zaman oyuncuya ait Grafik2D iki boyutlu grafiğini Vector2 ile belirtilen konuma çizdireceğiz.

Şimdi yapmamız gereken oyuncunun ilk konumunu belirtmek ve oyuncuya ait grafiğe bir ilk değer vermek.

Oyuncu sınıfının kurucu işlevini aşağıdaki gibi değiştirin.

    this(Grafik2D grafik, Vector2 konum)
    {
        oyuncuGrafik = grafik;

        // oyuncunun başlangıç konumu belirle
        this.konum = konum;

        // oyuncuyu aktif yapıyoruz
        aktif = true;

        // oyuncunun sağlık puanını belirle
        sağlık = 100;

        // her grafik nesnesinin bir w (genişlik) ve h (yükseklik) değeri
        // olduğu için oyuncumuzun genişlik ve yükseklik değerlerine bu
        // değerleri atayabiliriz
        genişlik = grafik.w;
        yükseklik = grafik.h;
    }

Oyuncumuzun ihtiyaç duyduğu ilk değerleri verdikten sonra artık oyuncuyu çizdirebiliriz. Bunu da oyuncunun çiz yöntemine bir Çizici nesnesi geçerek yapıyoruz.

Çizici nesnesinin yaptığı kendine geçilen bir iki boyutlu grafiği ekranın belirli bir konumuna çizdirmek. Çizici sınıfının ayrıntıların merak ediyorsanız src klasöründe bulan cizici.d modülünü inceleyebilirsiniz.

Oyuncu sınıfının çiz işlevini aşağıdaki gibi değiştirin.

    void çiz(Çizici çizici)
    {
        çizici.çiz(oyuncuGrafik, konum);
    }

Oyuncu sınıfıyla şimdilik işimiz bitti.

oyun.d dosyasının içinde

test klasöründeki oyun.d dosyasını açın.

Kod içinde Oyun sınıfını bulduktan sonra class Oyun : TemelOyun un hemen altına { dan sonra oyuncuyu ekleyin.

    Oyuncu oyuncu;

Oyuncuyu ekrana çizebilmek için önce oyuncuya ait grafiği yüklemeli ve oyuncunun ilk konumunu belirlemeliyiz.

Sabitdisk üzerinde bulunan grafikleri okuyup oyuna yükleyeceğimiz için bunları içerikYükle() metodunun hemen altında yapabiliriz.

super.içerikYükle() nin altına bu kodu ekleyin.

        // oyuncuya ait içeriği yükle
        auto oyuncuKonum = Vector2(288, 203);
        oyuncu = new Oyuncu(içerik.yükle("penguen.bmp"), oyuncuKonum);

Burada içerik.yükle kısmı dikkatinizi çekmiş olabilir. Oyunumuzun içerik isimli bir yapısı var. Bir grafiği yüklemek için bu yapıya yüklemek istediğiniz 2D grafiğin ismini vermeniz yeterli.

içerik.yükle() işlevi bir Grafik2D döndürüyor. Ayrıca Oyuncu sınıfının kurucu işlevi de parametre olarak bir 2D grafik ve oyuncunun konumunu belirten bir vektör alıyordu.

Oyuncuyu ekrana çizmeye hazırız. Oyun sınıfının çiz işlevine bu kodu ekleyin.

        /// Nesneleri göster
        // oyuncuyu çiz
        oyuncu.çiz(çizici);

İşte bu kadar. Artık çizme bölümü de tamamlanmış oldu.

Oyunu çalıştırmak

Programın kaynak kodunu derlemek için şu komutları girin:

Ubuntu altında konsoldan:

$ make ornek
$ cd bin
$ ./ornek

Windows altında Başlat->Çalıştır-> yolunu izleyerek buraya cmd yazın. Açılan konsolda:

make ornek -f win32.mak
cd bin
ornek.exe

Eğer her şey yolunda gittiyse ekranınınızda sevimli bir penguen görmeniz lazım

Dersin kaynak kodu

Programı derlerken herhangi bir sorun çıktıysa merak etmeyin. Dersin kaynak kodunu buradan indirebilirsiniz.

Uzman ipucu

Yazının başında da belirttiğim gibi SDL ile ilgili konuları bu bölümde anlatacağım. Bu yüzden bu bölümü okuyup okumamak sizin zevkinize kalmış

Amacımız ekranın arkaplan rengini değiştirmek. TemelOyun sınıfı içinde //Ekranı temizle yazan kısmın hemen altına gelin.

        SDL_FillRect(ekran, &ekran.clip_rect,
                     SDL_MapRGB(ekran.format, 0x00, 0x00, 0xFF));   

Burada SDL_MapRGB işlevinin aldığı ilk parametre piksellerin biçimi, ikincisi de rengi oluşturan r g b değerleri. Yani kırmızı yeşil mavi değerleri. İşlevin kendisi de bir uint tamsayı döndürüyor.Yani bu kırmızı yeşil mavi değerlerinin birleşimi olan renk değerini SDL'de bir uint işaretsiz tamsayı ile ifade edebiliyoruz.

Eğer Gimp, Photoshop gibi çizim programları kullandıysanız renklerin karşılıklarının 0 ile 255 arasında değişen RGB değerler ile ifade edildiğini hatırlayacaksınız. Örneğin RGB(255, 0, 0) kırmızı gibi.

Biz de bu renk değeri kullanarak ekranı temizle işlevini, ekranı maviye boyayacak şekilde değiştireceğiz. Burada sizin de farketmiş olabileceğiniz gibi bu değerler onaltılık sayı sisteminde 0x şeklinde yazılmış. Bu yüzden ekranı maviye boyamak için ikinci renk değerini 0xFF olarak değiştirin.

Programı tekrar derlediğinizde artık ekranın maviye boyandığını göreceksiniz.