Yazýlarýmý Daha Kolay Takip Etmek Ýçin Týklayýn!

XNA’de MATRIX YAPISI ve MATRİSLER

yazan: 12/6/2008 8:10:00 AM

Merhabalar; bir önceki yazımda kısaca XNA’de hatta ve hatta genel oyun programlama dünyasında matrislerin nasıl kullanıldığından ve ne gibi avantajlar sağladığından kısaca bahsetmiştim. Bu yazımda ise XNA’de matris yapısı (struct) ile neler yapabiliriz, hangi metodu ne amaçla kullanabiliriz gibi konulardan bahsedeceğim.

Öncelikle tarzım olduğu üzere metotları tanıyalım, sonra nasıl kullanıldıklarından bahsedeceğim.

CreateRotationX() ->

CreateRotationY() ->

CreateRotationZ() -> Z ekseni etrafında dönme hareketini sağlayacak olan matrisi geri döndürür.

CreateTranslation() -> Bir yada daha fazla eksene göre, dorusal hareket sağlayan matrisi geri döndürür.

CreateScale() ->  varlığı ölçekleyecek bir matris geri döndürür.

CreateLookAt() -> Kameranın bakış açısındakileri gösteren bakış matrisini (View matrix) oluşturur. Kameranın yerini, görüntülerin yerini ve hangi yönün yukarı olduğunu biz  belirleriz.

Not: Kamerayı monitörümüz aracılığı ile görebildiğimiz alan için, mönitörün ekranıdır diyebiliriz, sonuçta perspektif bir bakış açısında, görüntünün başladığı sınır ekrandır sonra z indexine göre görüntü derinlik kazanır. Yada basitçe bir FPS (counter strike gibi oyunlar) oyununda karakterimizin gözleri kameradır diyerek bunu kafamızda canlandıralım.

CreatePerspectiveFieldOfView() -> Perspektif izdüşüm kullanarak, görünür alanın matrisini yaratır, görünür dünyayı bir matrisle temsil eder. Bu method ile bakış matrisini (View Matrix), ekranın görüntü oranını (Aspect Ratio) , yakın  ve uzak görüntü sınırlarını paremetre olarak kullanırız, dolasıyla bu metod, View Matriximize bağımlıdır. Özetle bu metot bir perspektif görüş için ekrandan itibaren görebileceğimiz son sınıra kadar trepezoit (yamuk) bir alan oluşturur.

Not: Aspect Ratio (ekran oranı) GraphicsDevice türünden bir aygıtın,

aygıt.ViewPort.width / aygıt.ViewPort.Height  şeklinde kurabileceğimiz bir oranla hesaplanır. Sonuç genellikle 4:3 veya 16:9 gibi günümüz standart oranlarıdır.

CreatePerspectiveOffCenter() -> View Matrix’ten bağımsız bir perspektif izdüşüm matrisi oluşturur.

CreateWorld() -> Dünya matrisimizi oluşturur.

Şimdilik bu kadar metodu anlatmanın yeterli olduğunu düşünüyorum; fazlasını merak edenler MSDN kütüphanesinden yaralanabilirler.

Metotlarımızı tanıdığımıza göre şimdi matrisleri nasıl kullanacağımız konusuna değinelim;

Öncelikle dünyamızı temsil edecek bir dünya matrisi tanımlayalım;

 

Matrix worldMatrix = Matrix.Identity;

 

Matrix.Identity birim matris geri döndürür.

Şimdi de hareket işlemini nasıl sağlayacağımızı görelim;

 

worldMatrix*= Matrix.CreateRotationX(1.0f)*Matrix.CreateRotationY(1.0f);

 

Bir önceki yazımda iki matrisi çarparak haraket sağlayabileceğimizi anlatmıştım. Burda da yaptığımız aynen bu. Sadece matrisin değerlerini XNA’e tanımlatıyoruz, biz bildiğimiz klasik anlamda matrisi görmüyoruz. Gördüğünüz gibi her çarpı (*) işareti bir hareket anlamına geliyor, ikinci * işaretinde Y ekseni etrafında bir birimlik hareket, birinci * işaretinde de Y ekseni etrafında bir birimlik hareket yapıyoruz. Yani nesnemiz tek bir işlem dizisinde art arda iki hareket yapmış oluyor;

Gördüğünüz gibi XNA’de nesnelere hareket vermek bu kadar kolay, yazının başında verdiğim metotları da çarpma değeri ile çarparak hareketi çeşitlendirebiliriz.

Altın kural şu; önce, dünyayı nesneyi vb. tanımlayan bir matris atıyoruz, sonra hangi hareketi yaptıracağımıza karar veriyoruz, nesnemizi temsil eden matrisi hareketimizi sağlayacak matrisle çarpıp nesne matrisimize bu sonucu atıyoruz. Gördüğünüz gibi XNA’de matrislerden korkmanızı gerektirecek pek bir şey yok.

Currently rated 3.8 by 5 people

  • Currently 3.8/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , , , , ,

XNA

XNA’de 3 BOYUT TEMELLERİ ve NESNELERİN HAREKET MANTIĞI

yazan: 12/5/2008 7:19:00 AM

Herkese merhabalar, uzun bir aradan sonra XNA hakkındaki yazılarıma devam ediyorum. Malum vizelerdi, Türkiye’ye dönüş heyecanıydı ödevlerdi … bir sürü bahaneden sonra, tekrar bir seri başlatmayı düşünüyorum. XNA’ de 2 boyut ve XNA’de multiplayer yazı dizilerim oldukça iyi tepkiler aldı. Desteğiniz için hepinize teşekkür ediyorum.

Bu yazımın konusu 3 boyuta girişten ziyade XNA’de 3 boyutun mantığını anlatmak olacak, önce mantığını kavrayalım, sonra zaten bizi kimse tutamaz. Öncelikle bazı konuları maddeler halinde inceleyelim, gerektiği yerde açıklayalım.

. XNA sağ el koordinat sistemini kullanır. Yani sağ elinizin parmak uçları X eksenini gösterirken avucunuz Y eksenini ve baş parmağınız da Z eksenini gösterir.

. XNA’de 2 tip iz düşüm (projeksiyon) vardır. İz düşüm bir nesnenin görüntüsünün mesafesine göre nasıl ölçeklendiğidir gibi bilgisayar oyunlarına özel bir tanım yapalım şimdilik. Bu iki tip sırasıyla;

-          Perspektif: Cisim uzaklaştıkça daha ufak gözükür, görülebilir genişlik artar.

-          Ortogonal: Bu tipte ise uzaklaşsa bile cismin boyutu değişmez, 2 boyut gibi düşünelim.

. Köşeler: Diğer bir deyişle “açısal oluşum noktaları” evrende bir nokta düşünün. Bu noktadan çıkan doğrular aralarında açıları oluşturacaktır. Örneğin hemen bulunduğunuz odanın tavanının köşesine bakın, sırasıyla biri X, biri Y, biri de Z ekseninde 3 doğru çıkıyor değil mi? Ve aralarında 90 derecelik dik açı var. Ve her şekil köşelerin birleştirilmsiyle oluşur, çocukken bulmacalarda noktaları birleştirdiğimizi hatırlayalım. Ve eğer bu noktaların her birinden 3 boyuta doğru çizgilir çıksaydı ne olurdu? Yanıt basit 3 boyutlu modeller. Az önceki örnekten devam edelim odadaki her köşeyi birbirine bağlayın ne oldu? Bir oda yani dikdörgenler prizması, değil mi.

