DirectX ile Oyun Programlama İskeleti Oluşturma
Bu makalede sizlere DirectX ile bir oyun iskeletinin nasıl oluşturulup çalıştırılacağını anlatacağım.
DirectX ile .net ile yazılım yapmak için Microsoft.DirectX veMicrosoft.DirectX.Direct3D kütüphanelerini kullanmanız gerekmektedir. Bu dll leri bilgisayarınıza DirectX kurarak getirebilirsiniz. Eğer sharpdevelop kullanıyorsanız directX projesi yapmak için New Project içerisinde Direct3D Application'ı seçerek otomatik olarak yapabilirsiniz. Visual Studio kullanıyorsanız ise yukarıdaki iki kütüphaneyi projenize eklemeniz gerekmektedir.
Visual studio içerisinde projeye directX dll lerini ekleme.
Sharp develop içerisinde proje olarak Direct3D Application seçildiğinde directX dll leri otomatik olarak eklenmiş olarak proje açılır.
Oluşturacağımız bir DirectX iskeleti aşağıdaki gibi olacaktır.
using
protected virtual void FrameMove(){}
protected virtual void Render(){ if (device != null) { device.Clear(ClearFlags.Target, Color.Aqua, 1.0f, 0); device.BeginScene(); device.EndScene(); device.Present();} }
public void Run(){ while (Created) { FrameMove(); Render(); Application.DoEvents(); } }
protected override void OnPaint(PaintEventArgs e){this.Render();}
protected override void OnKeyPress(KeyPressEventArgs e){ base.OnKeyPress(e); if ((int)e.KeyChar == (int)System.Windows.Forms.Keys.Escape) { this.Close(); } }
static void Main(){ using (MainClass mainClass = new MainClass()) { if (!mainClass.InitializeGraphics()) { MessageBox.Show("Hata Direct3D"); return; } mainClass.Show(); mainClass.Run(); } } } }
Programda System, System.Collections, System.ComponentModel,System.Drawing, System.Windows.Forms,Microsoft.DirectX,Microsoft.DirectX.Direct3D isim uzayları kullanılmıştır. Bu isim uzayları window bazlı programlamı, çizimde, formlarda, directx, direct3d sınıflarını kapsar.Main sınıfının kurucusunda oluşacak olan pencerenin boyutları ve pencerenin başlığı yazılmaktadır. InitializeGraphics fonksiyonunda ise yeni bir grafik aygıtı tanımlanmaktadır. Yeni bir aygıt tanımlarken alınan parametreleri başka bir makalede ayrıntılı olarak inceleyeceğim için fazla üzerinde durmanıza gerek yok, şu an için kafa karıştırıcı olabilir. Burada en önemli nokta delegate vasıtasıyla event handlerların tanımlanmasıdır. Bu eventhandler vasıtası ile program işletim sisteminden gelen kesmelere cevap verebilecektir bir nevi işletim sistemi ile haberleşebilecektir. Bu event handlerların ne zaman tetiklendiğini görmek için her bir eventın içerisine message box konularak uyarı alınmıştır. Bu uyarılar ile programı çalıştırdığınızda hangi event'ın nasıl ne zaman tetiklendiğini görebilirsiniz. Şimdi bu eventları inceleyelim. device.DeviceLost += new EventHandler(this.InvalidateDeviceObjects); eventı pencere kaybolduğunda pencere üzerinde bir işlem yapıldığında tüm objelerin geçersiz duruma gelmesi halinde tetiklenir.Bu event'ı kullanarak pencerenin kullanıcı tarafından kapatılmasını ya da pencerenin büyüklüğünde yapılan değişiklikleride yakalayabilirsiniz. device.DeviceReset += new EventHandler(this.RestoreDeviceObjects) eventi aygıt üzerinde yapılan bir değişiklik sırasında ya da form resize edilirken tetiklenir. device.Disposing += new EventHandler(this.DeleteDeviceObjects); eventı ile objeler toplanıp finalize edilip garbage collectera gönderileceği zaman çağrılır.device.DeviceResizing += new CancelEventHandler(this.EnvironmentResizing); aygıtın boyutunun değiştirilmesinde tetiklenir.Render ise nesnelerin hazırlanması, sahneye çizilmesi aşamasıdır. Kodların nesnelere dönüşmesi, oyun görüntülerinin oluşmasını sağlayan kısımdır. Kodda önce device temizlenip daha sonra tekrar oluşturulmaktadır. Şimdi düşünün bir oyun esnasında yanlışlıkla formu kapatmak zorunda kaldınız eğer form hemen kapanırsa o ana kadar veriler kaybolabilir işte bu gibi durumlarda yukarıdaki eventlar vasıtası ile kullanıcıya oyunu kaydetmek isteyip istemediğini sorabileceksiniz. FrameMove() fonksiyonunda oyun içeriği ile işlemler yapılabilir. Mesale yapay zeka, network uygulamaları oyun ile ilgili işlemler yapılabilir. Form içerisinde OnKeyPress eventı ile program içerisinde klavye hareketleri yakalanabilmektedir. Program içerisinde eğer esc(escape) tuşuna basılırsa formun kapanması sağlanmıştır. Kullanıcının klavye,mouse vs üzerindeki hareketlerinin yakalanması ve buna göre programın akışını değiştirmek oyun programlamada çok önemli olacaktır. Form üzerinde zaman işlemleri için micsoft'un hazırladığı ve directX sdk sı içerisinde gelen DXUtil.cs dosyasını kullanabilirsiniz. Bu dosyada bulunan static fonksiyonlar ile programınız içerisinde zaman tutabilir, iki komut arasındaki zaman farkını bulabilirsiniz. Bu FrameMove fonksiyonu içerisine aşağıdaki kodu yazarak formun başlığında zamanlayıcıyı sürekli olarak yazdırabilirsiniz.
float
this.Text=time.ToString();
Timer nesnesinin aşağıdaki fonksiyonları vardır.
Reset Uygulama zamanını resetler ve 0 yapar
Start Uygulama zamanı durdurulduktan sonra çalıştırılmasını sağlar
Stop Uygulama zamanını durdurur
Advance Uygulama zamanını 0.1 saniye ileriye alır.
GetAbsoluteTime Mutlak sistem saatini verir
GetApplicationTime Uygulama zamanını verir
GetElapsedTime İki işlem arasında geçen süre hesaplamada kullanılır. Örnek olarak
DXUtil.Timer( DirectXTimer.GetElapsedTime );
f = DXUtil.Timer( DirectXTimer.GetElapsedTime );
şeklindeki bir işlemde ilk satırda süre sayılmaya başlanır ikinci satırda bu sayılan süre alınır.
Makalede ya da kodlarda bulunan hatalar ya da sorularınız için mehmetaliecer@gmail.com adresinden bana ulaşabilirsiniz. İyi çalışmalar.
Mehmet Ali ECER
www.mehmetaliecer.com