Ana Menü
· Ana Sayfa
· Dosyalar
· Dökümanlar
· Forum
· Günün Resmi
· Haber Arşivi
· WWW Linkleri
· Üye Listesi

     Forumlar

 strncpy ve strncpy_s
 Konu adi : Borland c++ Builder ile Amiral Batti
 Rady10 - YerliOyun
 Kabusta Kaybolmak
 Konsol da programı bekletmek
 Oyun programlama icin hangi programlama dilli ?
 flash! şanlıurfa bilgisayar oyununda(no rapid)
 Sevgilim Olur musun?
 Directx'e başlamak isteyenler bi bakın
 PSP programlama
 Flash tan php
 Bilgisyr oyunu yapmam için üniverstde hangi bölüme girmeliym
 www.arshiv.gen.ms
 Cimg.h ilgilenenler icin
 müttefik oyunu

Konu Disi
 Emraah
 Yeni sitemiz açıldı
 Kalp krizi durumunda ne yapılmalı?
 Oyun sektöründe hangi görevde çalışmak isterdiniz?
 Takım arkadaşı sorunu
 msn de renklı nıck
 pc hata veriyor ! YARDIM!!
 Gülmek isteyenler Buraya
 İnanılmaz hl 2 modu görüntüsü
 Computer Languages History

[ Forumlara Git ]


Delphi İle Oyun Programlamaya Giriş

(2624 kelime)
(1369 okuma)   Yazdırılabilir Sayfa




Delphi İle Oyun Programlamaya Giriş:

Bu dokümanda Delphi ile oyun programlamaya basit bir örnekle giriş yapacağız. Delphi günümüz programlama dilleri arasında oldukça popüler ,ancak gariptir ki bir o kadar da tercih edilmeyen bir dildir. Bunun sonucu olarak Delphi ile oyun programlama konusunda internette çok fazla kaynak bulunmaz. Özellikle Türkçe kaynak birkaç forum yazışması ve PC Magazine'in özel oyun programlama köşesi(mişli geçmiş zaman) dışında hiç yoktur.Bu eksikliğin yerini bir parça olsun doldurabilmek için bu dökümanı hazırladım.Bu dökümanda mümkün olduğu kadar basit bir dil kullanmaya ve yapılan herşeyi açıklamaya çalıştım ancak gene de temel bir Delphi bilgisine ve programlama mantığına ihtiyacınız var.
Peki, önemli misyonumuzun temellerini anlattıktan sonra öncelikle malzeme listesini verelim ve kolları sıvayıp işe koyulalım.

Gerekenler:

  • Delphi 3 ve yukarısı olmak şartıyla bir Delphi geliştirme ortamı:(www.borland.com dan freeware geliştirmek şartıyla, ücretsiz temin edebilirsiniz.)[140 MB]
  • DelphiX component package:[800-900 KB]:Bu bileşen paketi Delphi altından DirectX kullanımını sağlar,tabi ki tek alternatif değil,ancak şu anda en derli toplu paket bu.Bu paketi kullanabilmek için sisteminizde DirectX 7 veya daha yüksek runtime'ın kurulu olması gerekir.Yani SDK'ya ya da header ihtiyacınız yok,bir başka deyişle sisteminizde DirectX kullanılarak yapılmış oyunları oynayabiliyorsanız başka bir şeye ihtiyacınız yok demektir.
    Delphi 6 için: http://Delphigamedev.name2host.com/files/Delphix_d6.zip
    Diğer sürümler için: http://www.yks.ne.jp/~hori/
  • En azından basit düzeyde Delphi bilgisi.(Yani,projeye bir DXDraw nesnesi ekleyin dediğim zaman bunu sorunsuzca uygulayabilmeniz.)
  • Klasik olarak, biraz sabır.

Öncelikle DelphiX bir DirectX bileşeni olduğu için temel olarak DirectX hakkında biraz söz etmemiz gerekiyor.İsterseniz soru cevap şeklinde gidelim,böylece daha eğlenceli ve eğitici bir yazı olur.