Eh artık 3 boyutun unsurlarını biliyoruz peki bunları nasıl kullanacağız da bir oyun ortaya çıkacak?

XNA’de köşeler:

XNA’de köşeler, yerlerini ve diğer özelliklerini renk vb. içeren yapılar (struct) yardımı ile tanımlanırlar.

VertexPositionColor -> bu yapı ile bir köşe (vertex); yeri (position) ve rengi (color) ile tanımlanır.

VertexPositionTexture -> bu yapı ile bir köşe; yeri ve dokusu (texture) ile tanımlanır, desenin kendi içinde (0,0) desenin sol üst; (1,1) desenin sağ alt köşe limitidir.

VertexPositionColorTexture -> yukarıdaki iki yapının bileşimi gibi düşünelim.

VertexPositionNormalTexture -> bir normal vektörü ve bunun yanında yer ve desen tanımlanır.

XNA’de köşeleri birleştirmek için; GraphicsDevice.DrawPrimitives metodu kullanılır, bu metodun ilkel tipler (Primitive Types) için tanımlanmış enumaration değerlerine göre köşeler bir düzen içinde birleştirilir. Buradaki ilkel tipler programlama dillerindeki int, float vb. ilkel tiplerle karıştırılmamalıdır. Bahsettiğimiz Enum değerleri, 1. Parametre olarak kullanılacaktır; hepsi PrimitiveType. xxxx  şeklinde kullanılabilirler. Bu metodu kullanmadan önce Vertex buffer dediğimiz bir köşe listesini oluşturmamız gerekir. Bunu da Enum değerlerini gösterdikten sonra anlatacağım.

.PointList -> Köşe listesinde (Vertex Buffer) bulunan her vertex birbirinden bağımsız birer nokta şeklinde çizilir.

.LineList -> Köşe listesindeki köşeler sırayla ikişerli olarak gruplandırılır ve her ikilinin arası bir çizgi ile doğrusal olarak birleştirilir.

.LineStrip -> Köşe listesindeki köşeler sıra ile art arda birleştirilir.

.TriangleList -> Köşe listesindeki köşeler üçer üçer gruplandırılır, her üçlü bağımsız bir üçgen oluşturur.

.TriangleStrip -> Her yeni üçgen kendinden önceki üçgenin son iki noktası kullanılarak oluşturulur, dolayısı ile üçgenler bağlıdır, ilk üçgen dışındaki üçgenler için tek nokta gerek ve yeterlidir.

.TriangleFan -> İlk köşemiz tüm üçgenlerin tepe noktası olur ve üçgenler birfan şeklinde oluşur. Buna örnek olarak ikiye kesilmiş portakalı verebilirim, orta noktasını ilk noktamız kabul edersek, her dilim bir üçgen oluşturacaktır, tepe noktaları ortak olacaktır.

GraphicsDevice ekranKartı;

Şeklinde tanımlanmış bir aygıtımız olduğunu varsayarak; Bir  Vertex buffer ‘ı(Köşe Listemizi) nasıl oluşturacağız; buna bakalım;

VertexBuffer köşeListesi;

           // Diyerek bir VertexBuffer tanımlamış olalım. 

VertexPositionColor[]  köşeler= new  VertexPorsitionColor[10];             

//10 köşe barındıran bir dizi oluşturduk;

köşeler[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),Color.White);

            // gibi bir kodla tüm köşelerimizi atayacağınızı varsayıyorum; 

köşelListesi = new VertexBuffer (ekranKartı, 10* VertexPositionColor.SizeInBytes,

                 BufferUsage.WriteOnly);

// diyerek Vertex Bufferımızı oluşturduk. Buradaki 10 listemizdeki eleman sayısı.

 

Yukarıda fark etmişsinizdir; Köşemizin yerini belirlerken Vector3 diye bir yapı kullandık; peki bu yapı nedir?

Adından da anlaşılacağı üzere Vector3 yapısı 3 boyutlu bir vektör tutar, yani X, Y ve Z koordinatlarından oluşan bir vektörü tutar. Vektör denince kafası karışanlar için, buna noktanın tanımlandığı hacim (dünya, oda … vb 3 boyutlu bir mekan) içerisindeki yerini belirtir diyelim. Yani odanın duvarında duran X ve Y koodinatlarına sahip bir sinek değil de odada uçan, oda hacmi içinde herhangi bir yerde olan sineğin konumu Smile.

Madem Vector3 yapısına (struct) giriş yaptık kısaca metotlarının bazılarından bahsedivereyim;

Vector3.Distance() -> verilen iki nokta arasındaki uzaklığı hesaplar.

Vector3.Add()

Vector3.Subtract() -> bu metotlar, vektörel toplama ve çıkartma yapar. Yani X değerleri  X Değerlerinden, Y değerleri Y değerlerinden … çıkartılır.

Vector3.Multiply()

Vector3.Divide() -> Bu iki metor  iki vektör arası çarpma bölme işlemi veya verilen bir sayı ile bir vektörü çarpıp bölme işini yapar.

Vector3.Clamp() -> Vektörü verilen sınırların içinde tutar, sınırın dışarısında bir değer almasını engeller; yani yukarıdaki örnekteki sinek bu metot yardımı ile odanın dışına çıkamaz.

Vector3.Lerp() -> İki vektör arası doğrusal interpolasyonu hesaplar.

Vector3.SmoothStep() -> Verilen bir değeri ağılık kabul ederek, iki vektör arası interpolasyonu hesaplar.

 

Bunlardan ayrı olarak yine Vector3 yapısına dahil özelliklerden bazıları da;

Vector3.Zero -> Geriye tüm değerleri 0 olarak atanmış bir vektör döndürür. (0,0,0)

Vector3.Up -> Yukarıya bakan bir vektör döndürür (0,1,0)

Vector3.Right -> Sağa bakan bir vektör döndürür (1,0,0)

Vector3.Forward -> Sağ el koordinat sistemine göre ileri giden bir vektör döndürür (0,0,-1)

Vector3.Left , Vector3.Down, Vector3.Backward

Vector3.UnitX -> bir birim X vektörü döndürür (1,0,0)

Vector3.UnitY, Vector3.UnitZ

 

Peki bir nesne (model) köşelerin birleştirilmesinden oluşuyorsa ve her köşe bir vektör olarak temsil ediliyorsa, Oyunun geçeceği dünya nasıl temsil edilmeli?

Yanıt matrisler, eğer içinde bulunduğumuz oda bir 3 boyutlu matrisle temsil ediliyor olsaydı, kağıt üzerinde sineğimizin nerede uçuyor olduğunu işaretleyebilecektik.

XNA’de matrisler, bir nesnenin rotasyonunda (bir eksen etrafında dönme hareketleri), ölçeklendirilmesinde (uzağa giden nesne küçülür) ve translasyonunda (sabit yönlü hareket) kullanılır.

Eğer matris kullanmıyor olsaydık, bir nesnenin tüm hareketleri için vektörün her bir değerine tek tek ulaşıp o değeri değiştirecektik. Ama bu işi iki matrisin arasındaki matematiksel işlemler aracılığı ile yaparsak hem X, Y ve Z değerlerine ayrı ayrı ulaşmak zorunda kalmayacağız hem de her bir işlemi tek tek uygulamak yerine aynı anda hem haraket ettirebilecek hem de nesnenin boyutunu değiştirebileceğiz.

