Selam olsun size Ötüken’in onurlu gençleri,
Blogu kuralı tamı tamına iki sene olmuş fakat içerisinde dişe dokunur bir sayıda gönderi maalesef yok. Fakat artık günlük bir post atma kararı aldım.
Eveeetttt… Bugün amatör olarak yapmaya çalıştığım oyun motorumdan(game engine) ufak bir pascal dosyasını sizinle paylaşacağım dostlar. Büyük ihtimal içerisinde ki kodları bir yerlerden direk veya dolaylı olarak aldım çünkü hatırlamıyorum nereden geldi. Sahibi hakkını helal etsin lütfen.
unit Engine.Core.Collision;
interface
uses
System.Classes, System.Types, FMX.Graphics, FMX.Objects;
function CheckBoundryCollision( R1, R2 : TRect; pR : PRect = nil; OffSetY : LongInt = 0; OffSetX : LongInt = 0): boolean; {overload;}
function CheckImageCollision( R1, R2 : TImage; pR : PRect = nil; OffSetY : LongInt = 0; OffSetX : LongInt = 0): boolean; {overload;}
implementation
uses
IdHttp, IdTCPClient;
function CheckBoundryCollision( R1, R2 : TRect; pR : PRect = nil; OffSetY : LongInt = 0; OffSetX : LongInt = 0): boolean; {overload;}
begin
if( pR <> nil ) then
begin
with( R1 ) do
R1:=Rect( Left+OffSetX, Top+OffSetY, Right-(OffSetX * 2), Bottom-(OffSetY * 2));
with( R2 ) do
R2:=Rect( Left+OffSetX, Top+OffSetY, Right-(OffSetX * 2), Bottom-(OffSetY * 2));
Result:=IntersectRect( pR^, R1, R2 );
end
else begin
Result:=( NOT ((R1.Bottom - (OffSetY * 2) < R2.Top + OffSetY)
or(R1.Top + OffSetY > R2.Bottom - (OffSetY * 2))
or( R1.Right - (OffSetX * 2) < R2.Left + OffSetX)
or( R1.Left + OffSetX > R2.Right - (OffSetX * 2))));
end;
end;
function CheckImageCollision( R1, R2 : TImage; pR : PRect = nil; OffSetY : LongInt = 0; OffSetX : LongInt = 0): boolean; {overload;}
Var
B1,B2 : TRect;
begin
B1 := R1.BoundsRect.Round;
B2 := R2.BoundsRect.Round;
if( pR <> nil ) then
begin
with( B1 ) do
B1:=Rect( Left+OffSetX, Top+OffSetY, Right-(OffSetX * 2), Bottom-(OffSetY * 2));
with( B2 ) do
B2:=Rect( Left+OffSetX, Top+OffSetY, Right-(OffSetX * 2), Bottom-(OffSetY * 2));
Result:=IntersectRect( pR^, B1, B2 );
end
else begin
Result:=( NOT ((B1.Bottom - (OffSetY * 2) < B2.Top + OffSetY)
or(B1.Top + OffSetY > B2.Bottom - (OffSetY * 2))
or( B1.Right - (OffSetX * 2) < B2.Left + OffSetX)
or( B1.Left + OffSetX > B2.Right - (OffSetX * 2))));
end;
end;
end.
Kullanımını;
If CheckImageCollision(ImageOyuncu,ImageDusman) Then
ShowMessage('Çarpıştık loo');
Şeklinde kullanabilirsiniz.
Temel mantığı objelerin üst üste çıkıp çıkmadıklarını kontrol ediyor. Bu yüzden gerekli kontrolleri sağlamazsanız obje üst üste gelince uyarıyı verecektir. Peki o kontrolleri nasıl sağlarız;
Diyelim ki bir ana karakterimiz(ImageAnaKarakter) bir de duvarımız(ImageDuvar) ve son olarak bir adet butonumuz(Button1). Butonun onclick olayına;
procedure TForm1.Button1Click(Sender: TObject);
var
eskiX,eskiY : Integer;
begin
eskiX := ImageAnaKarakter.Position.X; //Ana karakterimizin hareket etmeden önceki x pozisyonu
eskiY := ImageAnaKarakter.Position.Y; //Ana karakterimizin hareket etmeden önceki y pozisyonu
ImageAnaKarakter.Position.X := ImageAnaKarakter.Position.X + 10; //Ana karakterimizi sağa(+x) doğru 10 koordinat ilerletiyoruz
If CheckImageCollision(ImageAnaKarakter,ImageDuvar) Then // Çarpışma var mı? Eğer varsa;
Begin
ImageAnaKarakter.Position.X := eskiX; //Ana karakterimizi geri x pozisyonuna çektik
ImageAnaKarakter.Position.Y := eskiY; //Ana karakterimizi geri x pozisyonuna çektik
End;
end;
Şimdiiiii….
Bu işlemi yaptığımızda ImageAnaKarakter nesnemiz duvarın üzerine gelir gelmez; geri eski pozisyonuna dönecektir. Belki iyi bir işlemcide bu görünmeyecektir bile şip şak ekran geçişi sağlanacaktır fakat çok çirkin ve amatör bir görüntü ortaya çıkabilir. Bunu gidermek ve bir adım ileriye gitmemiz için tabi ki kod değil mantık vereceğim (KötüAdamGülüşü.png);
Dinamik olarak bir image objesi oluşturup ImageAnaKarakter’in değerlerini ona aktarıyoruz. Sonra dinamik image objesine +x düzleminde 10 koordinat ekliyoruz. Ve çarpışma kontrolünü yapan fonksiyonumuza dinamik image objemizin adını vererek kontrol ettiriyoruz. Örneğin;
If not CheckImageCollision(ImageDinamikGoruntu,ImageDuvar) Then
Daha sonra bu if şart döngümüze ImageAnaKarakter.Position.X := ImageAnaKarakter.Position.X + 10; şeklinde ekleme yapıyoruz.
Peki bunu yaptık ne oldu? Bunun sonucunda karakter görüntümüz duvarın üzerine çıkmadan sanki +10 değer sağ taraftaymış gibi çarpışmayı kontrol etti ve, eğer çarpışma varsa olduğu yerde kaldı, eğer yoksa da 10 birim sağa gitti.
Her şey çok güzel; Peki bir sonra ki adam?
Eğer ImageAnaKarakter, ImageDuvar objesine 7 birim uzaklıktaysa ne olacak? Görüntü 7 birim geriden donup kalacak yani ilerleyemeyecek. İşte bunun için arada ki mesafe farkını hesaplayıp ImageAnaKarakter objemizi o kadar ilerletmemiz lazım. Peki bunun mantığını verecek miyim? Tabi ki HAYIR 😀
Çünkü ben de daha üzerinde durmadım şimdi yazarken aklıma geldi. Saat geç olduğu için ileri ki yazılarımızın birinde ara not olarak geçerim. Yazım hataları için özür dilerim normalde baştan sona okur düzeltirdim fakat saat geç oldu.
Allah’a emanet olsun mucx