Ekim 1

Lazarus ile Yazılım Uygulamaları – 1 / Yılan Oyunu

Yılan Oyunu


PROGRAMIN TANIMI VE ÇALIŞMA MANTIĞI

       Merhabalar, yılan oyunu belkide bilgisayar tarihinin en eski ve zekli oyunlarından biridir. Basit, sürükleyici ve yazan kişiye bağlı olarak geliştirilebilir bir oyundur.Tabi bizim burada yazacak olduğumuz oyun çok gelişmiş bir oyun olmayacak ama hayal gücünüze ve programlama bilginize bağlı olarak geliştirmeyi kendiniz rahatlıkla yapabileceksiniz.

       Yılan oyununda temelde iki nokta vardır. Bunlardan ilki halilen yedikçe uzayan bir yılan ve ikincisi yılanın uzamasını sağlayan yem. Bu iki mantığı güzel kurarsanız oyunu istediğiniz gibi zenginleştirirsiniz isterseniz duvarlar ekleyin, isterseniz değişik yemlerle farklı etkiler yaratın hep uzaması yerine bağzen hızlanan bağzense kısalan bir yılan yapabilirsiniz bu artık sizin hayal gücünüze kalmış.
       Böyle bir oyunu yazmak için nerden başlamak gerekir. Önce yılanın mantığını doğru anlamalıyız. Yılan pekçok parçadan oluşan ama kullanıcının sadece ilk parçayı kontrol ettiği bir nesne. Yani yılan 10 parçadan da oluşsa 100 parçadan da oluşsa kullanıcı sadece ilk parçayı kontrol ediyor. Yılanla ilgili ikinci durum her parçanın kendine özgü olmasıdır. Birinci parça aşağıya doğru giderken 15. parça sola 19. parça sağa gidebilir bu durumdan şöyle birşey ortaya çıkıyor. Esas kayıt tipimiz (type) yılan değil aslında parça ve yılan bu parçalardan oluşuyor. Yani yilan: array [0..100] of TParca; ve parça olarak tanımladığımız sınıfta olması gereken ilk tanım YÖN. Peki parçada yön haricinde başka ne tür bilgiler bulunmalı. Oyunda bildiğiniz gibi her parça bir önceki parçanın yerine yerleşir. Oyun tablosunda ise yer 2 temel bilgiden oluşur X ve Y. Demek ki parça YON , X ve Y bilgilerinde oluşması gerekiyormuş .

type
  TParca = record
  EksenX: integer;
  EksenY: integer;
  yon: byte;
end;

       Şimdi sıra yemin nasıl bir bilgi barındıracağına geldi. Yem tablanın üstünde belli zamanlarda rastgele yerlere yerleşen ve belli bir süre sonra ekrandan kaybolan nesneler olacak. Yemlerde herhangi bir hareketlilik bulunmayacak bu durumda yön gibi bir bilgi tutmayacağız. Ama tabla üstünde rastgele yerleşimler olması X ve Y bilgilerini barındırmamız gerektiğini gösteriyor.

Bu durumda yem (ben elma diyorum 🙂 )

TElma = record
  EksenX: integer;
  EksenY: integer;
end;

       Tipinde olması gerekir.

        Sonuç olarak klavye tuşlarımıza göre hareket eden ve her parçanın birbirini izlediği bir yılan, Bu yılanı büyüten bir yem ve bu yılanın hareket ettiği bir tabla hazırlamamız gerekecek.
Tablayı pek çok farklı şekilde yapabiliriz.

       Bunlardan biri GRID bileşeni kullanarak olabilir ve işimizi kısmen kolaylaştıradabilir. Ama öğrenmek için yapılan bir yazılımda işin biraz daha zorlaşmasının bir mahsuru olacağını sanmıyorum. Ben grid yerine 400×400 piksellik bir PANEL bileşenini tabla olarak kullanacağım ve bu tablayı 20’ye 20, X ve Y eksenlerine böleceğim. Peki Nasıl ?

PEKİ NASIL ?

        Artık yavaş yavaş programı yazmaya başlıyalım.

        Öncelikle lazarus’da standart olarak açılan forma iki adet panel ekleyeceğiz bunlardan birinin align özelliğini Top diğerinide Client yapıyoruz. Top olarak ayarladığımız panel başlık, diğeride yılanın dolaştığı tabla oluyor. Yılanın dolaştığı tablanın rengini siyah olarak ayarlayıp, başlık kısmına puan göstermek için bir adet label ve oyunun bitişini gösteren bir adet labelda tablaya ekledikten sonra görsel bileşenlerimizi tamamlamış oluyoruz. Tabi oyunun bittiğini yazan görsel bileşenin visible özelliğini false yapıyoruz.

        Bunun dışında da görsel olmayan 3 adet timer’ı formumuza ekliyoruz. Bu timerlardan biri yılan hareketini takip, diğeri yem oluşturmak sonuncusu ise yemleri temizlemek için kullanılacak.

       İlk önce genel değişkenlerden ve form.create olayından başlayalım. Programa genel değişkenler olarak ;

var
  Form1: TForm1;
  yilan: array [0..100] of TParca;
  elma: array [0..5] of TElma;
  uzunluk: byte;
  yon: byte;
  puan: integer;
  son_yilan_x : byte;
  son_yilan_y : byte;
  elma_sayisi: byte;
  basildi:Boolean;
  {yon = 0 => Sağ
   yon = 1 => Sol
   yon = 2 => Yukari
   yon = 3 => Asagi
   }
  carpan: byte;



       İsimlerden de anlaşılacağı gibi esas kontrol elemanımız yılan (100 parça uzunluğunda), yılanımız için gerekli olan yem (elma 5 parça uzunluğunda), yılanın uzunluğunu tutan uzunluk değişkeni, yılanın bir sonraki yönünü belirten yön değişkeni, oyundaki puanımız, son yılan parçasının bulunduğu X ve Y noktaları, parçaların boyutunu tanımlayan carpan değişkeni ve bir sonraki tuş girişi için programın hazır olup olmadığını belirten basıldı değişkeni.
       Burada basıldı değişkeninin biraz daha açıklamak gerektiğini düşünüyorum. Basıldı değişkeni klavyeden kullanıcının herhangi bir tuşa basmasından sonra yılanın bu pozisyona geçip geçmediği durumunu tutar. Bunun nedeni kullanıcı ard arda birkaç tuşa basarken daha yılanın ilk hamleyi bile yapmamış olduğu halde yönlerin birbiriyle  ters olması nedeniyle oyunun bitebilmesi durumudur. Örnek olarak yılanın aşağıya doğru gittiğini düşünün, siz sağ oka basıyorsunuz ardından yıkarı ve sol diyorsunuz ama daha yılan sağa dönmeden yukarı ve sol yapmış gibi davranıp size oyun sonu mesajı gösteriyor. Basıldı değişkeni bunu engellemek için kullanılıyor ve yılan her hamlesinden sonra false durumunu alıyor.

 

procedure TForm1.FormCreate(Sender: TObject);
begin
  uzunluk := 2;  // Yılanın uzunluğu
  puan := 0;
  // İlk üç yılanın tanımı
  yilan[0].EksenX := 3;
  yilan[0].EksenY := 0;
  yilan[0].yon := 0;
  yilan[1].EksenX := 2;
  yilan[1].EksenY := 0;
  yilan[1].yon := 0;
  yilan[2].EksenX := 1;
  yilan[2].EksenY := 0;
  yilan[2].yon := 0;
  // Son yılanın panel üzerindeki yeri
  son_yilan_x := 0;
  son_yilan_y := 0;
  // Tabladaki elma sayısı
  elma_sayisi := 0;
  // Oyun bağladığında yılanın gideceği yön
  yon := 0;
  // Yılanın boyutu
  carpan := 20;
  // Klavyeden tuş almak için hazır olma durumu
  basildi:=true;
end;

 Form Create olayı

procedure TForm1.FormKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
begin
  if (key = 40) and not(yon = 3) and basildi = true then yon := 2;
  if (key = 39) and not(yon = 1) and basildi = true then yon := 0;
  if (key = 37) and not(yon = 0) and basildi = true then yon := 1;
  if (key = 38) and not(yon = 2) and basildi = true then yon := 3;
  basildi :=false;