Matrislerin kullanılmasının bir diğer sebebi ise çağdaş ekran kartlarının tümünde GPU üzerinde matris algoritmaları olması, böylece CPU üzerine binecek yükten de kurtulmuş oluyoruz.

Bir nesneye Matris işlemleri ile haraket nasıl verilir?

Bir noktamız var koordinatları (20,10,30) olsun. Bunu 30 birim yukarı hareket ettirmek istiyoruz. Bunu nasıl yapacağız?

Sonunda Lineer Cebir dersleri bir işe yarıyor ve matrislerde çarpma yapıyoruz.

         [1, 0, 0, 0]

[20,10,30,1] x|0, 1, 0, 0|  = [20, 40, 30, 1]

                     |0, 0, 1, 0|

                     [ 0,30,0, 1]

Gördüğünüz gibi y değeri 30 arttı.

Eğer bu işlemde, ilk matrisimizde en sondaki 1’i arttırsaydık 60 birim ilerlemiş olacaktık, yani bu ilerleme katsayısıdır.

Eğer, İkinci matristeki köşegende bulunan 1’leri  arttırsaydık, nesnemizin boyu büyüyecekti, yani bu köşegen de nesnemizin ölçeklendirilmesinden sorumlu.

Ve aynı zamanda eğer ikinci matrisimizde sin ve cos değerleri kullanıyor olsaydık, nesnemiz dönme hareketi yapacaktı. Gördüğünüz gibi neredeyse hiç uğraşmadan tek matris işleminde nesnemizi hareket ettirdik.

Yazımı bitirmeden önce son bir şey söylemek istiyorum, matrisler sizi korkutmasın çünkü bu işlemleri XNA sizin için Matrix sınıfı aracılığı ile yapıyor, buradaki amacım size işin işleyiş mantığını göstermekti. Bir sonraki yazımda size Matris sınıfından bazı işlevlerinden bahsedeceğim, Eğer zaman bulursam Efektlere de tanıtma niyetinde bir giriş yapmak istiyorum. Hepinize kolay gelsin.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

NetworkSession Sınıfı ve İçindeki Olaylar (Eventler)

yazan: 9/10/2008 6:22:00 AM

Yazılarımı okurken bir arkadaşımın kafasına iki soru takılmış, birincisi 5 yazılık dizimde hiç bahsetmediğim diğer evenler nedir ne işe yarar? İkincisi ise delagate nedir; fonksiyon falan temsil ediyormuş ama nasıl yapacağız bunu? Sorulardan birincisine hazır elimi XNA’e bulamışken hemen cevaplandırayım, özel bir cevap yazmamamın nedeni bu sorunun diğer okuyucularımın da aklına takılabileceği düşüncesi. Hemen başlıyorum.

Öncelikle şunu belirteyim bu yazıyı, 5 yazılık proje boyunca hazırlamış olduğumuz proje üzerinden anlatacağım, bunun nedeni orada zaten kullanılmış olaylarımızın olması. Hemen onların altına eklemek suretiyle kodla da görebilirsiniz.

//oyun içinde gelişmesi muhtemel olaylar:

// Önceden bildiğimiz bu event oyuncu katılınca tetiklenir

session.GamerJoined +=

new EventHandler<GamerJoinedEventArgs>(session_GamerJoined);

//Oyuncu oyundan ayrıldığında bu olayı tetiklemesi gerekir.

session.GamerLeft +=

new EventHandler<GamerLeftEventArgs>(session_GamerLeft);

//Oyun başlarken, gerekli ayarları yapmamız için tetiklememiz gereklidir

session.GameStarted +=

new EventHandler<GameStartedEventArgs>(session_GameStarted);

//Oyun bittiğinde tetiklersek, verileri temizleme işi kolay olacaktır

session.GameEnded +=

new EventHandler<GameEndedEventArgs>(session_GameEnded);

//Bir oturum kapanırken tetiklenir,

session.SessionEnded +=

new EventHandler<NetworkSessionEndedEventArgs>(session_SessionEnded);

//Eğer Host çıktıysa, ve Oyunumuz host değiştirmeye izin veriyorsa

//host değiştiğinde tetikleriz ve oyun üzerindeki kritik değişiklikleri yaparız.

session.HostChanged +=

new EventHandler<HostChangedEventArgs>(session_HostChanged);

burada parantez içinde verilen değerler Delegate’dir ve bir fonksiyonu temsil ederler. Bunu değişkenin bellek adresini gösterip içine ulaşmak için referans oluşturması gibi düşünelim şimdilik, ayrıntıyı Delagate’ler ile ilgili yazımda bulabilirsiniz. Burdan sonrada olayın tetiklenmesinden sonra işleyişe konulacak metotları yazmamız gerekiyor bunlara da event handler diyoruz. (İleride Event Handlerlar ile ilgili bir yazı da yazmayı düşünüyorum.)

şimdi event handler (olay işleyici) metotlarımızın isimlerine dikkat; az önce parametreye yazmıştık. Aslında mantık olarak bu metotları önce vermek daha anlaşılır olurdu galiba, kusura bakmayın.

void session_GamerJoined(object sender, GamerJoinedEventArgs e)

{

    if (e.Gamer.IsHost)

        durum = "Host oturum açtı";

    else

        durum = "Oyuncu: " + e.Gamer.Tag + ", oyuna katıldı";

}

Yukarıdak metodu yazmıştık daha önce;  şimdi diğer event handler metodlarını da yazalım, kullanmasak bile en azından ihtiyacınız olduğunda fikriniz olur.

void session_GamerLeft(object sender, GamerLeftEventArgs e)

{

    durum = "Oyuncu " + e.Gamer.Tag + " oturumdan ayrıldı!";

}

void session_GameStarted(object sender, GameStartedEventArgs e)

{

    durum = "Oyun Başladı";

}

void session_HostChanged(object sender, HostChangedEventArgs e)

{

    durum = "Önemli: " + e.OldHost.Tag + " Hostluğu bıraktı yeni host:" +

               e.NewHost.Tag;

}

Bu event ve Handler’ı için çok önemli bir nokta var atlamayalım derim, bu eventi gerçekleştirebilmek için;

    oturum.AllowHostMigration = true;

olması gerekmektedir.

void session_SessionEnded(object sender, NetworkSessionEndedEventArgs e)

{

    durum = "Oturum sonlandı.";

}

void session_GameEnded(object sender, GameEndedEventArgs e)

{

    durum = "Oyun sonlandı.";

}

Özetle budur; bu metotların içini oyununuza göre doldurmalısınız. Eğer bir gün gaza gelirsem tüm yazılarımı içeren bir örnek oyun yapabilirim göstermek için; fakat İspanya muhabbetlerinden dolayı şu an müsait değilim.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , , ,

XNA

XNA'de Multiplayer Network Temelleri – 5

yazan: 9/9/2008 8:36:00 AM

4 yazı planlamıştım ama 5. yazımla karşınızdayım. Bir önceki yazımda bu yazıda gerekli olacak tüm açıklamayı yapmıştım bunları tekrarlamak istemiyorum. Bu nedenle XNA’de Multiplayer Network Temelleri – 4 adlı yazımı mutlaka okuyun. Hemen konuya kaldığım yerden dalıyorum

