Bu yazımızda platform oyunlarının en temel tekniklerinden biri olan arka planı kaydırma olayını xna ile nasıl yapabileceğimizi inceleyeceğiz. Yapacağımız örnekte bu olay zamanla doğru orantılı bir şekilde çalışacaktır. Bu teknik aynı zamanda Shoot-Em Up türündeki oyunlarda da çok sık kullanılır. Örnek vermek gerekirse Commodore64 dönemindeki River Raid oyununu hatırlayanlar vardır belki. Bu oyunda sürekli yukarıdan aşağıya doğru kayan bir oyun dünyası vardır. Platform oyunlarında ise ekranın kaydığı yön genelde basılan tuşa göre değişkenlik gösterir. Örneğin Mario oyununda oyuncu sağa gitmek istediği zaman oyun sahnesi sola doğru kaymaya başlar. Oyuncu eğer herhangi bir yön tuşuna basmazsa oyun sahnesi sabit kalır. Diğer bir örnekte Prince of Persia oyunudur. Bu oyunda da sahnenin yukarı-aşağı ve sağ-sol olmak üzere kaydığı 4 farklı yön vardır. Şimdi biz de en basit haliyle arka planı nasıl kaydırabiliriz bunu inceleyeceğiz.
Uygulamaya Başlangıç
Öncelikle yeni bir Windows Game projesi oluşturalım.
Örneğimizin asıl amacı buradaki temel tekniği anlamak olduğu için, sahnelerin çok uzun olmasına gerek yok. Bu yüzden 3 farklı arka plan bizim için yeterlidir. Görüntüler farklı olabilir ama yanyana geldiklerinde mutlaka bir uyum içinde olması gerekiyor tabiki. Şimdi biraz teknikten bahsetmek gerekirse aslında çok basit olduğunu söylemek gerekiyor. Burada önemli olan resimlerimizin boyutlarıdır. Şöyle ki; ilk resmin ekranda xy(0,0) noktasında oluştuğunu düşünelim. Ozaman ikinci resim, ilk resmin devamı niteliğinde olacağı için bunun oluştugu nokta, xy(1.resmin_oluştuğu_X_noktası + 1.resmin_genişliği, 0) olacaktır. Dolayısıyla üçüncü resim de, xy(2.resmin_oluştuğu_X_noktası + 2.resmin_genişliği, 0) olacaktır. Böylece bir bütünlük sağlanmış olacaktır.
Kod yazmaya geçmeden önce bahsettiğim gibi örneğimiz için 3 tane resim hazırlamıştım. Bunları aşağıdan kopyalayıp, Content içine atabilirsiniz (isimlerini bg1, bg2, bg3 olarak kaydetmeyi unutmayın)



Şimdi ekrandaki nesneleri daha rahat kontrol edebilmek için projemize GameObject adında bir sınıf ekleyelim. Sınıfımızın yapısı son derece basit olacaktır. Ekranda gösterilecek imajı tutacak olan bir alan ve bunun boyutu ile poziyonunun tutacak birer alan yazmak örneğimiz için yeterlidir. Bunun dışında bu değerleri kolay bir şekilde set edebilmek için de constructor 'ı overload ediyoruz. GameObject sınıfı aşagıdaki şekildedir.
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;namespace XNAScrollingBackground
{
public class GameObject
{
public Texture2D texture;
public Vector2 size;
public Vector2 position;public GameObject(Texture2D texture, Vector2 size, Vector2 position)
{
this.texture = texture;
this.size = size;
this.position = position;
}
}
}GameObject sınıfımızı yazdıktan sonra Game1.cs dosyamıza dönelim ve aşağıdaki gibi her bir arkaplan için global olarak 3 tane GameObject nesnesi tanımlayalım
GameObject bg1;
GameObject bg2;
GameObject bg3;Daha sonra LoadContent() methodu içinde bunlardan birer tane nesne oluşturalım.
bg1 = new GameObject(Content.Load<Texture2D>("bg1"), new Vector2(500, 500), new Vector2(0, 0));
bg2 = new GameObject(Content.Load<Texture2D>("bg2"), new Vector2(500, 500), new Vector2((bg1.position.X + bg1.size.X), 0));
bg3 = new GameObject(Content.Load<Texture2D>("bg3"), new Vector2(500, 500), new Vector2((bg2.position.X + bg2.size.X), 0));Nesneleri oluştururken kullandığım son paremetreye dikkat ederseniz eğer, az önce yukarda açıkladığım yöntemi burada aynen uyguladığımı görebilirsiniz.
Şimdi Update() methodu içinde gerekli hesaplamaları yapalım ve bu nesnelerin posizyon değerlerini zamana göre değiştirelim. Hatta buna birde hız özelliği katalım.
if (bg1.position.X < -bg1.size.X)
{
bg1.position.X = bg3.position.X + bg3.size.X;
}if (bg2.position.X < -bg2.size.X)
{
bg2.position.X = bg1.position.X + bg1.size.X;
}if (bg3.position.X < -bg3.size.X)
{
bg3.position.X = bg2.position.X + bg2.size.X;
}Vector2 direction = new Vector2(-1, 0);
Vector2 speed = new Vector2(160, 0);bg1.position += direction * speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
bg2.position += direction * speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
bg3.position += direction * speed * (float)gameTime.ElapsedGameTime.TotalSeconds;Yukarıdaki kod bloğunu kısaca açıklamak gerekirse eğer; ilk olarak if blokları ile hangi resimden sonra hangisinin geleceğinin kontrolü yapılıyor. Ardından Vector2 tipindeki direction nesnesi ile ekrandaki resimlerin kayma yönü belirleniyor. Burada Vector2 'nin aldığı parametrelere dikkat ederseniz eğer bir X değeri ile bir Y değeri aldığını görebilirsiniz. Siz eğer X paremetresine -1 değerini verirseniz bu resimlerin sağdan-sola doğru kayması anlamına gelmektedir. Eğer bunu 1 yaparsanız bu sefer resimler soldan-sağa doğru kayacaktır. Aynı işlemi Y parametresi için yaptığınızda ise ekrandaki görüntünün yukardan-aşağı veya aşağıdan-yukarı dogru bir harekete sahip olmasını sağlayabilirsiniz. Yani diğer bir deyişle nesneleri Y ekseni üzerinde hareket ettirmiş olursunuz. Biz örneğimiz de sadece sağdan sola doğru bir kayma hareketi kullanacağımız için X paremetresine -1 ve Y parametresine 0 değerini vermeliyiz. Hemen ardından hareketin hızını kontrol edebileceğimiz ve yine Vector2 tipinde tanımlanmış speed adında bir nesne oluşturuyoruz. Hareket X ekseni üzerinde olduğu için de X paremetresine pozitif bir değer vermemiz hareketin hızını belirlememiz için yeterlidir.
Buraya kadar hem yönümüzü hemde hızımızı tanımladık. Fakat bu değerler henüz GameObject 'lerimiz üzerinde herhangi bir etki yaratmıyor. Bunu gerçekleştirmek için de son 3 satıra bakıyoruz. Bu satırlarda öncelikle yön ve hız değerleri çarpılıyor. Oluşan bu değer ile aynı zamanda oyunda geçen toplam saniye 'de çarpıldığı zaman artık elimizde zamanla, hıza ve yöne göre hareket eden bir arka plan oluşmuş oluyor.
Geriye sadece görüntüyü oluşturacak kodları Draw() methodu içine yazmak kalıyor. Son olarak aşagıdaki kodları da aynen Draw() methodu içine yazıyoruz.
spriteBatch.Begin();
spriteBatch.Draw(bg1.texture, bg1.position, Color.White);
spriteBatch.Draw(bg2.texture, bg2.position, Color.White);
spriteBatch.Draw(bg3.texture, bg3.position, Color.White);
spriteBatch.End();Artık projeyi çalıştırıp sonucu görebilirsiniz.
Son olarak tavsiyem bu tarz örneklerden sonra kaynak kod üzerinde çeşitli değişiklikler yapmanızdır. Böylece yaptığınız değişikliklerin oyuna nasıl etki ettiğini somut olarak görebilirsiniz. Bu da konuyu daha net anlamanıza yardımcı olacaktır.
Kaynak : http://www.xnadevelopment.com/tutorials/scrollinga2dbackground/ScrollingA2DBackground.shtml
Örnek Uygulama
Mehmet Aydın Ünlü
0 yorum:
Yorum Gönder