end;

Bu kodda not ( yon = * ) dememizin nedeni yılanın bir yönde giderken tek bir tuşla tam tersi yöne gitmesini engellemek.

 

procedure TForm1.Timer_YilanTimer(Sender: TObject);
var
  i: integer;
begin
  i := 0;
  panel2.Canvas.Brush.Color := clBlack;  // Siyah rengini al
  // Önceki turdaki yılan parçalarından en son kareyi siyaha boya
  panel2.Canvas.Rectangle(son_yilan_x * carpan, son_yilan_y * carpan,
    (son_yilan_x + 1) * carpan, (son_yilan_y + 1) * carpan);
  // Bir sonraki tur için bu turdaki en son yilan karesinin bulunduğu yeri
  // kaydet
  son_yilan_x := yilan[uzunluk].EksenX;
  son_yilan_y := yilan[uzunluk].EksenY;

  for i := uzunluk downto 0 do
  begin
    // Eğer yılan karesinin ilerisi kırmızı renkte ise
    if Panel2.Canvas.Pixels[(yilan[i].EksenX + 1) * (carpan - 1),
      (yilan[i].Ekseny + 1) * (carpan - 1)] = clRed then
    begin
    // Puanı arttır ve yeni puanı ekrana yaz
      puan := puan + 10;
      label1.Caption := 'PUAN : ' + IntToStr(puan);
    // Yılanın uzaması için gereken procedure'ü çağır
      puan_ekle;
    end;
    // Eğer yeni boyanacak olan bölge mavi renkte ise oyunu bitir.
    if Panel2.Canvas.Pixels[(yilan[0].EksenX + 1) * (carpan - 1),
      (yilan[0].Ekseny + 1) * (carpan - 1)] = clBlue then
      oyun_bitti;
    // Bu alana gelindiğine göre oyunu bitirecek bir neden yok ve yılanı
    // bir kare ilerlet
    panel2.Canvas.Brush.Color := clBlue;
    panel2.Canvas.Rectangle((yilan[i].EksenX) * carpan, (yilan[i].EksenY) *
      carpan, (yilan[i].EksenX + 1) * carpan, (yilan[i].EksenY + 1) * carpan);
    if i > 0 then
      yilan[i] := yilan[i - 1];
 // Yılan bir kare ilerlediği için yılanı oluşturan
 // parçaların sırası bir öncekine doğru ilerler ve
 // 0.parça yon değişkeninin durumuna göre yeni değerlerini alır
  end;
  if yilan[0].yon = 0 then
    yilan[0].EksenX := yilan[0].EksenX + 1;
  if yilan[0].yon = 1 then
    yilan[0].EksenX := yilan[0].EksenX - 1;
  if yilan[0].yon = 2 then
    yilan[0].EksenY := yilan[0].EksenY + 1;
  if yilan[0].yon = 3 then
    yilan[0].EksenY := yilan[0].EksenY - 1;
  // Eğer yeni değerler 0 ile 20 arasında değil ise oyun biter
  if not (yilan[0].EksenX in [0..20]) or not (yilan[0].EksenY in [0..20]) then
    oyun_bitti;
  // Oyun bitmediğine göre yeni değeri 0.parçaya aktar
  yilan[0].yon := yon;
  basildi := True;  // Yeni tuş için hazır olduğunu belirt
end;

procedure TForm1.Timer_Elma_KontrolTimer(Sender: TObject);
var
  z: integer;