AgIsleri.cs’de; ağda paketlerimizi SendData() ile gönderip RecieveData() ile almadan önce paketlerimizi (ağ mesajlarımızı) yazmamızı ve okumamızı sağlayacak nesnelerimizi üretiyoruz.

        PacketWriter paketYazici = new PacketWriter();

        PacketReader paketOkuyucu = new PacketReader();

Şimdi mesajlarımızı yollamaya geldi sıra;

        public void MesajAt(string mesaj)

        {

            // aynı makinadaki tüm oyunclar – PC için gereksiz.

            foreach (LocalNetworkGamer oyuncu in oturum.LocalGamers)

            {

                // göndermeden evvel mesajı pakete yazıyoruz

                paketYazici.Write(mesaj);

    // paketi güvenlik tedbiri olmadan yolluyoruz “none”                   

    // diyerek. İlk parametre gördüğünüz gibi; yazılan

    // paketi barındıran, PacketWriter tipinde nesne

                oyuncu.SendData(paketYazici, SendDataOptions.None);

                durum = "Mesaj yollandı: " + mesaj;

            }

        }

Bu arada ilk çnceki yazımda bahsetmedim sanırım, SendData() metodunun bir overload’u sayesinde paketi istediğimiz herhangi bir oyuncuya yolayabiliyoruz, bunu yapmak için 3. parametreye NetworkPlayer tipinde oyuncu belirtmemiz gerekiyor. 3. parametre yoksa mesaj tüm oyunculara gider.

Sıra mesajları alacak fonksiyonun yapısına geldi. Ama önce RecieveData() metodunun gelen paketten, veriyi (byte[] veya PacketReader tipinde) ve gönderen kullanıcıyı (NetworkGamer tipinde) bize sunduğunu söylemek istiyorum.

        public void MesajAl ()

        {

            NetworkGamer uzakOyuncu; // Paketi yollayan oyuncu

            foreach (LocalNetworkGamer yerelOyuncu in oturum.LocalGamers)

            {

                // Ağda alınmamış veri olduğu sürece, almaya devam ediyoruz

                while (yerelOyuncu.IsDataAvailable)

                {

                    yerelOyuncu.ReceiveData(paketOkuyucu, out uzakOyuncu);

                    // farklı makinadaki oyunculardan mesaj alıyoruz

                    if (!uzakOyuncu.IsLocal)

                        durum = "Alınan mesaj: " +

                        paketOkuyucu.ReadString();

// burada gönderilen veriye göre ReadString() //metodunu seçtik verinin türü başka olsaydı uygun //metodu seçecektik.

                }

            }

        }

Mantık basit, veri olduğu sürece ağı taradık ve bilgileri aldık, alırken mesaj içeriğini PacketReader nesnesine oyuncu bilgisini de NetworkGamer den ürettiğimiz nesneye aktardık. Out anahtar sözcüğüne dikkat.

Son olarak da mesajın içeriğini çözdürdük.

Şimdi sıra Game1.cs den bu metotları çağırmaya geldi. Sadece oyun “Playing” durumunda iken mesajlarımızı iletmek istiyoruz bu nedenle update metodunda;

            // sadece playing durumunda mesajlaşmaya izin ver

            if (agYardimcisi.OyunDurumu == NetworkSessionState.Playing)

            {

                // basılmış tuşun bilgisini string olarak karşıya yolla

                foreach (Keys tus in Keyboard.GetState().GetPressedKeys())

                    agYardimcisi.MesajAt(tus.ToString());

                // aynı şekilde karşıdan al

                agYardimcisi.MesajAl();

            }

Böylece paket alışverişini sağlamış olduk. Böylece bu uzun XNA’de multiplayer network temelleri adlı serimizi bitirmiş olduk. Yazılanları geliştirin, bazı yerleri kurcalayın, bazı eklemeler yapın, tuşlar ekleyin menu oluşturun hem böylece kodun nerede ne tepki vereceğini daha iyi anlamış olursunuz.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , , , ,

XNA

XNA'de Multiplayer Network Temelleri – 4

yazan: 9/9/2008 7:21:00 AM

Şimdiye kadar ilk yazımda host oluşturmayı öğrendik; ikinci yazımda senkron, üçüncü yazımda da asenkron olarak hostu aramayı ve hosta bağlanmayı öğrendik, şimdi hosta bağlı olduğumuza göre sıra oyunu başlatmaya, oyunu oynamaya ve oyunu sonlandırmaya geldi. Biraz önbilgi vererek bu konuya başlayalım.

Şu ana kadar yaptığımız her şeyle oyun durumunu yada orijinal adıyla “NetworkSessionState”i hazır duruma geçirdik. Multiplayer oyunlarda hostun ve oyuncuların; tüm oyuncuların giriş yapmasını ve hostun oyuna başla komutunu vermesini, bekledikleri yere “lobby” denir. Diğer bir değişle oyunumuz bu durumda NetworkSessionState.Lobby durumundadır ve bu anda oyuncular oyuna başlayabilmek için durumlarını ready yapmalıdırlar bu da oyuncuya(LocalNetworkGamer sınıfından türeyen oyuncuyu temsil eden nesneye) ait IsReady özelliğini True yapmakla olur.

Bu yazımızın konusuna gelirsek, oyunu başlattığımızda; ağın durumunun Lobby’den Playing (oynanıyor) durumuna geçmesi gerekir. Bu da oturum nesnemizin StartGame metodoyla sağlanacaktır.

Bu halledildikten sonra artık çoklu ortamda, oyundasınız. Bu durumda bilgisayarlar arası haberleşme yaptırmanız gerekmektedir. Bunu da bilgisayarlar arasında paket transferi ile yapabilriz. Bir paketi PacketWriter türünden bir nesnenin Write() metodu ile hazırlarız. Sonra bu paketi oyuncuyu temsil eden nesnenin SendData() metodu ile göndeririz. Gelen paketi ise oyuncuya ait RecieveData() metoduyla ağdan çeker alırız. Ve paketin içeriğini PacketReader türünden okuyucu nesnenin Read…..() metodu ile çözeriz (okuruz).  Buradaki …. Kısmında türe göre metot seçilmelidir, örneğin fare koordinatları için ReadVector2() gibi…

Tüm bu paket alış-verişi işinde önemli olan nokta; Verilerin gönderiliş ve alınış türlerinin aynı olması ve paket gönderme sırasının, paket alma sırasıyla uyumlu olmasıdır.

Önemli olduğunu düşündüğüm için SendData() metodunun 2. parametresi hakkında bilgi vermek istiyorum metodu birazdan kodda göreceksiniz;

2. parametre paketin gönderiliş yöntemini belirler, SenderDataOptions enumuna dahil olan seçeneklerden,

None: paketin karşı tarafa ulaşacağını garantilemez,

InOrder: paketleri belirli bir sırayla yollar ama ulaşıp ulaşamayacağını garantilemez.

Reliable: paketler karşı tarafa ulaşırlar (garantili), ama sıraları belirli değildir.

ReliableInOrder: paketler sıralı olarak karşı tarafa ulaşır.(garantili)

Durum bu; buradan seçeceğiniz özellik paketlerinizin türüne göre değişmelidir. Çok da önemli olmayan paketler için en güvenli yolun kullanılması boşuna işlemcinin doldurulmasıdır.

