Arşiv

Etiketlenen yazılar SoundEffectInstance

XNA Oyunu / Çanakkale Geçilmez – 1

11 Mayıs 2011 Yorum yapılmamış

Bu yazımı okumadan önce XNA konusundaki diğer makalelerimi okumanızı öneririm.

Bu sefer yapacağımız oyun, 30 Ağustos‘un ruhuna uygun olacak – Çanakkale Geçilmez.

Önce görsellerimizi verelim;

XNA - Çanakkale Geçilmez - Arkaplan XNA - Çanakkale Geçilmez - Düşman Gemisi XNA - Çanakkale Geçilmez - Top XNA - Çanakkale Geçilmez - Gülle XNA - Çanakkale Geçilmez - Karakterler XNA - Çanakkale Geçilmez - Sayılar

İki tane de ses dosyamız var;

Gemi Vuruldu Sesi

Arkaplan Müziği

Başlayalım oyunumuzu yazmaya; Çanakkale Geçilmez projemizi oluşturduktan ve Game1.cs‘in ismini GameLoop.cs olarak değiştirdikten sonra, class seviyesindeki değişkenlerimizi tanımlayalım;

public const int PENCERE_GENISLIK = 800;
public const int PENCERE_YUKSEKLIK = 600;
public const bool TAM_EKRAN = false;

Texture2D Arkaplan;

Oyun penceremizin sınırlarını tutacağımız Rectangle tipinde bir değişkeni class seviyesindeki değişkenlerimize ekleyelim;

Rectangle Pencere;

Gelelim bu değişkenleri kullanmaya, GameLoop class‘ımızın constructor methodunda aşağıdaki kodları yazalım;

graphics.PreferredBackBufferWidth = PENCERE_GENISLIK;
graphics.PreferredBackBufferHeight = PENCERE_YUKSEKLIK;
graphics.IsFullScreen = TAM_EKRAN;
Pencere = new Rectangle(0, 0, PENCERE_GENISLIK, PENCERE_YUKSEKLIK);

Ses dosyalarımız için class seviyesinde değişkenlerimiz tanımlayalım;

SoundEffectInstance ArkaplanSes;
SoundEffectInstance GemiVurulduSes;

LoadContent() method‘unda değişkenlerimize yükleme işlemlerini gerçekleştirelim;

Arkaplan = Content.Load<Texture2D>("Arkaplan");

ArkaplanSes = Content.Load<SoundEffect>("pong").CreateInstance();
GemiVurulduSes = Content.Load<SoundEffect>("ir_begin").CreateInstance();

ArkaplanSes.IsLooped = true;
ArkaplanSes.Volume = 0.3f;
ArkaplanSes.Play();

Ses dosyaları ile yaptığımız bu işlemleri XNA ile Pong oyunu yazalım – 2 yazımdan hatırlayacaksınız.

Bu oyunumuzda aktörleri Nesne Yönelimli Programlama (Object Orriented Programming) kurallarına uyarak oluşturalım; oyun projemize yeni bir class ekleyelim ve ismini GameObject.cs verelim.

Çanakkale Geçilmez oyunumuzda oluşturacağımız tüm nesneleri GameObject class’ından oluşturacağız.

public class GameObject
{
	public bool IsAlive;
	public Texture2D Texture;
	public Vector2 Position;
	public Vector2 Center;
	public Vector2 Velocity;
	public float Rotation;

	private Rectangle _TextureRectangle;
	public Rectangle TextureRectangle
	{
		get
		{
			_TextureRectangle.X = (int)Position.X;
			_TextureRectangle.Y = (int)Position.Y;

			return _TextureRectangle;
		}
	}

	public GameObject(Texture2D Texture)
	{
		this.IsAlive = false;
		this.Texture = Texture;
		this.Center = new Vector2(Texture.Width / 2, Texture.Height / 2);
		this.Position = Vector2.Zero;
		this.Velocity = Vector2.Zero;
		this.Rotation = 0;

		this._TextureRectangle = new Rectangle(0, 0, Texture.Width, Texture.Height);
	}
}