begin
  if elma_sayisi > 0 then
  begin   // Elma Sayısı sıfırdan büyük ise
   {0. elmanın olduğu yere bak eğer o noktada renk kırmızıdan farklı ise
    elma ya yenmiştir ve renk siyahtır ya da yılan üzerinden geçmiştir ve
    renk mavidir }
    if Panel2.Canvas.Pixels[(elma[0].EksenX + 1) * (carpan - 1),
      (elma[0].Ekseny + 1) * (carpan - 1)] <> clRed then
    begin
       { Bu durumda 0. elma yenilmiş olduğu için onu iptal et ve diğer elmaları
         bir geriye kaydır. }
      for z := 0 to elma_sayisi do
        elma[z] := elma[z + 1];
      // 0. Elma yenilmiş olduğu için elma sayısını bir düşür
      elma_sayisi := elma_sayisi - 1;
      // Elma kontrolünü tekrar yap
      Timer_Elma_KontrolTimer(self);
      // Buraya dönünce timer uygulamasına devam etme ve bu olaydan ayrıl
      abort();
    end;
    // Bu kod satırına gelindiğine göre elma yenilmemiş durumda
    panel2.Canvas.Brush.Color := clBlack;
    // Elmanın bulunduğu yeri siyah renkle boya
    panel2.Canvas.Rectangle((elma[0].EksenX) * carpan, (elma[0].EksenY) *
      carpan, (elma[0].EksenX + 1) * carpan, (elma[0].EksenY + 1) * carpan);
    // Elmaların yerlerini bir sıra kaydır
    for z := 0 to elma_sayisi do
      elma[z] := elma[z + 1];
    // Elma sayısını bir düşür
    elma_sayisi := elma_sayisi - 1;
  end;

end;

Buradaki kodların yanında açıklama olduğu için tekrar açıklama yapmıyorum.

procedure TForm1.Timer_Elma_OlusturTimer(Sender: TObject);
var
  i: integer;
  z: integer;
  r_x: byte; // Oluşacak elma için rastgele X
  r_y: byte; // Oluşacak elma için rastgele Y
  onay: boolean; // Oluşacak eksende yılanın varlığı (True ise yok False ise var)
begin
  Timer_Elma_Kontrol.Interval := 10000; //Elma kontrol timer'ını başlat
  onay := True; //Onay değişkenine ilk değer ver
  r_x := Random(20); // 20 sayı içinden rastgele bir değer seç
  r_y := Random(20);
  if elma_sayisi < 5 then
  begin
    for z := uzunluk downto 0 do
      if (yilan[z].EksenX = r_x) and (yilan[z].EksenY = r_y) then
        onay := False; // Elma için seçilen koordinatları bütün yılan parçalarında kontrol et
    if onay = True then
    begin
      panel2.Canvas.Brush.Color := clRed;
      panel2.Canvas.Rectangle(r_x * carpan, r_y * carpan, (r_x + 1) *
        carpan, (r_y + 1) * carpan);
      elma[elma_sayisi].EksenY := r_y;    // Kırmızı renkte bir elma oluştur
      elma[elma_sayisi].EksenX := r_x;
      elma_sayisi := elma_sayisi + 1;     // Ve elma sayısı bir arttır
    end;
  end;
end;

Programın sonuna iyice yaklaştık.

Şimdi son iki procedure kaldı bunlardan biri puan_ekle, diğeri ise oyun_bitti.

 

procedure puan_ekle;
var
  i: integer;
begin
  uzunluk := uzunluk + 1;   // uzunluğu bir arttır
  for i := uzunluk downto 0 do
    if i > 0 then
      yilan[i] := yilan[i - 1]; // Yılan parçalarını sırala
end;

procedure Oyun_bitti;
begin
  form1.Timer_Elma_Kontrol.Interval := 0;     // Bütün timer'ları kapat
  form1.Timer_Elma_Olustur.Interval := 0;
  form1.Timer_Yilan.Interval := 0;
  form1.Label2.Visible := True;       // Oyun bitti yazısını göster
end;

Eveet oyunun yazılımını artık bitirdik.
Umarım Lazarus-Pascal ve programlama hakkında faydalı bir kaynak olmuştur.

 PROGRAMIN KAYNAK KODU VE PDF DOKUMANI İÇİN BURAYI TIKLAYINIZ….

Did you like this? Share it:

Etiketler:, , , , , ,

Posted 01 Ekim 2011 by admin in category Lazarus, Programlama, Uygulamalar

2 thoughts on “Lazarus ile Yazılım Uygulamaları – 1 / Yılan Oyunu

Leave a Comment

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*