Şimdi koda geçelim, eğer açıklamalara göz attıysanız pek anlamakta sıkıntı çekmeyeceksiniz ama herhangi bir durumda iletişime geçmekten çekinmeyin.

1. Adım tüm oyuncuları hazır hale getirmek ve oyunu başlatmak:

AgIsleri.cs’de oyuncuları hazır hale getiriyoruz.

public void OyuncuyuHazırla()

        {

            /* foraeach'in amacı aynı makinede oynayan oyuncuların

            hepsini hazır etmektir ama PC'de daima 1 local oyuncu

            olacağı için Pc oyununda foreach'e gerek yoktur.

             */

            foreach (LocalNetworkGamer oyuncu in oturum.LocalGamers)

                oyuncu.IsReady = true;

        }

Game1.cs den de oyuncunun arayüzden hazırım demesini sağlıyoruz ben “R” (ready) tuşunu seçtim.

            if (Keyboard.GetState().IsKeyDown(Keys.R))

                agYardimcisi.OyuncuyuHazirla();

AgIsleri.cs ye geçelim. Eğer tüm oyuncular hazırsa host oyunu bu metod ile başlatmalı:

//eğer herkes hazır durumdaysa oyunu başlatacak

        public void HerkesHazırsaBaslat()

        {

            if (oturum.IsHost)

            {

                if (osturum.IsEveryoneReady)

                    oturum.StartGame();

            }

        }

Şimdi bize bir de oyunun(ağın) durumunu gösteren bir değişken lazım ki Game1.cs ye geçince bize durumu anlatabilsin.

        public NetworkSessionState OturumDurumu

        {

            get

            {

                if (oturum == null)// oturum yoksa

                    return NetworkSessionState.Ended;

                else

                    return oturum.SessionState;

            }

        }

Şimdi Game1.cs ye geçip, herkes hazırsa hosta oyunu başlattıracak kodu yazalım:

//loby durumundayken herkes hazırsa oyun başlar.

            if (agYardimcisi.OturumDurumu == NetworkSessionState.Lobby)

            {

                agYardimcisi.HerkesHazırsaBaslat();

            }

Burada elimde olmayan nedenlerden ötürü (birinin sahur yemeğini pişirmesi gerekiyor) yazımı kesiyorum. Veri paketlerinin işlenmesini aynen kaldığım yerden devam ederek anlatacağım, yukardaki öntanımlar bir sonraki yazı için aynen geçerlidir.

 

Currently rated 4.0 by 4 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

XNA'de Multiplayer Network Temelleri – 3

yazan: 9/6/2008 10:00:00 AM

Bu yazımın konusu da Host edilmiş oyunu Asenkron olarak bulmak ve dahil olmak. Bu işin senkron olarak yapılışı için bu yazıma bakabilirsiniz.

Asenkron aramanın senkron aramaya göre avantajı senkron aramada olduğu gibi arama sonuçlanana kadar hostun duraksamıyor olması. Bu nedenle tercih edilen yöntemdir. Önce ön tanım yaparak yazıma başlıyorum.

IAsyncResult : Asenkron olarak iş görebilecek metotları barındıran sınıflar bu Interface’den türer. Asenkron bir işi başlatan metotların geri dönüş değeridir (NetworkSession.BeginFind() gibi). Ve Asenkron bir işi bitiren metotlarda 3. parametrenin tipidir (NetworkSession.EndFind() gibi) Ve ayrıca işleri bitince AsyncCallback delegate’lerine parametre olarak aktarılırlar. 

Yapacağımız iş özetle şu; BeginFind() metodunu çağırcağız geri dönüş değerini AsyncOturumBul değişkeninde saklarken, işini bitirdiğinde 4. parametresinde verilen delagate’in gösterdiği metoda gidecek ve giderken biz belirtmesek de IAsyncResult’un özelliği olarak sonucu da beraberinde parametre olarak götürecek. Ve burada EndFind() ile aramayı bitirirken  geri dönüş değeri olark bulduğu oturumların listesini oradaki değişkenimize aktaracak. Gerisi senkron aramanın aynısı. Şimdi karışık geliyor olsa da kodu inceledikçe anlayacaksınız.

AgIsleri.cs dosyamıza değişkenler arasına şunu ekleyelim:

        /*asenkron arama için IAsyncResult türünde bir nesne tanımlıyoruz;

          dikkat edilmesi gereken nokta, aramaya başlayan metodun

          geri dönüş tipi bu Interface türündendir.*/

        IAsyncResult AsyncSonuc = null; 

Artık asenkron aramada kullanacağımız metodu yazabiliriz,

        public void AsenkronOturumAra()

        {

            durum = "Asenkron arama başlatıldı.";

            if (AsyncSonuc == null)

            {

                AsyncSonuc = NetworkSession.BeginFind(

                    NetworkSessionType.SystemLink, maxLocalOyuncu, null,

                    new AsyncCallback(BulunanOturumlariAra), null);

            }

        }

BeginFind() metodunun ilk 3 parametresi senkron aramadaki Find metoduyla aynı, 4. parametre arama işi sonuçlandığında gideceği metodu tutan bir delegate , 5. parametre ise aramanın durumunu tutabiliyor.

İşimiz burada bitmiyor tabiki, şimdi arama bitip sonuçlar hazır olduğunda delegate aracılığı ile gidilecek metodu yazalım;

        // görüldüğü gibi buradaki parametre yukarıda kullandığımız       

  // AsyncSonuc ile aynı türden zaten buraya da ta kendisi

  // gelecek parametre olarak

  public void BulunanOturumlariAra(IAsyncResult result)

        {

            // bulunan tüm oturumları tutacak

            AvailableNetworkSessionCollection uygunOturumlar;

            // katılacağımız oturumu tutacak

            AvailableNetworkSession uygunOturum = null;

            if (AsyncSonuc.IsCompleted)

            {

                // EndFind’ın geri dönüşü koleksyon şeklinde

                uygunOturumlar = NetworkSession.EndFind(result);

                // Oyucuncu için slota sahip olan bir oturum arıyoruz

                foreach (AvailableNetworkSession aramadakiOturum in uygunOturumlar)

                {

                    int OturumSlotlariToplami =

                                      aramadakiOturum.OpenPublicGamerSlots +

                                      aramadakiOturum.OpenPrivateGamerSlots;

                    if (OturumSlotlariToplami > aramadakiOturum.CurrentGamerCount)

                    uygunOturum = aramadakiOturum;

                }

                // Uygun bir oturum bulunduysa, bağlan

                if (uygunOturum != null)

                {

                    durum = " " +

                    uygunOturum.HostGamertag + " adlı hostta

                                        uygun oturum bulundu.";

                    oturum = NetworkSession.Join(uygunOturum);

                }

                else

                    durum = "Hiç uygun oturum bulunamadı.";

            }

 

                // Arama sonucunu sıfırlayıp değişkeni temizliyoruz.

                AsyncSonuc = null;

        }

       

Böylece Asenkron aramayı da tamamladık geriye herzaman olduğu gibi Etkileşim tuşu kalıyor. Ben “A” (asenkron ara) seçiyorum.

// Asenkron olarak oturum ara

            if (Keyboard.GetState().IsKeyDown(Keys.A))

                agYardimcisi.AsenkronOturumAra();

Böylece asenkron arama konusunu da halletmiş olduk. Network temelleri konusu da artık bitmek üzere çok az kaldı. Bir dahaki yazıda görüşmek üzere

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , , ,