Sık sorulan sorular:


Soru 1) DirectX nedir?
Cevap 1) DirectX, Microsoft tarafından üretilen multimedia donanımına doğrudan ve hızlı erişim sağlayan ,özellikle oyun yapımında kullanılan bir kütüphaneler topluluğudur.

Soru 2) DirectX tam olarak nelerden oluşuyor?
Cevap 2) DirectX'in temel bileşenleri;
  • DirectDraw: 2 boyutlu çizimleri sağlayan bileşen
  • DirectSound:Ses (Wave,Midi) çalınmasını sağlayan bileşen
  • DirectInput:Kontrol aygıtları arayüz bileşeni
  • DirectMusic:DirectSound'dan türeme bir bileşen(DelphiX tarafından desteklenmiyor,çok işe de yaramıyor açıkçası)
  • DirectPlay: Çokluoyuncu desteği sağlayan bileşen
  • Direct3D: Tüm 3D çizim arayüzünü yöneten bileşen.

Soru 3) Neden DirectX( ya da openGL,yani neden multimedia APIsi) kullanmak gerekir ?
Cevap 3) Pek çok avantaj nedeniyle,kısaca saymak gerekirse:

  • Kolaylık: Mesela multiplayer bir oyun yapmaya çalıştığımızı düşünelim,eğer DirectX kullanmazsak bilgisayarlar arasındaki iletişimi sağlayacak kodu da bizim yazmamız gerekir. Bu fazladan efor demek olur,ve de hata olasılığını artırır. Burada DirectX herşeyi bizim yerimize yapar gibi de düşünmemek gerekir, ancak işleri önemli bir biçimde hafiflettiği ortadadır.
  • Hız: DirectX bilgisayarın grafik donanımına doğrudan erişir,bu da uygulamalarımızın çok daha hızlı işlemesini sağlar.
  • Yaygınlık: yaygın 3D API'ler için örnek kaynak kod bulmak da oldukça kolaydır.

Soru 4) Peki , ben Delphi üzerinden DirectX kullanarak her türlü oyunu rahatlıkla programlayabilir miyim?
Cevap 4) Valla rahatlıkla mı olur onu bilemem ama,Delphi (ve DelphiX ) her türlü projede kullanabilir ve hız açısından hiçbir dezavantaj yaşamazsınız.

Soru 5) DelphiX'in en önemli avantajı nedir?
Cevap 5) Kullanımının son derece kolay olması.İnanın VB daha kolay bir dil olmasına rağmen, VB'de DirectX kullanmaktan çok daha kolay DelphiX.

Soru 6) Öyleyse neden Delphi ticari oyun programlamada kullanılmıyor?
Cevap 6) Bu bir kullanım alışkanlığı meselesidir,"Bu sektördeki insanlar daha çok C ve C++ tercih ettikleri için" yanıtı çok yanlış olmaz.

DelphiX kurulum:


Şimdi sisteminizde herhangi bir Delphi sürümünün kurulu olduğunu varsayarak DelphiX'i kuruyoruz.Bu noktada en önemli şey sizin sahip olduğunuz sürüme uygun paketi kurmak.Ben Delphi6 kullanmama rağmen bulamadığım için birkaç kez eski paketlerden kurmaya çalıştım ancak hep sorun çıkartıyordu,ve sonunda 6. sürüm için olanını bulup rahat ettim.
DelphiX'i kurmak için indirdiğiniz zip dosyasını boş bir klasöre açıp sizin sürümünüze uygun dpk uzantılı dosyayı (mesela DelphiX_for3.dpk) çift tıklayın.Karşınıza gelen diyalog kutusunda Install'ı tıkladıktan sonra DelphiX ile çalışmaya başlayabilirsiniz.

Öncelikle yeni install ettiğimiz bileşenlere bir bakalım:

wpeA.jpg (5446 bytes)

Bileşen Adı

Bileşen Açıklaması

