9 Ekim 2011 Pazar

Projeye İçerik (Content) Eklenmesi ve Çizdirilmesi

Bir projede en önemli bileşenlerden biri de içeriktir. Hatta öyle ki, büyük oyunlarda (3 GB gibi) içerik projenin %99.99'unu kaplar. Çünkü çalıştırılabilir program olarak adlandırılan .EXE dosyaları sadece basit derlenmiş koddan başkasını içermez (gömülmüş içerikler hariç).

İçerik dosyaları o kadar gelişmiştir ki bazıları kod bile içerebilir. Bazen sadece kod içeren içerik dosyalarımız da olabilir. Bunlara script deriz. Bunları işlemek için kendimiz bir işleyici yazmamız gereklidir. Kendi script dilimizi yazmak istiyorsak önümüzde üç yolumuz vardır:
  1. Dosyayı gerçek zamanda kendimiz çözümleriz ve gerekli komutları yürütmeye çalışırız.
  2. Interpreter (Yorumlayıcı) şablonunu kullanırız.
  3. Parser Generator (Çözümleyici Üretici) kullanırız.
Bu üç seçeneği de kullanmak işimize gelebilir. Küçük çaplı ve çözümlemesi kolay bir dil tasarlamışsanız birinci seçenek çok daha iyi olacaktır. Fakat biraz genişletilebilirlik ve düzen istiyorsanız artık ikinci seçenek sizin için daha iyi olacaktır. İkinci seçenek script dilleri için yeterli olabilir. Fakat gerçekten günümüzde kullanılan programlama dillerine (Java, C++ gibi) yakın bir dil tasarlamak istiyorsanız üçüncü seçenek kaçınılmaz olacaktır. Oyunlarda genellikle ikinci seçenek kullanılmakla beraber bazı büyük oyun motorlarında üçüncü seçeneğinde kullanıldığına rastladım.

Bu kısımda iki boyutlu ve üç boyutlu içeriğin nasıl eklenileceğini göstermeye çalışacağım. İlk olarak iki boyutlu içerik ile başlayalım:

Bir önceki bölümde oluşturduğumuz projenin alt projesi olan içerik projesine Add>Existing Item... seçeneği ile diskimizde olan içerikleri ekleyebilir.

Oyunun içerikleri içerik projesine (Content Project) eklenir. Örnek olarak bir iki boyutlu doku (texture) dosyası ekleyelim.


Dosyayı gelen pencereden seçtikten sonra projemizde bu resmi temsil etmemiz gerekir. Aşağıdaki gösterilen google images'ten alınmış resmi bu şekilde göstermeye çalışacağız.


İki boyutlu resim (doku) dosyamız Texture2D sınıfı ile temsil edilir. Temsil etmek için Game1 sınıfımıza sınıf üye değişkeni ekleriz. Az sonra yukarıdaki resmi çizdireceğiz. Dolayısıyla ilk önce bu resmi yükleriz (atc.jpg) ve ardından kodda aşağıdaki değişiklikleri yaparız:

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D atcTexture; 

Burada ek olarak atcTexture nesnesi bizim resim içeriğimizi tutacaktır. Resmi diskten içerik yöneticimize almak için ise LoadContent metodunda şu kod çağrısını yazarız:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    atcTexture = Content.Load<Texture2D>("atc");
}

Farkedileceği üzere burada atc.jpg yerine atc ismini kullandım çünkü içerik isimleri uzantıdan bağımsız olarak tekil adlara sahip olurlar. Yani ben ayrıca atc.png veya atc.fbx diye dosyalar eklemek istersem bunlara başka içerik isimleri atamam gerekir. Varsayılan olarak dosyanın uzantısız ismi ve içerik ismi aynı olur. Bu yapıya sadık kalmak ileriki proje değişikliklerinde sorun yaşanmaması için iyi bir önlemdir.

Elimizdeki bu resmi artık resim işleyen her yerde kullanabiliriz. Örnek olarak ben elimizdeki resmi çizdereceğim.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();

    spriteBatch.Draw(atcTexture, Vector2.Zero, Color.White);

    spriteBatch.End();

    base.Draw(gameTime);
}

Bütün iki boyutlu çizimler SpriteBatch sınıfının Begin ve End metotları arasında olmalıdır. Buradaki Draw fonksiyonu basitçe elimizdeki resmi (0, 0) konumuna yani ekranın sol üst köşesinden başlayarak çizdirir.

Sonuç olarak böyle bir resimli ile karşılaşırız:


Fakat biz genellikle resmimizin bu sol üstten kırpılmış halini değil, ekran boyutu ile ölçeklenmiş halini görmeyi tercih ederiz. Bunu yapmak için ise:

spriteBatch.Draw(atcTexture, GraphicsDevice.Viewport.Bounds, Color.White);


Ayrıca bu kod herhangi bir ekran boyutu değişikliği karşısında tekrar yazım yapılmasını da engellemiş olur.

Üç Boyutlu İçerik Ekleme ve Çizdirme

Üç boyutlu modellerin eklenmesi iki boyutlu resimlerden çok farklı değildir. Texture2D yerine Model sınıfı kullanılması yeterlidir. Farklılık ancak çizimde ortaya çıkar. Bu bölüm üç boyut çizimin ayrıntısı ile ilgili olmadığı için basit örnek olarak bir araba modeli nasıl yüklenir ve çizilir bunu yazacağım.

İlk olarak modeli sınıf nesnesi olarak tanımlarız.

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D atcTexture;
    Model carModel;

carModel nesnesini de LoadContent fonksiyonu içinde yapılandırırız.

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    atcTexture = Content.Load<Texture2D>("atc");
    carModel = Content.Load<Model>("car");
}

Çizdirmek için Draw metodunu kullanırız. Aşağıdaki kod parçası sadece örnek amaçlıdır. Kamera veya ileri üç boyutlu çizim düzeltmeleri yapılmamıştır.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    Vector3 cameraPosition = new Vector3(0.0f, 300.0f, 450.0f);
    Vector3 lookAt = new Vector3(0.0f, 35.0f, 0.0f);

    Matrix[] transforms = new Matrix[carModel.Bones.Count];
    carModel.CopyAbsoluteBoneTransformsTo(transforms);
    
    foreach (ModelMesh mesh in carModel.Meshes)
    {
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.EnableDefaultLighting();
            effect.TextureEnabled = true;
            effect.World = transforms[mesh.ParentBone.Index] *
                Matrix.CreateRotationY(MathHelper.Pi / 2);
            effect.View = Matrix.CreateLookAt(cameraPosition, lookAt,
                Vector3.Up);
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45.0f), GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f);
        }
        mesh.Draw();
    }

    base.Draw(gameTime);
}

Sonuç olarak karşımıza siyah bir araba modeli çıkar:


Hiç yorum yok:

Yorum Gönder