XNA

XNA'de Multiplayer Network Temelleri – 2

yazan: 9/6/2008 6:25:00 AM

Bu yazımın konusu host edilmiş oyunu senkron şekilde bulmak olacak;Hostu nasıl oluşturacağımız hakkındaki yazımı buradan bulabilirsiniz.

Senkron bulmada yapmamız gereken uygun oturumları (session) bulmak, bulduğumuz oturumda oyuncu için boş slot aramak eğer uygunsa o slota yerleşmek. Yalnız bu kodu yazıp bitirdikten sonra 2 bilgisayara ihtiyacınız olacak, birinden host kurup diğerinden buraya bağlanacaksınız ben sanal makine kullanırım diyenlere eyvallah diyorum. Neyse ben başlayayım fazla uzatmadan;

Aşağıdaki metot bize oturum bulmayı ve içinden slot edinmeyi gösteriyor; bu metodu AgIsleri.cs dosyamıza ekleyelim.

  public void OturumBul()

        {

            // Tüm uygun sessionların listesi

            AvailableNetworkSessionCollection uygunOturumlar;

            // Katılacağımız session

            AvailableNetworkSession uygunOturum = null;

            // Bu komut ile tüm uygun oturumları listemize almiş oluyoruz

            uygunOturumlar =NetworkSession.Find(NetworkSessionType.SystemLink,

                                                 maxLocalOyuncu, null);

                        /* Yukrıda 3. parametredeki null Arama filtrelemek için bir opsiyondur

                               Buraya istenirse SearchProperties tipinde değer girilebilir */

            // Oyuncu için slota sahip olan bir oturum arıyoruz

            foreach (AvailableNetworkSession aramadakiOturum in uygunOturumlar)

            {

                // mantık basit bir oturuma ait açık ve rezerve

                //tüm slotların toplamı alınır

                int OturumSlotlariToplami = aramadakiOturum.OpenPublicGamerSlots +

                                             aramadakiOturum.OpenPrivateGamerSlots;

                // ve bu toplam dolu slotlardan fazlaysa hemen o oturum

                //uygun kabul edilir.

                if (OturumSlotlariToplami > aramadakiOturum.CurrentGamerCount)

                    uygunOturum = aramadakiOturum;

            }

            // eğer uygun oturum bulabildiysek katılıyoruz

            if (uygunOturum != null)

            {

                durum = " " + uygunOturum.HostGamertag + " adlı hostta uygun oturum

                                                            bulundu.";

                oturum = NetworkSession.Join(uygunOturum);

            }

            else

                durum = "Hiç uygun oturum bulunamadı.";

        }

Bu şekilde host arama ve dahil olma işini hallettikten sonra bu aramayı çalıştıracak kullanıcı etkileşimine geldi sıra, Game1.cs dosyasını açıyoruz, Update metoduna alttaki kodu ekliyoruz. Ben etkileşim tuşu olarak “S” (Senkron ara) tuşunu seçtim, siz aslında uğraşıp görsel tuşlar da ekleyebilirsiniz herşey dikdörtgenden ibaret, dikdörtgen çizmeyi (hatta içini doldurmayı) bu yazımda fare etkileşimini de bu yazımda anlatmıştım. Size de fare tıklamasının dikdörtgenin sınırları içinde olup olmadığını kontrol etmek içindeyse gerekli işi yaptırmak kalıyor.  Ya da dikdörtgene onMouseclick tarzı bir event handler da yazabilirsiniz gördüğünüz gibi bir sonuca ulaşmanın birden çok yolu var. Takılırsanız iletişime geçin. Neyse bu moladan sonra işe devam; Game1.cs sınıfımızın Update metoduna aşağıdaki kodu ekleyelim;

            // Oturum ara

            if (Keyboard.GetState().IsKeyDown(Keys.S))

                agYardimcisi.OturumBul();

İşte bu kadar basit XNA’de herşey çok basit zaten. Yazıyı kısa bulanlar Allah’larından bulsunlar. Bu saatte yazıyorum. Bir sonraki yazımda da Asenkron şekilde slot aramayı anlatacağım.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

XNA'de Multiplayer Network Temelleri - 1

yazan: 9/6/2008 5:12:00 AM

Merhabalar ne zamandır XNA hakkında yazmadığımı farketim ve bu günün Cuma olmasından faydalanıp “Yapılacaklar” listeme baktım. Sırada “XNA’de basit bir network altyapısı nasıl kurulur” konusu vardı.

Bildiğiniz gibi bize kolaylıklar unmakta üstüne olmayan XNA GS, network konusunda da başımızı hiç ağrıtmayacak nasıl bu kadar eminim? C++’la yapmaya da çalışmıştım oradan biliyorum siz de farkedeceksiniz ki XNA sizden sadece oyunu yapmanızı istiyor altyapı işlerini kendi hallediyor.  Yazımı bu sefer 4 kısma ayırmak istiyorum. Bu yazımın alt konusu Host’u hazırlamak. İşte başlıyorum;

Öncelikle Tarzım olduğu üzere bazı ön tanımlamalar ve açıklamalar yapacağım

LIVE Guide: Bilgisayarınızdan Games for Windows ağına bağlanmanızı sağlayan, kendi oyunlarınızda profil yönetimi sağlayan bir bileşendir.

Components.Add(new GamerServicesComponent(this));

Komutunu oyunumuzun yapıcı metodunda belirtmemizle aktifleşir. 

Metotlar:

NetworkSession.Create(): 4 parametre alan, oturumumuzu yaratan metottur.

1.      parametresi (NetworkSessionType) ne tür bir oturum açacağımızı ,

2.      parametresi (int)aynı makinedeki oyuncu sayısını ki PC için 1’dir,

3.      parametresi (int)oturumda en fazla kaç oyuncu olacağını,

4.      parametresi (int)davet üzerine gelecek oyuncular için kaç tane rezerve slot olduğunu (opsiyoneldir)

5.      parametresi NetworkSessionProperties türünden oturuma parametre olarak geçirilecek değerleri (opsiyoneldir)

gösterir.  

NetworkSessionType: (enum) Ne tür bir oturum açacağımızı gösterir demiştik, bunlar:

1.      Local : Tek bir makinanın üzerinden gerçekleştiği XBox oyunlarında kullanılır (split screen – aynı ekranda)

2.      SystemLink : Aynı alt ağda bulunan makinalar arasında bağlantı kurmak içindir (yerel ağ)

3.      PlayerMatch : XBox Live servislerini kullanılarak internet üzerinden bağlantı kurmak içindir.

4.      Ranked : Xbox Live sertifikası almış oyunlar için geçerlidir.

Bir Host yapabilmek ve oyunu başlatabilmek için: sırayla 4 ana adımı izlememiz gerekiyor.

1-     Öncelikle bir  oyuncu oyuna girmeli (sign in)

2-     Bu oyuncu bir oturum açmalı, kendi oturumuna bağlananlar için kurallar belirlemeli (host)

3-     Diğer oyuncular bu oyuna bağlanmalı

4-     Oyun başlatılmalı.

 

Bu önbilgiden sonra şimdi konu anlatımına geçiyorum; Öncelikle ağ işlerini yapmak için yeni bir yardımcı sınıf yazalım ki ana sınıf karmakarışık olmasın. Ben bu yardımcıya “AgIsleri.cs” adını verdim. İsimuzaylarını (namespace) ana sınıftan aynen alabilirsiniz, fakat bize şu anlık bu 3 tanesi  yetecek;

