Bu sayfadaki yazılar
Sayfanın metni
Sayfa 99
OpenGL, Direct3D gibi kütüphaneler ekran kartının en temel özelliklerini kullanmanızı sağlayan son derece “alt düzey” kütüphanelerdir. glBegin(GL_TRIANGLES)’larla, d3dDevice->SetTransform(D3DTS_WORLD, &matrix)’lerle demo yazmaya çalışmanın, kanımca tamamen assembly kullanmaktan çok farkı yoktur.
Bir obje çevirme işi için Direct3D’de üç fonksiyon, Ekrana bir sprite çizmek için OpenGL’de ondan fazla fonksiyon çağırmak abesliktir. Bu kütüphaneler zaten kendilerini olduk olmadık yerlerde çağırmayacağınız düşüncesi ile tasarlanmışlardır. Size sunduğu fonksiyonların amacı kendi grafik kütüphanenizin yapı taşlarını oluşturmaktır.
Dolayısıyla bu alt düzey kütüphaneleri daha verimli kullanmanızı sağlayacak, onları “wrap” edecek bir üst düzey sistem tasarlamalısınız. Bu sistem de en basit şekilde birçok global fonksiyondan oluşan basit bir kütüphane olacak.
Bu kütüphanenin ana işlevi, demolarınızı yazarken sık kullanacağınız çizim işlemlerini size tek fonksiyonla sağlamak olacak. Bunun yanı sıra doku, obje gibi sık kullanacağınız tipleri tanımlamak da yararlı olacaktır.
DrawSprite(logo, logoCercevesi) ;
Rotate(5.0f * time, 0.0f, 1.0f, 0.0f) ;
RenderState state = Renderer::Texture | Renderer::DepthTest ;
DrawMesh(kup, state) ;
Motorun bu kısmı, “grafik programlama” yapacağınız belki de yegane yer olacak. Çizim kütüphanelerinin size sunduğu imkanların dışına çıkmamak için hiçbir sebebiniz olmayacak. Kendi renk sınıflarınızı oluşturabilir, bunların kendi aralarında ilginç birleşme kurallarını belirleyebilirsiniz. Mesh manipülasyonundan başlayıp dokular üzerinde görüntü işleme gibi ufuklara yelken açabilirsiniz.
Demo Motoru Üzerine Son Sözler
Eğer bu üç ana kısmı hakkıyla bitirip yanına ek kütüphanelerle müzik çalmayı da eklerseniz ortalamanın epey üzerinde bir demo sistemine sahip olacaksınız. Bu sistemi kullanarak yaptığınız demolar, sıfırdan kodlanan demolardan çok daha az zaman alacaktır. Dahası işin teknik ayrıntıları yerine direk demoya odaklanacağınız için ortaya çıkacak ürünler de daha kaliteli olacaklardır.
Demo motoru bir kez yazıp ölene kadar kullanacağınız bir sistem değildir. Daha doğrusu, hiçbir sistemin tüm zamanlara uygun olma gibi bir özelliği olamaz. Siz kendinizi geliştirdikçe motorunuzu da geliştirecek; daha hızlı, daha esnek ve daha güçlü hale getireceksiniz. Özellikle renderer diye bahsettiğimiz kısım üzerinde belki demolar kadar vakit harcamanız gerekebilir. Siz tam kıvamında bir çizim kütüphanesi yazsanız bile, teknoloji sizden hızlı gideceği için bu kısmı yenileme ihtiyacı duyacaksınız. Ama tecrübelerim ile söyleyebilirim ki; yeni bir demoda, hem motora hem demoya ayıracağınız toplam süre, ilk demonuz için harcadığınız süreyle kıyaslanamayacak kadar kısa olacak.
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 98
// Demonun başında.
Framebuffer::Create(640, 480, BufferType::DoubleBuffer) ;
// Her frame sonunda.
Framebuffer::Swap() ;
Timeline
Demonuzda tüm zamanlama işlerini her frame'de bir artırdığınız bir tamsayı üzerinden yapabilirsiniz. İstediğiniz hızı elde edip başka bir bilgisayarda yaptığınız şeyi denediğinizde, elde edeceğiniz şey sadece hüsran olacaktır.
Eğer donanımı kesin kurallarla tanımlanmış bir platformda çalışmıyorsak, frame'lerin farklı konfigürasyonlarda farklı süreler alacağını bilmemiz gerek. Dahası tek konfigürasyonda bile tüm demo boyunca sabit bir frame hızı hayalleri kurmayalım.
Yapmamız gereken, tüm zamanlama işlerini sabit bir saat kaynağına göre senkronlamak ve elle tuttuğumuz sayaçlardan medet ummamak. Bunun için, bu sayıdaki derleme yazısında bulunan Timer gibi bir sınıfı kullanabiliriz.
Geriye sadece belli iki süre aralığında belli partları çalıştıran fonksiyonları çağırmak kalıyor. Bunun için her frame başında, demo başında başlattığımız sayacımıza bakıp hangi partları çizmemiz gerektiğini anlamalıyız. En basit yöntem tabii ki şöyle bir şey:
if(sure >= 5.0f && sure <= 12.0f) GirisParti() ;
if(sure >= 11.2f && sure <= 16.6f) Gecis1() ;
Aslında bu yöntem gayet de işe yarıyor ama işleri biraz daha kolaylaştırabiliriz. Tüm partların fonksiyon adreslerini, partların başlangıç ve bitiş süreleriyle birlikte bir listede tutup, bu listeyi bir fonksiyona sayacın o anki değeriyle yollayabiliriz. Bu fonksiyonun amacı sayaca bakıp hangi partların çalışması gerektiğini anlamak ve ilgili fonksiyonları çağırmak olacak.
Bazı partların zaman aralığını negatif sayılara çekip, örneğin -1 zamanıyla bunların çalışmasını sağlayabiliriz. Bunu, loading'te yapmanız gerekenleri yaptıracak bir kısayol olarak da düşünebilirsiniz. Tabii ki birçok if satırı yazmak yerine işleri daha da kolaylaştıracak her türlü yöntem makbuldür.
Ayrıca her partın kendi başlangıç sürelerine göre hangi konumda bulunduklarını bilmeleri iyi olabilir. Bunu, part fonksiyonlarını bu süreyi alacak şekilde tanımlayıp, çağrıldıkları zaman “demo süresi – part başlangıcı”nı bu fonksiyona yollayabilirsiniz. Bu sayede göstereceğiniz her türlü animasyonun zamanlamasının fps bağımsız olmasını garantileyebilirsiniz.
Motorun timeline kısmının hazırlanması belki de en karmaşık işimiz olacak. Kavramları oturtmak için Flash gibi animasyon hazırlama programlarının timeline kavramlarını inceleyebiliriz. Hazırlayacağımız sistem bunlardan çok farklı olmayacak.
Renderer
İnanılmaz OpenGL, Direct3D vs. biliyoruz. Bu kütüphaneleri kullanarak süper efektler hazırlıyoruz. Pek güzel, pek hoş. Tamamen farklı bir demoda, bambaşka bir efekt için yeniden dokuya çizim yapmamız gerekti. Yani ekrana değil direk ekran kartının bellek alanlarında bir yere çizeceğiz. Ne yapıyoruz peki? Eski koddan alıp aynen kopyala yapıştır. Sonra uymayan değişken isimlerini düzeltelim. Denedik, çalışmadı. Farklı bir doku tipi kullanmışız, farklı bir çizim modundayız. Neleri değiştirmemiz lazım? Hmm, tamam oldu gibi. O da nesi? Farklı çözünürlük olduğu için tüm oranlama hesapları yanlış!