Yukarıdaki kodu incelediğimizde;

  • Oyun nesnesinin hala canlı olup olmadığını anlamak için IsAlive değişkeninin olduğunu
  • Oyun nesnesinin Texture‘unu almak için Texture nesnesinin olduğunu
  • Oyun nesnesinin ekrandaki yerini almak için Position değişkeninin olduğunu
  • Oyun nesnesinin kendi etrafında dönüş miktarını almak için Center ve Rotation değişkenlerinin olduğunu
  • Oyun nesnesinin hızını almak için Velocity değişkeninin olduğunu
  • Oyun nesnesinin ekranda kapladığı alanı bulmak için TextureRectangle özelliğinin olduğunu görürüz.

GameObject sınıfının constructor‘ı sadece bir Texture2D nesnesi alıyor ve bu parametreyi kendi iç değişkenlerinin değerlerini hesaplamada kullanıyor.

Artık GameLoop sınıfımızın class seviyesinde, Top nesnesi için, GameObject sınıfından değişken oluşturabiliriz.

public GameObject Top;

LoadContent() methodunda bu değişkenin atamasını yapalım;

Top = new GameObject(Content.Load<Texture2D>("Top"));

Update() methodunda Top nesnemizin yerini hesaplayalım;

KeyboardState ks = Keyboard.GetState();

if (ks.IsKeyDown(Keys.Left))
	Top.Position.X -= 5;
if (ks.IsKeyDown(Keys.Right))
	Top.Position.X += 5;

Aynı method içerisinde Top nesnemizin dönüş miktarını da hesaplayabiliriz; (Yukarı ve Aşağı tuşlarına basıldıkça 10 derece dönmesini sağlayacağız)

if (ks.IsKeyDown(Keys.Up))
	Top.Rotation += MathHelper.ToRadians(10);
if (ks.IsKeyDown(Keys.Down))
	Top.Rotation -= MathHelper.ToRadians(10);

MathHelper sınıfının static ToRadians fonksiyonu sayesinde, Top’umuzun dönme açısını radian cinsinden kolaylıkla hesaplayabiliyoruz.

Top‘umuzun dönme açısının -90 ile +90 dereceler arasında olduğundan ve ekrandan dışarı çıkmayıp, görünür olduğundan emin olalım;

if (Top.Position.X < 0)
	Top.Position.X = 0;
if (Top.Position.X > PENCERE_GENISLIK)
	Top.Position.X = PENCERE_GENISLIK;

if (Top.Rotation > MathHelper.ToRadians(90))
	Top.Rotation = MathHelper.ToRadians(90);
if (Top.Rotation < MathHelper.ToRadians(-90))
	Top.Rotation = MathHelper.ToRadians(-90);

Oyunun, Windows'ta başka bir pencereye geçilmesi esnasında (focus kaybetme) bekleme moduna geçmesini, tekrar oyuna dönüldüğünde ise (focus alma), kaldığı yerden devam etmesini sağlayalım;

Öncelikle sınıf seviyesindeki değişkenlerimize,

bool OYUN_DEVAM_EDIYOR = true;

ekliyoruz. Microsoft.Xna.Framework.Game sınıfından türetildiği için GameLoop sınıfının OnActivated ve OnDeactivated method’larını override edebiliriz.

OnDeactivated method’unda, oyun penceresinin focus kaybettiğini, OnActivated method’unda ise, oyun penceresinin focus aldığını anlayabiliriz.

protected override void OnActivated(object sender, EventArgs args)
{
  OYUN_DEVAM_EDIYOR = true;
  ArkaplanSes.Resume();
  base.OnActivated(sender, args);
}

protected override void OnDeactivated(object sender, EventArgs args)
{
  OYUN_DEVAM_EDIYOR = false;
  ArkaplanSes.Pause();
  base.OnDeactivated(sender, args);
}

Şu ana kadar oyunumuza hiç düşman eklemedik. Bir sonraki yazımda düşmanları ekleyeceğiz.

Top’umuzla da düşmanları vurup, puan kazanıyor olacağız.

XNA ile Pong oyunu yazalım – 2

11 Mart 2010 Yorum yapılmamış

XNA ile Pong oyunu yazalım – 1 yazıma bu yazı ile devam ediyorum.

XNA ile ekrana yazı yazdırmak için öncelikle Content projesi içerisinde bir spritefont dosyası oluşturmalıyız.

Pong projesi için ben Arial.spritefont ismini verdiğim dosyayı oluşturdum, “yorum satırları kaldırılmış halini” aşağıdaki gibi düzenledim;

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
	<Asset Type="Graphics:FontDescription">
		<FontName>Arial</FontName>
		<Size>16</Size>
		<Spacing>0</Spacing>
		<UseKerning>true</UseKerning>
		<Style>Regular</Style>
		<CharacterRegions>
			<CharacterRegion>
				<Start>&#32;</Start>
				<End>&#126;</End>
			</CharacterRegion>
		</CharacterRegions>
	</Asset>
</XnaContent>

Gördüğünüz gibi, font dosyası aslında font’un özelliklerini yazdığımız bir Xml dosyası.

GameLoop sınıfının değişkenlerine Arial font dosyamızı yükleyeceğimiz değişkeni de ekleyelim;

SpriteFont Arial;

LoadContent() method’unda Arial.spritefont dosyasını Arial değişkenine yükleyelim;

Arial = Content.Load<SpriteFont>("Arial");

Şimdi Draw() method‘una aşağıdaki kodları ekleyerek, oyuncuların skorlarını ekrana yazdıralım;

spriteBatch.DrawString(Arial, "Oyuncu 1 : " + Oyuncu1Skor, new Vector2((float)(PENCERE_GENISLIK * 0.05), 30), Color.Yellow);
spriteBatch.DrawString(Arial, "Oyuncu 2 : " + Oyuncu2Skor, new Vector2((float)(PENCERE_GENISLIK * 0.80), 30), Color.Yellow);

Bu kod parçası ile, spriteBatch değişkeninde yeralan DrawString() method’unu kullandık. DrawString() method’unun parametrelerine bakacak olursak;

  • Birinci parametre olarak, spritefont tipinde bir değişken alır
  • İkinci parametre, ekrana yazdırmak istediğimiz yazıdır
  • Üçüncü parametre olarak Vector2 tipinde yazıyı nereye yazacağımız bilgisini ister
  • Son olarak, yazının rengini verdiğimiz dördüncü parametre vardır

Biz, Pong oyununda ilk oyuncunun skorunu ekranın %5 kadar içine, ikinci oyuncunun skorunu ise ekranın %20 kadar içine yazdırdık.

Gelelim, oyunda ses çıkartmaya;

Öncelikle wav formatında iki ses dosyasını Content içerisine sürükleyip bırakalım.

Class seviyesindeki değişkenlere iki tane daha ekleyelim;

SoundEffectInstance ArkaplanSes;
SoundEffectInstance SkorSes;

LoadContent() method’unda bu değişkenlerin değerlerini atayalım;

ArkaplanSes = Content.Load<SoundEffect>("Pong").CreateInstance();
SkorSes = Content.Load<SoundEffect>("recycle").CreateInstance();

Gördüğünüz gibi, SoundEffectInstance tipinde iki değişken tanımladık. Bu değişkenlere Content içindeki ses dosyalarını yüklerken, SoundEffect tipinin CreateInstance() method‘unu kullandık.

Böylece ses değişkenlerimiz kullanıma hazır hale geldi.

LoadContent() method’una aşağıdaki kodları da ekleyerek, arkaplanda çalacak ses değişkeninin sesini %20 oranına düşürelim ve loop olmasını sağlayalım (Böylece ses dosyasının sonuna geldiğinde başa dönüp çalmaya devam edecek).

Son olarak Play() methodu ile, ses dosyasını çalmaya başlayalım;

ArkaplanSes.Volume = 0.2f;
ArkaplanSes.IsLooped = true;
ArkaplanSes.Play();

Update() method’unda oyuncuların skor kazandığı kodlara aşağıdaki satırı da ekleyelim;

SkorSes.Play();

Böylece oyuncular skor yaptıkça, SkorSes değişkeninde yüklü olan ses dosyası çalınacak.

İşte Pong oyunundan ekran görüntüsü. Oyunun kaynak kodlarını buradan indirebilirsiniz.

XNA Pong oyunun bitmiş hali