wpeD.jpg (991 bytes)TDXDraw Global DirectX bileşeni DelphiX kullanabilmek için her projede bir tane tanımlı olması gerekir.Bütün surface'ler ve diğer bileşenlerin parent object'idir.
wpeE.jpg (1005 bytes) TDXDib Bir tane aygıttan bağımsız bit eşlem resimini (Device Independent Bitmap-DIB) tutar.
wpeF.jpg (1150 bytes)TDXImageList Birden fazla DIB resmini saklamaya yarar,özellikle iki boyutlu oyunlarda grafik yönetimini kolaylaştırır.İçeriğini DelphiX'in özel formatı olan *.dxg dosyalarına saklayabilir ya da bu dosyalardan içerik yüklenebilir.(Quake 1-2 ya da Half Life'ın *.wad formatı gibi düşünebilirsiniz.)
TDX3D Bu bileşen eski DirectX sürümleriyle uyumluluk amacıyla konulmuştur.Kullanılmasına gerek yok.
TDXSound DirectSound nesnesinin kullanımını sağlar,TDXWave veya TDXWaveList'teki dosyaların çalınabilmesi için projede bir tane bulunmalıdır,ve bu bileşenlerin DXSound özelliklerine bu bileşen seçilmelidir.
TDXWave Bu bileşen aynı TDXDIB gibidir,ve tek bir wave dosyasını saklayabilir.
TDXWaveList Bu bileşen de aynı TDXImageList gibi birden fazla wave dosyasının saklanmasında kullanılır,kendi dosya uzantısı *.dxw'dir.
TDXInput DirectInput nesnesinin kullanımını sağlar,yani klavyeden mouse'tan ve joystickten gelen mesajları algılamamızı sağlar.
TDXPlay DirectPlay nesnesinin kullanımını sağlar,Multiplayer oyunlarda kullanılır.
TDXSpriteEngine Özellikle Sprite içeren iki boyutlu oyunlarda kullanılır,Resim saklama,koordinat tutucu ve çarpışma denetimi gibi gelişmiş özellikler içerir.
TDXTimer Delphi'nin System bileşenleri altında bulunan Timer'dan çok daha hassas bir timer,genellikle her oyunda bulunan genel döngüyü içerir.
TDXPaintBox Delphinin standart TImage'inin DelphiX versiyonu.

İşte ilk projemiz:


1.Delphi'de File->New Application'ı seçerek yeni bir proje oluşturun. Öncelikle DirectX çizim kütüphanelerini kullanabilmek için Formumuza bir adet TDXDraw Nesnesi eklemeliyiz.Bu nesne varsayılan olarak 100x100 boyutlarında bir kontrol olarak gelir.DxDraw1'in ve Formunuzun Width ve Height özelliklerini 640x480'e ayarlayın.DXDraw1'in Forma otomatik olarak yerleşmesini istiyorsanız DXDraw1'in Align özelliğini alClient olarak değiştirin.DXDraw1'i formumuzun istediğimiz herhangi bir yerine taşıdıktan sonra,ikinci önemli bileşen olan TDXTimer'dan formumuza bir adet eklemeliyiz.Bu bileşeni eklememizin nedeni yukarıda da belirttiğim gibi hemen her oyunda bir genel döngünün bulunması gerekliliğidir.(Bunu aşağıda daha ayrıntılı açıklayacağım) DXTimer'ımızın Interval özelliği normal Timer'larda olduğu gibi saniyenin 1000de kaçında işlem yapacağını gösterir.Biz mümkün olan en yüksek FPS'yi(frame per second,yani bir görüntünün 1 saniyede kaç kez çizildiği) elde etmek için bunu 0 olarak ayarlıyoruz