using System;

using Microsoft.Xna.Framework.GamerServices;

using Microsoft.Xna.Framework.Net;

Yukarıda verdiğim 4 maddeye göre şimdi sırayla Host’umuzu oluşturalım.

1. oyuncu oyuna giriyor;

 AgIsleri.cs’de

public void SignInGamer()

        {

            if (!Guide.IsVisible)

            {

                // burada 1. parametre gösterilecek giriş ekranı sayısını

    // gösteriyor PC için hep 1

                // 2. parametre true ise sadece online profiller gözükür

                Guide.ShowSignIn(1, false);

            }

        }

Böylece giriş yöneticisini ekrana getireiliyoruz.

Şimdi Game1.cs’de bu sign in işinde kullanıcıdan tepki alacak olan nesneyi(buton vb…) yapmamız gerekiyor. Ama burda kısaca herhangi bir tuşa atayacağım bunu, kısa olsun özü dağılmasın.

Sınıf değişkenleri arasına son durumu aktarabilmek veya haberdar olabilmek için AgIsleri cinsinden bir nesne tanımlıyoruz.

AgIsleri agYardimcisi;

Ve Initialize metodunda değer atıyoruz.

// session ile ilgili olarak yapmayı düşündüğümüz işleri

// yapacak olan olan sınıf nesnesi

            agYardimcisi = new AgIsleri();

Update metodunda ;

            // Guide menusunu ekrana getiriyor.

            if (Keyboard.GetState().IsKeyDown(Keys.G))

                agYardimcisi.SignInGamer();

şeklinde kod parçasını yazarak, G (giriş) tuşuna basınca giriş yöneticisini açmayı sağladık. 

2)Oturum açıp kurallar belirliyoruz

AgIsleri.cs’de

Şimdi değişkenlerimizi tanımlayalım

      private NetworkSession oturum = null; // oturum

            private int maxOyuncu = 2; // oyun 2 kişlik olacak

            private int maxLocalOyuncu = 1; // Bir makinada bir kişi olacak

Şimdi de yeni bir oturum yaratmak için kod yazalım;

public void OturumYarat()

            {

               if (oturum == null)

               {

            oturum = NetworkSession.Create(NetworkSessionType.SystemLink,

                                                 maxOyuncu,

                                                 maxLocalOyuncu);

               }

            }

 NetworkSessionType ile ilgili bilgi yukarıdadır. Artık bir oturum yaratabildiğimize göre ağın durumunu yenilemesi gelişmeleri haber vermesi gerekiyor. Bunu da;

      public void Update()

            {

                if (oturum != null)

                    oturum.Update();

            }

Metodu aracılığı ile yapacağız. Şimdi bu metodu Game1.cs’den çağıralım,

Game1.cs ‘de

update metodunun en üst kısmında agYardimcisi nesnemizin yeni yazdığımız update metodunu çağırıyoruz

//session'un update olmasını sağlıyor

            agYardimcisi.Update(); 

işimiz bitti sonucu görmek için ufak bir iki ekleme yapabiliriz,

content dosyamıza solution explorer menüsünden bir spritefont ekleyip adına Arial diyelim (değiştirmek size kalmış) ekrana yazı yazdıran spritebatch.drawstring hakkında bilgiyi bu yazımda bulabilirsiniz.

Şimdi bu eklediğimiz fontu oyunda tanıtalım;

Game1.cs’de

SpriteFont ArialYazi;

Şeklinde bir değişken tanımlayalım, ve LoadContent metodunda kaynağını ekleyelim.

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

Bu SpriteFontumuzun ekrana basacağı yazıya kaynaklık etmesi için AgIsleri.cs sınıfımızda bir string tanımlayalım;

AgIsleri.cs

public String durum = "Kulanıcı hareketi bekleniyor.";

ve bu stringimizi ayarlayacak olayı yazalım;

Eğer oturum nesnemizin sonuna (.) işareti koyup intellisense aracılığı ile bakacak olursak 6 tane event (olay) göreceğiz. Bu olayların hepsine göz atmak için bu yazıma bakınız. Şimdilik bize 1 olay yeter.

oturum.GamerJoined +=

              new EventHandler<GamerJoinedEventArgs>(session_GamerJoined);

Bu olay ile oyuncu katılımı durumunda bir metodu tetikleyeceğiz. Bu metot da;

        void session_GamerJoined(object sender, GamerJoinedEventArgs e)

        {

            if (e.Gamer.IsHost)

                durum = "Host oturum açtı";

            else

                durum = "Oyuncu: " + e.Gamer.Tag + ", oyuna katıldı";

        }

Bu şekilde event handler’ımızı da hallettik. İsterseniz siz de oturum.GamerLeft olayını ve ele alınışını kodunuza ekleyin (o kadarı da ödev olsun )  hazır durumda olan stringimizi ekrana bastıralım; Game1.cs dosyasına geçelim Draw metodunda

Game1.cs

            spriteBatch.Begin();

spriteBatch.DrawString(Arial, "Oyun durumu: " +

agYardimcisi.durum,

                                    new Vector2(20, 20),

Color.Yellow);

            spriteBatch.End();

Hala  farkettiğiniz gibi bir eksiğimiz var update metodunda yeni oturumu açma tuşunu belirleyelim ben “Y” (yeni oturum) tuşunu seçtim.

// yeni session oluşturuyor

            if (Keyboard.GetState().IsKeyDown(Keys.Y))

                agYardimcisi.OturumYarat();

Böylece kullanıcı olarak giriş yapabildiğimiz (sign up) ve yeni oturum başlatabildiğimiz bir Hostumuz oldu, Diğer 2 yazımda host edilmiş oyunu bulup oyuncu olarak katılmayı anlatacağım.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

XNA’de İKİ BOYUTLU NESNE ÇİZİMİ – 3

yazan: 8/2/2008 4:40:00 AM

Önceki yazımda sabit duran nesneleri çizdirmeyi göstermiştim. Bu yazımda da aynı sınıfları kullanarak hareketli bir nesne çizdirmeyi göreceğiz.

 

Öncelikle nesnemiz hareket edeceği için bir hareket hızı olması lazım; bunu CizilecekNesne sınıfımıza değişken olarak ekliyoruz.

            public Vector2 velocity;

daha sonra; Game1.cs sınıfımıza dönelim;

nesne.velocity = new Vector2(0.0f, 0.5f);

nesne.position = new Vector2(350, 250);

bu şekilde sadece yukarı yönlü bir hız vektörü belirleyelim, ve nesnemiz için bir pozisyon değeri atayalım.

Daha sonra klavyeden girdi alarak nesnemize hareket verelim.

if (keyboardState.IsKeyDown(Keys.Up))

            obje.position -= obje.velocity;

      if (keyboardState.IsKeyDown(Keys.Down))

            obje.position += obje.velocity;

şeklinde daha önce de anlattığım gibi, kullanıcı girdisi alarak nesneyi gideceği yöne doğru hareket ettirelim. Birinci deyimde -= işareti yukarı yönlü bir harekete neden olcaktır çünkü unutmayalım ekranımızda y ekseni aşağı gittikçe artar. Sonra;

 

