C# ile Oyun Yapımı Tekniklerine Giriş C# dili ile basit bir oyun yapıyoruz. Timer nesnesini de incelediğimiz bu makalede, Jackpot oyununu sıfırdan inşa ediyoruz.
C# ile Oyun Yapımı Teknikleri Yıllardır programcılar C,C++ veya java gibi oldukça dezavantajları olan programlama dilleri ile oyun kodlamaya çalışmaktadırlar. Bunlar arasında C yapısal bir programlama dili olduğu için programcıyı en zorlayan ve karmaşık kodlar arasında programcının kaybolmasını sağlayan bir yapıya sahiptir. C++ ve Java için aynı şeyi söylemek mümkün değilken yinede bazı dezavantajları bulunmaktadır. C# için ise aynı şeyi söyleyemeyeceğim. Çok kullanışlı bir dil olmasına rağmen programcılar daha çok database programlamada bu dile rağbet etmektedir. Bizim üstünde duracağımız konu ise C# ile C++ veya Java’ya nazaran daha kolay bir şekilde oyun programlama yapabileceğimizdir. Bu kolaylıklar getiren ve durmadan gelişmekte olan dilin sadece Database programlamada kullanılması biraz saçma olurdu zaten. Şu anda DirectX veya diğer SDK lar ile kolayca programlama yapabilmekteyiz. Fakat oyun programlamaya yeni başlayan biri için DirectX biraz karmaşık gelebilir. En azından hiç oyun yazmamış birinin bu mantığı programa oturtmasında zorluklarla karşılaşılabilir. Bunun içinde temel bir oyun programlama mantığı ile “oyunları nasıl programlayabiliriz ? “ soru cümlesinin üstünde durmak isterim. Sıradan bir Jackpot düşünün kolu çekiyorsunu ve simgeler sırayla dönüyor ve rasgele bir şekilde 3 sıralama karşımıza çıkıyor. Bu sayının 3 olması standart bir işlem olmayıp 3,4 veya 5 li kombinasyonlara görede sıralama yapabiliyoruz. 3 sıralı bir jackpotun karmaşıklığını ele alırsak ve her bir sırada da 4 adet simgenin ardarda döndüğünü düşünürsek toplamda elimizde 4 adet simge olacaktır ve biz bu 4 simgenin 3 lü sıralanışlarını ele alacağız. Olasılığımız ise 64 olacaktır. Jackpot gerçek hayatta mekanik bir yapıyla hareket etmekteyken biz yazılımsal bir yöntemle yaklaşacağımız için bu mekanişk yapının mantığını kağıda aktarmamız gerekecek. Olasıklarımız 64 adet olduğuna göre ve bu 64 olasılığı tutacağımız bir dizi işimizi görecektir. Mekanik yapıda şans devredeyken yazılımsal yapıda da aynı metodu ve rasgeleliği programımıza uygulamak için randomize ifadeler işimize yarayacaktır. Oyun tekniğimiz bu kadar basitken görselliğimizde oyun yapımcısının ellerindedir. İster çok kötü bir kullanıcı arayüzü ile bu işi halledelim, ister Las Vegas’dan alınmış bir jackpot görünümü verelim Arka planda en iyi teknikleri kullanmış olsanızda çok kötü gözüken bir oyun hiç tutmayacaktır. . Oyunun kullanıcı arayüzü de oyun programlamada geniş bir yer tutmakta olup bu yazımız da bunu gözardı etmek durumunda kalacağız. Oyunun görünümü kullanıcının oyunun başında ne kadar kalacağı ve oynama sıklığı ile doğru orantılıdır. Basit bir Jackpot programlamaya kalktığımızda öncelikle ortaya koyduğumuz kombinasyonları basit bir ifade ile diziye aktarmak olacaktır. Bu olasılıklar dizisini basit bir kod parçasıyla yazmamız mantıklıyken kombinasyonları görmemiz açısından tek tek elle yazmak bizim için daha yararlı olacaktır. Her bir resmimize bir rakam verelim bunlar sırasıyla 0,1,2,3 olsun. Birinci
resmimiz 0, ikinci resmimiz 1 , üçüncü resmimiz 2 ve son resmimiz ise 3 numaralı sayı ile temsil edilmektedir. Toplam olasılığımızı ve resimlerin değişik kombinasyonlarını 3 lü sırada yazalım; 0,2,0 0,2,1 0,2,1 0,2,3 1,0,1 1,0,2 1,0,3 2,0,1 2,0,2 2,0,3 3,0,1 3,0,2 3,0,3 0,1,0 0,1,1 0,1,2 0,1,3 1,1,1 1,1,2 1,1,3 2,1,1 2,1,2 2,1,3 1,2,0 1,2,1 1,2,2 1,2,3 0,3,0 0,3,1 0,3,2 0,3,3 3,3,0 3,3,1 3,3,2 3,3,3 3,1,0 3,1,1 3,1,2 3,1,3 2,2,0 2,2,1 2,2,2 2,2,3 1,3,0 1,3,1 1,3,2
1,0,0
2,0,0
3,0,0
1,1,0
2,1,0
1,3,3 0,2,0 0,2,1 0,2,2 0,2,3 3,2,0 3,2,1 3,2,2 3,2,3 2,3,0 2,3,1 2,3,2 2,3,3
Bu 4’lü gruplarımızdan toplamda 16 adet bulunmaktadır. Önemli olan ise bizim için 64 sayısıdır çünkü jackpotun kolunu çevirdiğimizde bunlardan herhangi biri karşımıza gelmektedir. Randomize bir sayı oluşturup ardından 1 ile 64 arasında bize bir rakam verirse karşımızda rasgele koluna başılmış ve gerçek hayatta jackpotun işini yani içerdiği simgelerin rasgele sırlanışını elde etmiş oluruz. Artık temel oyun mantığımız hazır ve sırada sadece bu mantığı kodlamak kaldı bu mantığıda kod becerimize göre bir kabiliyetle kodlayabiliriz. Oyunda 4. Resim 3 tane çıkarsa oyuncu kazanır şeklinde bir mantık eklememiz çok kolay 64 sayısını randomize komutuyla elde ettiğimiz de oyuncu kazanacaktır veya birinci resim ilk iki karede çıkarsa 3. Nolursa olsun parasının iki katını kazanması için [1,1,0][1,1,1][1,1,2][1,1,3] kombinasyonlarından birisinin gelmesi yeterlidir. Aslında bunun Jackpot uygulaması için zor bir yol olduğunu ve C# programlama dili ile daha basit bir yolunun olduğunuda söylemek isterim. Klasik olarak yolumuz bu şekildeyken bir Timer nesnesi işimizi dahada kolaylaştırabilir. Peki, “bu timer nesnesi nedir ve nasıl bu işi daha kolay bir şekilde yapabiliriz ? ” sorusunu C# kodumuzun üstünde açıklamak isterim. Öncelikle Windows projesi oluşturup basit bir kullanıcı arayüzü yapalım burada para atacağımız bir kısım, bir kol, 3 adet imagelerimizi barındıracağımız bir picturebox, 4 veya daha fazla jetonlarımız ve birde kasamızda ne kadar bulunduğunu gösteren label veya textbox ile bu işe başlayalım. Yaptığım örnek uygulamanın görüntüsü aşağıdaki gibidir;
Öncelikle oyunumuzu hazırlamak için alanlarımızı ve metodlarımızı belirleyelim ve windows uygulamasına ekleyeceğimiz bileşenleri inceleyelim; 4 adet timer kontrolü ekleyelim ve bir tanede imagelist kontrolü. Bu imageliste göstereceğiniz 4 adet resim ekleyin. Alanlarımız; int[] tut; int para = 0; int oyun = 0; Çekeceğimiz kolun ters bir görünümünü alıp form load’un da bu picturebox’ın visible özelliğini false yapmamız gerekmektedir. Böylece kolu çekteğimizde oyuncu kolun aşağıya indiğini görecektir. Ardından bir baslangic metodu tasarlayalım; private void baslangic() { int[] timrand = new int[3]; tut = new int[3]; for (int i = 0; i < 3; ++i) { tut[i] = 0; } Random rast = new Random(); timrand[0] = rast.Next(100, 250); timrand[1] = rast.Next(100, 250);
timrand[2] = rast.Next(100, 250); timer1.Interval = timrand[0]; timer2.Interval = timrand[1]; timer3.Interval = timrand[2]; timer4.Interval = 1000; } Timer1,timer2,timer3 ve timer4 eklediğimiz timerların isimleri. Timrand isimli integer dizimiz ve tut isimli dizimiz 3 boyutludur. Bir döngü ile tut dizimizin bütün indislerini sıfır yapıyoruz. Rast isminde bir Random nesne nesne oluşturup 100 ile 250 arasında bir değer tutmasını istiyoruz. Randomize rakamları timrand dizilerinin indislerine sırayla atıyoruz. Timerlarımızın interval özelliğini bu rakamlarla belirliyoruz. Böylece yaşam döngüsü birbirinden farklı timerlarımız oluyor. Bu arada cash sistemini yapmak amacıyla Sürükle-Bırak işlemlerini pictureboxlarımızla ve textbox için yapılandırıyoruz. private void pictureBox5_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) { pictureBox5.DoDragDrop("10", DragDropEffects.All); para += 10; } } Yukarıdaki sarı,kırmızı,mavi ve yeşil para görünümde kutucuklar için bu işlemi yapıyoruz. Farklı olan değerimiz sadece para+=10 işaretindeki 10 sayısı olacaktır çünkü her paranın farklı değeri olacaktır. DragDrop işleminde textbox için ekleyeceğimiz kod ise aşağıdaki gibidir; private void textBox2_DragDrop(object sender, DragEventArgs e) { int t; textBox2.Text = e.Data.GetData(DataFormats.Text).ToString(); t = (Convert.ToInt32(textBox1.Text) - Convert.ToInt32(textBox2.Text)); if (t =< 0) { MessageBox.Show("Not Enough Coin"); } else textBox1.Text=t.ToString(); } Kasamızda para kalmamışsa “Not Enough Coin” hatası alacağız. Textboxın dragover event’ine ise şu kodu ekleyelim; private void textBox2_DragOver(object sender, DragEventArgs e) { if (e.KeyState == 1) { e.Effect = DragDropEffects.Copy;
} } Randomize seçtiğimiz ilk 3 timer’ın tick event’ine ise aşağıdaki kodları ekleyelim; private void timer1_Tick(object sender, EventArgs e) { pictureBox1.Image = ımageList1.Images[tut[0]]; tut[0]++; if (tut[0] == 3) tut[0] = 0; } private void timer2_Tick(object sender, EventArgs e) { pictureBox2.Image = ımageList1.Images[tut[1]]; tut[1]++; if (tut[1] == 3) tut[1] = 0; }
private void timer3_Tick(object sender, EventArgs e) { pictureBox3.Image = ımageList1.Images[tut[2]]; tut[2]++; if (tut[2] == 3) tut[2] = 0; } Ardından çekeceğimiz kolun yani picturebox’ın üstüne çift tıklayıp aşağıdaki kodu yazalım; private void pictureBox4_Click(object sender, EventArgs e) { if (para != 0 & textBox2.Text!="") { baslangic(); pictureBox10.Visible = true; pictureBox4.Visible = false; timer1.Start(); timer2.Start(); timer3.Start(); timer4.Start(); } else { MessageBox.Show("Please Take Coin."); } } Dikkat ederseniz ilk 3 timer’ın tick event’leri için belirli bir kod yazmıştık fakat aynısını 4. ve en önemli olan timer4 ün click evet’i için yapmadık. Çok önemli bir event ve oyunu
sağlayan en önemli eventlerden biri. Kod aşağıda; private void timer4_Tick(object sender, EventArgs e) { oyun++; if (oyun == 8) { timer1.Stop(); timer2.Stop(); timer3.Stop(); timer4.Stop(); if (tut[0] == 0 & tut[1] == 0 & tut[2] == 0) { MessageBox.Show("You WIN"); int temp1 = Convert.ToInt32(textBox1.Text) + (para * 10); textBox1.Text = temp1.ToString(); } else { MessageBox.Show("You Loose"); } pictureBox4.Visible = true; pictureBox10.Visible = false; oyun = 0; para = 0; if (Convert.ToInt32(textBox1.Text) <= 0) { MessageBox.Show("game over"); Application.Exit(); } } } Bundan sonra kazanca ve kayba göre her kolu çektiğimizde oyunumuzu oynayabiliyoruz. Her birisi farklı hızda dönüp farklı zamanlarda duruyorlar. Timer kontrolümüzünde önemli bir kullanımı göstermiş olduk. Başlangıç kısmında anlatmış olduğum olasılık ile ilgili probleminde kullanım alanları vardır mesela bu mantığı aynısını bulma oyunu için uyarlayabilirsiniz. Yazar : Volkan Atasever e-Posta :
[email protected] Alıntı