2. Şimdi ekrana bir resim dosyasını çizebilmek için bir Surface tanımlayacağız(Surface nedir:Surface DirectDraw'un temelidir denebilir,surface üzerine çizim yapabileceğimiz,ya da bir dosyadan içerik yükleyebileceğimiz bir hafıza alanıdır,Surface'leri TImage bileşenleri olarak düşünebilirsiniz,tek fark siz istemedikçe Surface'lerin ekranda görünmemesidir.Surfacelerin içeriği siz tersini seçmedikçe video kartın belleğinde saklanır.),aslında bu işi bir DxImageList kullanarak çok daha kolay bir biçimde halledebiliriz,ancak ben Surface tanımlamanın çok daha faydalı ve ileriye dönük bir yöntem olduğunu düşünüyorum.Neyse kod pencerenizde TForm1 class'ının private yordamlarının altına alttaki eklemeyi yapın :

ilkyuzeyim:TDirectDrawSurface;

Yani şöyle olmalı:

type
TForm1 = class(TForm)
DXDraw1: TDXDraw;
DXTimer1: TDXTimer;
private
ilkyuzeyim:TDirectDrawSurface; //Bizim yaptığımız ekleme
{ Private declarations }
public
{ Public declarations }
end;


3. Şimdi bu Surface'i kullanmak için gereken kodları yazacağız.Öncelikle Delphi'de herhangi bir nesneyi kullanmak için her zaman gerektiği gibi bu Surface'i de (create) yaratmalıyız.Bu işlem için en uygun yer DXDraw nesnemizin onInitialize event'idir.Formumuzda DXDraw1'i seçtikten sonra Object Inspector'un Events sekmesine gelip onInitialize kısmındaki boşluğu çift tıklayın.Önünüze gelecek kod penceresine aşağıdaki kodları ekleyin:

procedure TForm1.DXDraw1Initialize(Sender: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface.Create(Dxdraw1.DDraw); //Surface'i DXDraw'un DirectDraw nesnesini
kullanarak yarat.

ilkyuzeyim.LoadFromFile(extractfilepath(application.ExeName)+'gordon.bmp');//Surface'e uygulamamızla
aynı klasörde bulunan "gordon.bmp" dosyasını yükle. Extractfilepath fonksiyonu herhangi bir dosya
isminden dosya yolunu ayırır,yani extractfilepath ("c:\levent.txt") ,"c:\" değerini döndürür.

end;


4. Şimdi final kısma geliyoruz.Çizim nesnesini(DXDraw1) ekledik,çizim kaynağı olan surface'i(ilkyuzeyim) yarattık ve içeriğini yükledik,şimdi surface'den DXDraw'a çizim yapacağız,gerekli kodu DXTimer'ın onTimer metodunun altına yazmamız gerekiyor.Burada küçük bir parantez açıp neden bir kez ilk çalışma anında çizim yapıp daha sonra bunun üzerine devam edemeyeceğimizi (yani neden bir döngüye ya da Timer'a ihtiyacımız olduğunu) kısaca açıklayayım,eskiden DOS'ta programlama yaparken DOS'un single-tasking yapısı sayesinde programınız(ya da oyununuz) çalışırken ekrana erişen başka hiçbir yazılım olmayacağını bilirdiniz,bu da ekrana önceden ne çizildiğini hafızada tutma gerekliliğini ortadan kaldırıyordu.Ancak Windows multi-tasking bir işletim sistemi olduğu ve sizin programınızla beraber pek çok uygulamayı da çalıştırdığı için sizin pencereye kendini yeniden çizmesi gerektiği emrini belirli aralıklarla vermeniz gerekir,yoksa ekrana erişen başka uygulamalar görüntüde kalır. Ayrıca oyun içinde yeri değişen objelere göre arkaplan ve objeler yeniden çizilmezse(ve bu işlem çok hızlı yapılmazsa) ekranda flicker denilen bir önceki karenin gölge gibi arkadan gelmesi sorunu ortaya çıkar.Biz de burada bunları önlemek için DXTimer kullanıyoruz ve Interval'i düşük tutuyoruz.Neyse çok konuştuk biraz da iş yapalım,alttaki kodu DXTimer1'in onTimer event'ine ekleyin.

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
dxdraw1.Surface.Draw(0,0,rect(0,0,640,480),ilkyuzeyim,false);// dxdraw1 esas çizim nesnemiz olduğu
gibi,ona ait surface'e yapacağımız her çizim de ekranda görünecektir.Burada Draw metoduyla,sırasıyla
ekrana çizim yapılacak koordinatları (x,y) kaynak dörtgeni (yani kaynak surface'deki resmin ne
kadarını) ve de kaynak surface'in adını ve son olarak ta transparan olarak çizilip çizilmeyeceğini
belirtiyoruz.Biz burada Draw diyerek 0,0 koordinatına kaynak resmin 0'dan 640'a genişlik ve 0'dan 480'e
boy olarak transparan olmadan çizilmesini sağladık.

dxdraw1.Flip;// Bu kısım dxdraw'a bütün çizim bittikten sonra çağırılmalıdır.Dxdraw'un ekrana
basılmasını söyler.(yani flip edilmesini) Eğer eklemezseniz sistem kilitlenebilir.

end;


5. Herşey tamamsa Run'a basın ve Gordon Freeman'ı tüm karizmasıyla görün.Tebrikler Delphi'de DirectX kullanarak ekrana bir resim çizdirmeyi başardınız.

Biraz derinlere:

6. Herşey bu kadar mı?,evet, en basit uygulama bu kadar,ancak ben bu basit uygulamaya biraz daha özellik eklemek istiyorum.şöyle basit bir ateş etme efekti fena olmaz değil mi?,bunun için 2. basamakta yaptığımız gibi yeni bir surface daha ekleyeceğiz. Yine private yordamının altına

silah:TDirectDrawsurface;

kısmını ekleyin.ve 3. basmaktaki kodlara alttaki eklemeleri yapın

silah:=TDirectDrawSurface.Create(Dxdraw1.DDraw);
silah.LoadFromFile(extractfilepath(application.ExeName)+'Gun.bmp');

bu noktaya kadar bir farklılık yok,ancak şimdi ufak bir ekleme yapacağız,yukarıdaki kodların hemen altına şu tek satırı ekleyin,bu silah surface'inin hangi rengi transparan göstereceğini, yani çiz emri verdiğimizde hangi rengi çizmeyeceğini belirtir:

silah.TransparentColor :=silah.Pixels[1,1];

DXDraw1 in onInitialize event'inin altı şöyle olmalı:

procedure TForm1.DXDraw1Initialize(Sender: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface.Create(Dxdraw1.DDraw);
ilkyuzeyim.LoadFromFile(extractfilepath(application.ExeName)+'gordon.bmp');
silah:=TDirectDrawSurface.Create(Dxdraw1.DDraw);
silah.LoadFromFile(extractfilepath(application.ExeName)+'Gun.bmp');
silah.TransparentColor :=silah.Pixels[1,1]; //Pixels[1,1] surface'in 1,1 koordinatındaki rengi transparan
renk olarak seçer.Bu bizim resim dosyamızda eflatundur.

end;

Şimdi bu surface'i de DXTimer'ın onTimer eventinin altında çizdirmenin bir manası olmayacak o yüzden daha farklı bir uygulama yapacağız.Aşağıdaki kodu DXDraw1'in onMouseUp eventinin altına ekleyin:

procedure TForm1.DXDraw1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ilkyuzeyim.Draw(x-16,y-16,rect(0,0,32,32),silah,true); // burada ilkyuzeyim surface'imizin üstüne silah
surfaceini transparan olarak çiziyoruz. X ve y koordinatları mouse'un ekrana tıklandığı koordinatlar,x
ve y'den 16 çıkartarak gun.bmp resmini tam ortalıyoruz(resim 32x32 çünkü).Burada silah surfaceini
ilkyuzeyin üstüne çizmemizin nedeni (daha doğrusu doğrudan DXDraw1'in üstüne çizmememizin nedeni)
DXDraw saniyenin 1000'de 1nde yeniden çizilirken buradaki kod sadece biz ekrana tıkladığımızda
işleyecek bu yüzden eğer DXDraw'a çizersek biz tıkladıktan 1-2 milisaniye sonra ilkyuzey yeniden
DXDraw1'e çizilmiş olacak ve biz hiçbir şey göremeyeceğiz.Bu etkiyi incelemek için timer'ın Intervalını
yükseltip DXDraw'a çizmeyi deneyebilirsiniz.

end;

tamam yeniden çalıştırıp gordon abinize birkaç el ateş edin bakalım.

7. Bir de ses mi ekleyelim? Tamam bana uyar, ses efekti için bir wave dosyasına ,sesleri çalabilmek için bir DXSound nesnesine ihtiyacımız var.projeye bir tane DXSound nesnesi ekleyin. Yine 2. basmakta açıklanan private yordamının altına gidin ve şu eklemeyi yapın:

silah_ses:TDirectSoundBuffer;

sonuç şöyle olmalı:

private
ilkyuzeyim:TDirectDrawSurface;
silah:TDirectDrawsurface;
silah_ses:TDirectSoundBuffer;
{ Private declarations }
public
{ Public declarations }
end;

Şimdi 3.basamaktaki gibi bu ses buffer'ını yaratmalıyız,DXDraw1 onInitialize olayına gidin ve aşağıdaki eklemeyi yapın:

silah_ses:=TDirectSoundBuffer.Create(DxSound1.DSound );
silah_ses.LoadFromFile(extractfilepath(application.ExeName)+'gun.wav');

sonuç şöyle olmalı:

procedure TForm1.DXDraw1Initialize(Sender: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface.Create(Dxdraw1.DDraw);
ilkyuzeyim.LoadFromFile(extractfilepath(application.ExeName)+'gordon.bmp');
silah:=TDirectDrawSurface.Create(Dxdraw1.DDraw);
silah.LoadFromFile(extractfilepath(application.ExeName)+'Gun.bmp');
silah.TransparentColor :=silah.Pixels[1,1];
silah_ses:=TDirectSoundBuffer.Create(DxSound1.DSound ); //mantık çizim surface'i ile tamamen aynı
sadece burada ses objelerine referans veriyoruz.

silah_ses.LoadFromFile(extractfilepath(application.ExeName)+'gun.wav'); //Dosyamızı da yükledik.
end;

Şimdi DxDraw1'in onMouseUp eventine gidip son eklemeyi yapın:

silah_ses.Play(false);

Yani sonuç böyle olmalı:

procedure TForm1.DXDraw1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ilkyuzeyim.Draw(x-16,y-16,rect(0,0,32,32),silah,true);
silah_ses.Play(false); //false parametresi sesin loop etmesini yani sürekli çalınmasını engeller,eğer true
verirseniz bir kere tıkladığınızda ses sürekli çalar.

end;

Eveet, böylece işimiz tamamlandı.Umarım hoşunuza gitmiştir.İsterseniz sitemizde "dosyalar/döküman_ek" bölümünde de yer alan örnek proje dosyasını [ buradan ] indirebilir ve inceleyebilirsiniz.En karizma oyun kahramanlarından olan Gordon Freeman'ı da böylece harcamış olduk ama olsun, önemli olan bu yazıdan birşeyler öğrenmiş olmanız.Benden şimdilik bu kadar,herhangi bir şey sormak için buradaki forumu kullanabilir ya da leventbbayar@operamail.com adresine mail atabilirsiniz.Derslerim izin verdikçe daha başka DelphiX dökümanları yazmayı düşünüyorum.Tabi bu sizden gelecek talebe de bağlı.

Levent Baykan Bayar :: 2003-03-03 :: www.oyunyapimi.org
  

[ Geri Dön: Oyun Yapımı (Genel) | Bölümler İndeksi ]




Web site powered by PHP-Nuke
Web site engine\'s code is Copyright © 2002 by PHP-Nuke. All Rights Reserved. PHP-Nuke is Free Software released under the GNU/GPL license.
Sayfa Üretimi: 0.046 Saniye