obje.position.Y = MathHelper.Clamp(obje.position.Y,

 0, ekranAlanı.Height-obje.sprite.Height);

 

Diyelim, bu metoda dikkat Clamp metodu birinci parametresinde verilen değeri alır; ikinci ve üçüncü parametreler arasında tutar. Eğer değer son iki parametrenin arasında ise değişmez, eğer birini geçiyorsa geçtiği max veya minimum değere eşitlenir.

Burada nesnemizin Y bileşeni ancak “0” ve  “Ekran alanı – Nesnenin boyu” arasında bir değer alabilir. Eğer birini geçerse geçtiği değere eşitlenir. Böylece nesnemiz sürekli ekranda kalacaktır.

 

Olay kısaca bu zaten diğer kısmını önceki yazıda halletmiştik şimdi araya bunları ekleyerek nesnemizi harekete geçirdik.

Önceki yazıya buradan; çevre birimlerinden girdi almaya buradan ulaşabilirsiniz.  

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

XNA’de İKİ BOYUTLU NESNE ÇİZİMİ – 2

yazan: 8/1/2008 8:25:00 AM

 

 Önceki yazımda nesnelerimizi oyun ekranında 2B olarak temsil etmek için gerekli olabilecek bazı metotlardan bahsetmiştim. Bu yazımda da bu metotları kullanarak ekranda bir temsil oluşturmayı anlatmaya çalışacağım.

Öncelikle işin mantığını sıralayalım:

1-     Nesnelerimizin ihtiycı doğrultusunda sınıflar hazırlıyoruz; örneğin durağan bir nesne için konum ve desen gibi iki değişken yeterli olabilecekken; hareket eden bir nesne için hız, yön, hareketin başlama konumu gibi özelliklere ihtiyaç duyarız.

2-     Sınıflarımızın yapıcı metotlarında (Constructor) değişkenlerimizi ayarladık,

3-     Game1.cs’de nesnemizi temsil edecek değişkenler oluşturduk.

4-     LoadContent() metodu içinde nesnemize başlangıç değerlerini yükledik.

5-     Update() metodu içinde, nesnemizin etkileşimini sağlayacak işlemleri yaptık. Gerektiğinde if deyimleri ile nesnemize yeni tepkiler verdirdik. Bu metot saniyede 50-60(değişebilir) kez tekrarlanacak buna dikkat ettik.

6-     Draw() metodunda spritebatch nesnesinin metotlarıyla çizim işlemini gerçekleştirdik. Bu da Update metodu gibi saniyede onlarca kez tekrarlanacak.

Not: XNA GS’nin bize hazırladığı metotların içini doldurmak yerine ufak metotlar tanımlayarak bu kısımların içinde çağırırsak daha bir güzel olur kodumuz ama bu yazıda buna dikkat etmeyeceğim, siz edin.

Bu yazımın konusu olarak hareketsiz nesneleri çizmeyi seçtiğim için ekranda haket etmeyen bir nesne çizeceğiz. Daha sonra hareket eden nesnenin nasıl çizileceğini ve kullanıcı girişinden nasıl etkileneceğini yazacağım.

Şimdi yavaş yavaş başlayalım;

1. Adım:

CizilecekNesne.cs:

        public Texture2D deseni;

        public Vector2 konumu;

şeklinde bazı nesne özellikleri tanımladık.

2. Adım:

CizilecekNesne.cs:

        public CizilecekNesne (Texture2D yüklüDesen)

        {

            konumu = Vector2.Zero;

            deseni = yüklüDesen;

        }

3. Adım:

            Game1.cs

               //arkaplanımız için bu değişkeni tanımladık.

        Texture2D arkaPlan;

         //bu değişken de oyunun ekran alanını tutacak.

        Rectangle ekranAlanı;

        //nesnemiz

        GameObject nesne;

4. Adım:

            Game1.cs – LoadContent methodu:

            arkaPlan = Content.Load<Texture2D>("arkaplan");

            //bunun için önceden Content klasörüne bu isimle bir resim koymuş

//olmamız gerekir

 

 

nesne = new CizilecekNesne(Content.Load<Texture2D> ("nesneFoto"));

nesne.konumu = new Vector2(

graphics.GraphicsDevice.Viewport.Width/2,

graphics.GraphicsDevice.Viewport.Height/2);

           

            ekranAlanı = new Rectangle(0, 0,

                graphics.GraphicsDevice.Viewport.Width,

                graphics.GraphicsDevice.Viewport.Height);

           

 burada arkaplanımızı nesnemizi ve ekran alanımızın temsillerini hazırladık.

5. Adım:

            Game1.cs – Draw metodu:

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);

      spriteBatch.Draw(arkaPlan, ekranAlanı, Color.White);

/* ekran alanı büyüklüğünde, arkaPlan desenine sahip bir resmi beyaz ışıkla döşedik. Dolayısıyla bu bizim arkaPlanımız oldu.*/

 

      spriteBatch.Draw(nesne.deseni, nesne.konumu, Color.White);

      // Burada da nesnemizi ekrana çizdirmiş olduk.

            spriteBatch.End();

 

Böylelikle ekrana nasıl arkaplan deseni verileceğine ve bir nesnenin nasıl çizdirileceğini görmüş olduk. İlerki yazılarımda hareketli bir nesnenin çizimini ve hareket ettirilmesini, çarpışmaları anlatmaya çalışacağım. Ama herşey buradaki gibi basit, değişken tanımla, LoadContent metodunda gerekli şeyleri yükle, Draw metodunda çiz. Eğer hareket veya etkileşim söz konusu ise nasıl davranacağına Update metodunda karar ver.

Sonraki yazılarda görüşmek dileğiyle...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , ,

XNA

 

Yazar Hakkýnda

Erçin YONTAR
Erçin Yontar
1986 yýlýnda Çorlu'da doðdu.Ýlk öðrenimini Ankara'da, ortaöðrenimini Eskiþehir'de gördü.
Çanakkale 18 Mart Üniversitesi Bilgisayar Mühendisliði Bölümü mezunu.
Yazýlým ile çok ilgili; Visual Studiosu daima açýk :) bunun sayesinde Imagine Cup 2008 Türkiye 3.sü ve bir çok proje geliþtiriyor.
Yazýlým dýþýnda : Frp hastasý, rock/metal dinliyor, organizasyon iþlerine merak sardý. Bunlarýn yanýnda o bir; 
MCTS (Microsoft Certified Technology Specialist)



MSP (Microsoft Student Partner)

Bana posta atýn Send mail

Favorilerine Ekle


Add to Technorati Favorites

 

Twitter - Ne Yapýyorum?

    Pages

      Recent comments

      Feragatname

      Burada yazan yazýlar ve içerdikleri fikirler yazarýna aittir. Baþkasýný ilgilendirmez. Yazýlarý kaynaðýný kopyaladýðýnýz yazýnýn içinde týklanabilir link halinde belirtmek þartý ile olduðu gibi kullanabilirsiniz. Bu kurallarý deðiþtirme hakkým saklýdýr. Yarýn bir gün benim yazým benim blogumdan baþka bir yerde olamaz dersem Kopyaladýðýnýz yazýyý da silmek zorundasýnýz. Bu iþe girþen kiþi bu koþullarý ve doðan yasal yükümlülükleri kabul etmiþ sayýlýr. Eyvallah diyen devam etsin.

      © Tüm haklarý saklýdýr.

      Giriþ