Sayfa: [1]   Aşağı git
  Yazdır  
Gönderen Konu: Delphi ile oyun progralamaya giriş ....  (Okunma Sayısı 663 defa)
0 Üye ve 1 Ziyaretçi konuyu incelemekte.
rasitc
Yeni Üye
*

Karma: 0
Offline Offline

Cinsiyet: Bay
Mesaj Sayısı: 11



Üyelik Bilgileri WWW
« : 14 Ağustos 2008, 22:35:58 »

Delphi ile oyun progralamaya 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ı
Linklerin Görülmesine Izin Verilmiyor
Linki Görebilmek Için Üye Ol veya Giris Yap
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:
Linklerin Görülmesine Izin Verilmiyor
Linki Görebilmek Için Üye Ol veya Giris Yap
http://Delphigamedev.name2host.com/files/Delphix_d6.zip

Diğer sürümler için: Linklerin Görülmesine Izin Verilmiyor
Linki Görebilmek Için Üye Ol veya Giris Yap
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
DirectMusicirectSound'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:




İş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(Sende r: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface .Create(Dxdraw1.DDra w); //Surface'i DXDraw'un
DirectDraw nesnesini
kullanarak yarat.
ilkyuzeyim.LoadFromFile(extrac tfilepath(applicatio n.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),ilkyuze yim,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.Crea te(Dxdraw1.DDraw);
silah.LoadFromFile(extractfile path(application.Exe Name)+'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(Sende r: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface .Create(Dxdraw1.DDra w);
ilkyuzeyim.LoadFromFile(extrac tfilepath(applicatio n.ExeName)+'gordon.bmp');
silah:=TDirectDrawSurface.Crea te(Dxdraw1.DDraw);
silah.LoadFromFile(extractfile path(application.Exe Name)+'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.DSou nd );
silah_ses.LoadFromFile(extract filepath(application .ExeName)+'gun.wav');

sonuç şöyle olmalı:

procedure TForm1.DXDraw1Initialize(Sende r: TObject);
begin
ilkyuzeyim:=TDirectDrawSurface .Create(Dxdraw1.DDra w);
ilkyuzeyim.LoadFromFile(extrac tfilepath(applicatio n.ExeName)+'gordon.bmp');
silah:=TDirectDrawSurface.Crea te(Dxdraw1.DDraw);
silah.LoadFromFile(extractfile path(application.Exe Name)+'Gun.bmp');
silah.TransparentColor :=silah.Pixels[1,1>;
silah_ses:=TDirectSoundBuffer. Create(DxSound1.DSou nd ); //mantık çizim surface'i
ile tamamen aynı
sadece burada ses objelerine referans veriyoruz.
silah_ses.LoadFromFile(extract filepath(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.
Logged
Meraklı
Acemi Üye
**

Karma: 0
Offline Offline

Cinsiyet: Bay
Mesaj Sayısı: 31


Üyelik Bilgileri
« Yanıtla #1 : 26 Ağustos 2008, 21:07:16 »

Sagol Guzel anlatım .. aynen devamm
Logged
SedoRKinG
Yeni Üye
*

Karma: 0
Offline Offline

Cinsiyet: Bay
Mesaj Sayısı: 1


Üyelik Bilgileri
« Yanıtla #2 : 08 Eylül 2008, 02:28:53 »

Çok teşekkürler gayet yararlı oldu emin olun sıkılmadan anlattığınız için çok teşekkürler ben şu browser oyunları gibi bi delphide offline oyun yapmak istiyorum acaba bu konuda bir döküman yada bilginiz varmı?
Logged
Sayfa: [1]   Yukarı git
  Yazdır  
GoogleTagged

 
Gitmek istediğiniz yer: