Herkese merhaba, bu derste Game Maker’ın yazılım dili olan GML ile basit bir oyun tasarlayacağız. Derse başlamadan önce biraz da olsa GML bilgi birikiminizin ve tecrübenizin olmasının çok iyi olacağını söylemek isterim. Çünkü bu derste kullanacağımız basit kodları yorumlamakta güçlük çekmenizi istemeyiz. Bunun yanında kesinlikle Game Maker’ı basit de olsa kullanmayı bilmelisiniz. Kullanmaktan kastım ise yeni bir kaynak dosyası oluşturmak, event ya da aksiyon oluşturmak gibi temel fonksiyonlar. Çoğunuzun zaten bildiği şeyler yani.
Peki o zaman, hadi derse başlayalım!
NOT: Dersteki yapılan oyunun “.gmk”sını indirmek isterseniz şu linki kullanabilirsiniz:
https://www.box.com/s/3f037cc3c1d20fbae631
İlk olarak oyunumuzun nasıl bir şey olacağından bahsedeyim. Oyun 2 boyutlu olarak tepeden bir bakış açısıyla oynanacak. Oyunda bizim kontrol ettiğimiz kare şeklindeki bir obje ile bilgisayarın kontrol ettiği başka renkteki bir kare obje arasındaki puan rekabetini konu alacağız. Puan toplamak içinse birbirlerini vuracaklar. Ancak zamanla düşman sayısı artacak. Hedef ise 500 puana ulaşmak. Bu uğurda harcayabileceğimiz 3 canımız olacak ve canlarımızın hepsi biterse de başarısız olacağız.
Evet, oyun biraz da olsa ilginizi çektiyse başlayalım. 🙂
Öncelikle Game Maker’ı açın ve yeni bir proje oluşturun. Ardından projenizi herhangi bir isimle kaydedin.
Şimdi projeniz için 4 yeni sprite oluşturun. Bunlara istediğiniz isimleri verebilirsiniz. İlk 2 sprite bizi ve düşmanımızı temsil edecek, kare şeklinde ancak farklı renklerde olacaklar. Boyutlarını ise 32 X 32 olarak ayarlayın. Bu 2 spriteyi dilediğiniz gibi çizebilirsiniz. Spriteleri çizdikten sonra bizim karakterimizin spritesinin “Origin” noktasını “X=16 , Y=0” yapın. Düşmanınkini ise “X=16 , Y=32” yapın.
NOT: Burada “Origin” noktasını değiştirmemizdeki amaç; oyun boyunca bizim oyun ekranının alt kısmında, düşmanın da üst kısmında olacağını varsayarak, ateş edeceğimiz kurşunun tam “Origin” noktasından, yani karakterimizin ortasından değil de uç kısmından çıkmasını sağlamaktı.
Son 2 sprite ise bizim ve düşmanımızın kurşununu temsil edecek ve şekli de hâliyle dairesel olacak. Ebatlarını 6 X 6 yapın ve “Origin” noktalarını merkeze, yani “X=3 , Y=3”e ayarlayın.
Bu aşamadan birkaç resim:
Evet, şimdi gerekli spriteleri oluşturduğumuza göre gelelim objelerimizi oluşturmaya. Önce bizim karakterimizi temsil eden bir obje oluşturun ve adını “biz” koyun. Artından oluşturduğumuz karakter spritesini objenize bağlayın. Ardından obje için “Create” eventi oluşturup içine “control” sekmesinden bir “Execute Code” aksiyonu ekleyin. İçine şunları girin:
can=3;
score=0;
Böylece 3 adet canımızı ve skorumuzu birer değişken olarak tanımladık. Şimdi karakter objemizden çıkıp yeni bir obje oluşturun ve adını “biz_kursun” koyun (Kesinlikle isimlerde Türkçe karakter kullanmayın!!). Bu objeyi karakterimizin oluşturacağı kurşun için oluşturuyoruz, o yüzden objeye bizim kurşunumuzun spritesini verin. Ardından kurşunun “Create” eventine “Execute Code” aksiyonu ekleyip içine şunu girin:
vspeed=-5;
Böylece kurşunumuz oluştuğunda yukarı yönde, saniyede 5 pixel ilerleyecek. “vspeed”in açılımı ise “Vertical Speed”, yani “Dikey Hız”. Bu değer şimdi yaptığımız gibi negatif olursa obje yukarı yönde, pozitif olursa aşağı yönde hareket eder.
Ardından kurşun için bir “Outside Room” eventi oluşturun. Bunu “Other” seçeneği içinde bulabilirsiniz. Bu event; objemiz oyunun geçtiği room’un sınırlarından çıkınca gerçekleşir. Böyle bir durum gerçekleştiğinde o kurşun objesine artık ihtiyaç duymayız, oyunu boş yere yavaşlatmaması için onu yok etmeliyiz. Bunun için bir “Execute Code” aksiyonu içine şu kodu yazın:
instance_destroy();
Bu kodun yaptığı şey, event gerçekleştiğinde; objenin eventi gerçekleştiren kopyasının (instance) yok olmasını sağlamaktır. Yani oyun sahasından çıkan kurşunların böylece yok olmasını sağladık.
Evet, şimdilik “biz_kursun” objemizle işimiz bitti. Tekrar “biz” objesine dönün ve bir “Keyboard Space” eventi oluşturun. Ardından içine bir “Execute Code” aksiyonu koyup şu kodu yazın:
if(ates_mumkun==1)
{
instance_create(x,y,biz_kursun);
ates_mumkun=0;
alarm[0]=6;
}
Bu kodu açıklayalım. Ben öncelikle “ates_mumkun” adında kontrol amaçlı bir değişken kullanmak istedim. Eğer bu değişkenin değeri 1 ise “instance_create()” ile karakter objemizin bulunduğu x ve y koordinatlarında bir “biz_kursun” objesi kopyası (instance) oluşturulmasını sağladık. Ardından “ates_mumkun” değişkeninin değerini 0 yapıp “alarm0”ı 6 adıma (step) kurduk.
Şimdi burada “ates_mumkun”un ne işe yaradığını kesinlikle sorguladığınızı düşünüyorum. Bu değişkenin işlevi, biz SPACE tuşuna basılı tuttukça sürekli kurşun oluşturmak değil de belli aralıklarla kurşun yollamamızı sağlamak. Çünkü “Keyboard Space” eventi elimizi SPACE’den çekmediğimiz sürece sürekli gerçekleşen bir eventtir ve eğer “ates_mumkun” değişkeniyle her 6 stepte bir kurşun oluşmasını sağlamasaydık her 1 stepte bir kurşun oluşacaktı ve elimiz SPACE’deyken; kötü gözüken, anlamsız derecede çok kurşun oluşmuş olacaktı. Ancak burada şöyle bir durum var, oyunumuzu ilk çalıştırdığımızda SPACE’e ilk bastığımız anda oyunumuz hata verecektir çünkü “if()” koşul sınama deyiminde kullandığımız “ates_mumkun” değişkeni henüz tanımlı bir değişken değil. Değerinin kaç olduğu bilinmediği için de hata almak kaçınılmazdır. Bunu engellemek içinse karakter objemizin “Create” eventindeki “Execute Code” aksiyonunun içine şu kodu ekleyin:
ates_mumkun=1;
Böylece objemiz oluştuğu sırada “ates_mumkun” değişkenini 1 olarak tanımlamış olduk. Artık tek bir sorun kaldı, o da “alarm0” için gerekli şeyleri kodlamak. Bunun için bir “alarm0” eventi oluşturun ve içine “Execute Code” aksiyonuyla şu kodu ekleyin:
ates_mumkun=1;
Bu sayede “alarm0” gerçekleştiğinde “ates_mumkun” değişkeninin değeri de 1 olacak ve tekrar ateş edebileceğiz.
Evet, karakterimize ateş etme işlevi eklediğimize göre gelelim karakterimizin hareket etmesine. Karakterimiz oyunda sadece sağa ve sola gidebilecek. Bunun için “Keyboard Left” eventi oluşturup içine şu kodu ekleyin:
x-=4;
Böylece klavyedeki sol ok tuşundan elimizi çekmediğimiz sürece sola doğru saniyede 4 birim ilerleyeceğiz. Aynı şeyi “Keyboard Right” eventi için de yapın ancak bu sefer içine “x+=4” yazın ki sağa doğru gitsin karakterimiz.
Karakter objemiz için kalan son bir event kaldı, o da karakterimiz odanın dışına çıkarsa yapılacak event. Bunun için bir “Outside Room” eventi ekleyip içine bu sefer şu kodu girin:
if(x<0)
{
x=room_width+15;
}
else
{
x=-15;
}
Böylece eğer karakterimiz odanın dışına sol taraftan çıktıysa odanın sağ tarafına ışınlanacak, yok eğer sağ taraftan odanın dışına çıktıysa odanın en soluna ışınlanacak. Böylece sürekli odanın sınırları içinde kalacak. Bu işlemle beraber karakter objemizi şimdilik tamamladık. Projenizi kaydedin ve tavsiyem 300X304 boyutlarında yeni bir oda oluşturup içine 1 tane “biz” objesini koyarak yaptıklarımızı test edin.
Oyun içi bir resim:
Pekala şimdi düşman objemizi oluşturarak oyunumuza biraz renk katalım. Bunun için “dusman” adında yeni bir obje oluşturup düşman objesi için çizdiğiniz spriteyi ona ayarlayın. Ardından “Create” eventine şu kodu ekleyin:
can=3;
if(irandom_range(1,2)==1)
{
hspeed=-3;
}
else
{
hspeed=3;
}
alarm[0]=45;
Burada yaptığımız işlem önce “can=3” ile düşmana 3 değerine sahip bir can değişkeni oluşturmak. Bu değişken sayesinde düşmanın 3 kere vurulunca ölmesini sağlayacağız. Ardından yaptığımız şey “irandom_range()” ile 1 veya 2 sayısından rasgele tekini bilgisayara tutturmak ve eğer sonuç 1 çıkarsa “hspeed”i, yani Horizantal (Yatay) hızı -3 yaparak düşman objesini sola hareket ettirmek, yok eğer sonuç 2 çıkarsa da bu değeri 3 yaparak sağa hareket ettirmek. Böylece düşmanımız sürekli aynı yönde hareket etmek zorunda kalmayacak ve bu da monotonluğu azaltacak. Ardından “alarm0”ı 45 step’e kuruyoruz. Yani bu 30 FPS’lik standart oyun hızımız için 1,5 saniyeye denk geliyor.
Ardından bir “alarm0” eventi oluşturun ve içine az önce “Create” eventine yazdığımız kodun aynısını yazın. Böylece karakterimiz her 1,5 saniyede yönünü değiştirme olasılığına sahip olacak ve vurulması nispeten zorlaşacak.
Ardından tıpkı “biz” objemizde yaptığımız gibi bu objeye de bir “Outside Room” eventi ekleyip içine “biz” objemizdeki kodun aynısını yerleştirin. Böylece düşman herhangi bir şekilde oda sınırlarını aşarsa karşı taraftan oyuna tekrar dahil olacak. Şimdi oyuna bir “dusman” objesi ekleyip oyunu test edin. Düşman sürekli aynı yönde hareket etmeyecektir.
Örnek bir resim:
Ancak kısa bir süre sonra sizin de fark edeceğiniz üzere karakterimizin kurşunları henüz düşmana etki etmiyor. Bunu ayarlamak için düşmanın “Collision ‘biz_kursun’ “ eventine şu kodu ekleyin:
with(other)
{
instance_destroy();
}
//////////
if(can>1)
{
can-=1;
}
else
{
score+=5;
hspeed=0;
vspeed=-4;
alarm[1]=10;
}
Bu kod sayesinde yaptığımız işlem şu: Öncelikle “with(other)” içindeki “instance_destroy();” ile düşmana çarpan mermiyi yok ediyoruz. Ardından “can” değişkenin değerine bakıyoruz. Eğer bu değer 1’den büyükse daha düşmanın canı var demektir ve tek yaptığımız canı 1 azaltmaktır. Ancak “can” değişkeninin değeri 1 ise artık düşmanın canı kalmamış demektir ve ölecektir. Bunun için önce “biz” objemizde de kullandığımız “score” değişkeniyle skora 5 ekliyoruz. Ardından ben şöyle düşündüm: Biz düşmanı öldürdüğümüzde düşman aniden yok olmasın. Bu çok da güzel gözükmez. Bunun yerine düşman öldüğü zaman sahnenin yukarısına doğru çıkmaya başlasın ve ardından sahneden kaybolsun. Böylece basit bir animasyon tasarlamış gibi olduk. Ancak sahnenin dışına çıkan düşman objesini de bir süre sonra yok etmek için “alarm1”i 10 adıma kuruyoruz ve objenin içinde bir “alarm1” eventi oluşturup içine “instance_destroy();” kodunu yazıyoruz. Böylece düşmanın ölmesi işlemini tamamladık. İsterseniz oyunu şimdi test edebilirsiniz. Düşmana 3 kez vurduğunuzda düşmanın animasyon eşliğinde ölmesi lazım.
Şimdi gelelim düşmanın bize ateş etmesine. Düşmanın kurşunu için bir obje oluşturup adını “dusman_kursun” koyun. Ardından ilgili spriteyi objeye bağlayın. Bu objenin de oluştuğunda sahnede aşağı yönde ilerlemesi lazım, bunun için “Create” eventine “vspeed=5;” yazın. Ardından “Outside Room” eventine de “instance_destroy();” yazarak bu objeyle işinizi tamamlayın.
Sıra geldi düşmanın ateş etmesini ayarlamaya. Bunun için yapmanız gereken “dusman” objesindeki “Create” eventini açıp kodların en altına şunu eklemek:
alarm[2]=60;
Sonrasında da obje için bir “alarm2” eventi oluşturup içine şu kodları yazın:
instance_create(x,y,dusman_kursun);
alarm[2]=60;
Böylece düşmanın her 2 saniyede bir (60 step) kendi kurşununu oluşturmasını sağladık. Şimdi oyunu tekrar deneyin. Ancak şimdi de fark edeceğiniz üzere düşman kurşunu bize değince hiçbir şey olmuyor. Bunu da ayarlayalım. 🙂
“biz” objesini açıp “Create” eventi içine “saglik=3” kodunu ekleyin. Bu değişken ile biz de 3 kez vurulunca öleceğiz. Ardından objeye bir “Collision ‘dusman_kursun’ “ eventi ekleyip içine şu kodu yazın:
with(other)
{
instance_destroy();
}
///////////////
if(saglik>1)
{
saglik-=1;
}
else
{
with(dusman_kursun)
{
instance_destroy();
}
hspeed=0;
vspeed=5;
alarm[1]=10;
}
Böylece eğer “saglik” değişkeni 1’den büyükse değerini 1 azaltıyoruz, yok eğer bu son sağlığımızsa da önce sahnedeki tüm düşman kurşunlarını temizliyoruz, ardından tıpkı düşmanlarda yaptığımız gibi bir ölme animasyonu oynatıyoruz. Ancak bu sefer “alarm1” eventi için kodlarımız farklı olacak. Objeye bir “alarm1” eventi ekleyip içine şu kodları ekleyin:
if(can>1)
{
can-=1;
with(dusman_kursun)
{
instance_destroy();
}
x=room_width/2;
y=room_height-48;
vspeed=0;
saglik=3;
}
else
{
show_message(“!!!KAYBETTİN!!!”);
game_restart();
}
Şimdi ilk önce karakterimizin hiç canı kalmış mı bakıyoruz. Eğer kalmışsa; canı 1 azaltıyoruz, sahnedeki tüm “dusman_kursun” obje instancelerini tekrar (varsa) yok ediyoruz. Çünkü yeniden doğar doğmaz yeni bir kurşunla yeniden vurulmak istemeyiz değil mi? Ardından karakteri odanın yarısına, ilk oluşturduğumuz konuma geri götürüyoruz (Bu değerler bende böyleydi, sizde y değeri değişiklik gösterebilir.). Ardından dikey hızı sıfırlayıp “saglik” değişkeninin değerini tekrar 3’e çıkarıyoruz.
Yok eğer bu son canımızmışsa “show_message();” ile oyuncuya bir kaybetme mesajı gösterip oyuna “game_restart();” ile restart atıyoruz. Şimdi oyunu tekrar çalıştırın ve bilerek 3 kere vurulun. Animasyonun ardından ilk 2 seferde tekrar doğduğunuzu gözlemleyin. Ancak 3. seferde kaybetmeniz ve oyunun yeniden başlaması lazım.
Artık oyunumuzu neredeyse tamamladık. Birkaç işlem kaldı sadece. Bunlardan en önemlisi de oyundaki düşman sayısının zamanla artması. Bunu sağlamak için yeni bir obje oluşturmamız lazım. Bunun için “dusman_olusturucu” isminde bir obje oluşturun ve “Create” eventine “alarm0=120;” kodunu yazın. Böylece oyun başladıktan 4 saniye sonra ikinci düşmanımız oyuna eklenecek. Bunu sağlamak için “alarm0” eventi içerisine şu kodu ekleyin:
instance_create(random(room_width),48,dusman);
alarm[0]=120;
Böylece her 4 saniyede bir odanın herhangi bir x koordinatında (random() ile yaptık.) bir “dusman” objesi instancesi oluşturuyoruz. Şimdi oyuna bir “dusman_olusturucu” ekleyip test edin. Her 4 saniyede bir yeni bir düşman oyuna eklenmeli. Bu da örnek bir resim:
Şimdi de oyunumuza biraz daha renk katacak olan can göstergesini ayarlayalım. Bu göstergede kalan canımız ve o anki skorumuz yazacak. Ayrıca sağlığımız da gözükecek. Bunun için yeni bir objeye de gerek yok, çünkü bu işlemleri “dusman_olusturucu” objesiyle halledebiliriz.
“dusman_olusturucu” objesini açın ve içine bir “Draw” eventi ekleyin. Bu event ekrana bir şeyler yazdırmaya yarar. “Draw”ın içine ise şu kodu ekleyin:
draw_text(45,room_height/2,”Kalan Can:”+string(biz.can)+” Saglik:”+string(biz.saglik)+” Skor:”+string(score));
Burada “draw_text();” ile x=45 ve y’si de odanın tam ortasından başlayan bir yazı yazarak sırasıyla kalan canı, sağlığı ve o anki skoru yazıyoruz. Burada yazının arasında bir değişkenin değerini göstermek için “+string(degisken_adi)+” komutunu kullandık. Ayrıca “biz” objesindeki değişkenlerin hepsi Local (Yerel) olup global (Evrensel) olmadıkları için örneğin “can” değişkeni için “biz.can” şeklinde bir kullanım yaptık. Yani önce ilgili objenin adını, sonra da o objede tanımlanan local değişkenin adını yazdık (Ve aralarına nokta koyduk.). Buradaki tek istisna ise “score”de yaşandı, çünkü “score” değişkeni zaten Game Maker’ın içinde hazır olarak tanımlanmış bir global değişkendir. Ayrıca yazıda Türkçe karakter kullanmadık, çünkü bu karakterler desteklenmiyor. Şimdi oyunu tekrar açın ve test edin. Aşağıdaki resimdeki gibi başarılı sonuç elde etmelisiniz:
Evet, oyunumuz için her şeyi yaptık. Sırada ne var peki? Çok basit, 500 puana ulaşınca oyunu bitirmek. Çünkü bunun haricinde kalan her şeyi tek tek yaptık. Oyunu bitirmek içinse “dusman” objesine kurşunumuz değdiğinde olan “collision” eventinde, “alarm[1]=10;” yazan kodun hemen altına, ancak if-else kapama parantezinin de üstüne şu eklemeyi yapmak:
if(score==500)
{
show_message(“!!!TEBRİKLER – KAZANDIN!!!”);
game_restart();
}
Böylece eğer skor 500’e eşit olursa oyuncuya bir tebrik mesajı gösterilir ve oyuna restart atılır.
Ve böylece; bu son eklemeyle oyunu da tamamlamış olduk. Başlangıç için hiç fena değil ha!? Eğer ki bu dersi baştan sona anladıysanız emin olun oyun tasarımında çok çabuk kavrama yeteneğiniz var, çünkü çoğu GML fonksiyonunu ya açıklamadım ya da kısaca açıkladım. Bunları zaten bildiğinizi varsayarak yerden tasarruf etmeye çalıştım. Yok, eğer derste anlamadığınız noktalar varsa da sorun etmeyin, dilerseniz siteme girip derslerime bakın (Özellikle “Sayı Tahmin Etme Oyunu” tasarlama dersine bakın.) ya da başka bir yerlerden GML’ye başlangıç için gerekli bilgilere sahip olduktan sonra bu tutorial’i tekrar baştan sona uygulayın. Seçim sizin! Ayrıca oyunun “.gmk” dosyasını da sorun yaşarsanız incelemenizi tavsiye ederim.
O halde artık başka yazılarımda görüşmek üzere!