Oyun tahtasının arkasındaki mantığı oluşturmanın ilk adımı, bir oyun tahtası karesinin programlanabilir bir şekilde nasıl temsil edileceğine karar vermektir.
Bir tahta karesini tasarlamak için senin ve oyuncunun tahta karelerini nasıl kullandığını düşün. Bir kutu oyunu genellikle ayrık alanlardan oluşur. Bu, UEFN dünya alanından farklıdır.
Dünya alanında koordinatlar, vector3 konumlarıyla temsil edilir. Bunun anlamı, koordinatların birbirine kayan noktalı sayıların olabileceği kadar yakın olabileceğidir. Bu da dünya koordinatlarını ayrık olmaktan çok sürekli hale getirir. Ayrıca, hepsi aynı tahta karesinde olacak birçok farklı vector3 konumu vardır. Bundan birkaç sonuç çıkarabilirsin:
Tahta kareleri ayrık olduğundan konumlarımızı temsil etmek için ayrık bir veri (ayrık veri, tamsayı değerlerine karşılık gelen bir dizi değer alan veridir), bir başka deyişle
floatyerineinttürünü kullanmayı tercih edebilirsin.Tahta iki boyutludur, bu nedenle bir konumu yalnızca iki boyut içinde depolaman gerekir. Tahta karesi konumunu depolamak için üç boyutlu bir veri yapısına ihtiyacın yoktur.
Tahta Veri Türlerini Tanımla
tile_coordinate sınıfı, bir karenin oyun tahtası üzerinde nerede yer aldığını temsil eder. tile_coordinate sınıfını oluşturmak için utilities.verse adında yeni bir Verse dosyası oluştur. Bu dosyanın içinde DataTypes adında yeni bir modül oluştur.
DataTypes<public> := module:
Bu modüle yeni TileCoordinate sınıfını ekle ve sınıfın bileşenlerini tanımla.
using { /Verse.org/Simulation }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
@editable
Left<public>:int = 0
@editable
Forward<public>:int = 0
Koordinat Savaşı’nda 5 x 5’lik bir tahta ızgarası oluşturuyorsun. Bu da oyun tahtasının sınırlarını tanımlaman gerektiği anlamına gelir. Bunu yapmak için bir tile_coordinate Left veya Forward değerinin ne kadar küçük veya büyük olabileceğine dair bir alt ve üst sınır tanımlayan, bounds adlı yeni bir sınıf oluştur.
using { /Verse.org/Simulation }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
@editable
Left<public>:int = 0
@editable
Forward<public>:int = 0
Tek bir oyun tahtasına dair sınırları tek bir veri yapısında tutacak bir yapıya sahip olman uygun olacaktır. Bunu yapmak için bir tile_coordinate’ın bileşenlerinin her biri için bir alt ve üst sınır tanımlayan, board_bounds adlı yeni bir sınıf oluştur.
using { /Verse.org/Simulation }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
@editable
Left<public>:int = 0
@editable
Forward<public>:int = 0
Oyun Tahtasını Tanımla
Artık aşağıdakileri yapmanı sağlayacak yapıların var:
Tahta alanında bir karenin gösterimini tanımlamak.
Tahta alanının sınırlarını tanımlamak.
Ancak büyük bir parça hâlâ kayıp: oyun tahtasının kendisi. Oyun tahtasını tanımlamak için board.verse adında yeni bir Verse dosyası oluştur ve board adında yeni bir Verse cihazı ekle.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
Tahtada birkaç şey yer almalıdır:
Tahta dünya alanında nerede bulunuyor?
Tahtanın sınırları nedir?
Bir tahta karesinin boyutu nedir?
İlk soru için yeni bir değişken gerekmez; cihazın kendisinin yerleşik dönüşümünü kullanabilirsin. Bir Kreatif cihazının transform’unu GetTransform API fonksiyonu ile alabilirsin.
İkinci soru, bir board_bounds değişkeniyle tanımlanabilir.
Üçüncü soru ise kare boyutunu takip etmeye yönelik bir vector2 değişkeni tanımlanarak çözülebilir.
Bunların son ikisi, board cihazın için alanlar olarak eklenir.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
Tahta Alanından Dünya Alanına Dönüştür
Ardından, bir karenin dünyada vector3 olarak nerede yer aldığını belirle. Bu kareye oyun tahtası üzerinde bir tile_coordinate olarak konum verilir. Bu fonksiyonu ToVector3 olarak adlandır. Bu işlem, oyun tahtasının merkezinin nerede olduğunun bilinmesi için oyun tahtasının sınırları içinde yapılmalıdır.
Fakat öncelikle çözmen gereken bir belirsizlik vardır. Bir tile_coordinate verildiğinde, aynı karede birçok farklı vector3 dünya konumu vardır. Matematik dilinde buna birden çoğa (one-to-many) fonksiyonu denir. İdeal olan, karenin dünya alanında nerede yer aldığını belirtecek tek bir dünya konumu seçmendir. Burada doğal bir seçim, karenin merkezi olacaktır.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
Bu fonksiyon aşağıdakileri gerçekleştirir:
Tahtanın dünya alanındaki dönüşümünü alır.
Dönüşümden tahtanın dünya alanındaki konumunu alır.
Tahtanın merkezine göre girdi karesinin ofsetini hesaplar.
Dünyanın merkezine göre konumu elde etmek için ofseti tahta konumunun merkezine ekler.
Dünya Alanından Tahta Alanına Dönüştür
Dünya alanında vector3 olarak bir konumun varsa bunu bir tile_coordinate’a dönüştürmen gerekecektir.
ToTileCoordinate adında bir fonksiyon oluştur. Bu fonksiyon, bağımsız değişkeni olarak bir vector3’ü alır ve bir tile_coordinate döndürür. Dünya alanındaki bir konum bir vector3 olarak verildiğinde, oyun tahtasındaki konumun tile_coordinate olarak belirlenmesi biraz daha karmaşıktır.
Bunun daha karmaşık olmasının temel nedeni, tahtanın ayrık bir ızgara olmasından dolayı dünya alanında, oyun tahtasının parçası olmayan birçok konumun olmasıdır. Dolayısıyla dünya alanındaki bir konum bir vector3 olarak verildiğinde, bu konum oyun tahtası üzerinde olmayabilir. Bu durum, ToTileCoordinate’ı <decides> fonksiyonu efekt belirleyicisine sahip olma konusunda öncelikli bir aday yapar. ToTileCoordinate’ın mükemmel bir aday olmasının nedeni, oyun dünyasında bir kare koordinatında bulunmayan çok sayıda konum olmasıdır. Bu durumda bu konumlardan birini dönüştürme girişimi başarısız olur. Bu dönüşümün ne zaman başarılı veya başarısız olduğunu bilmek önemlidir. ToTileCoordinate fonksiyonu öncelikle, bir konumun oyun tahtası üzerinde olup olmadığına karar verir. Konum oyun tahtası üzerinde ise o tile_coordinate konumunu döndürür.
Karmaşıklığın fazla olmasının bir diğer nedeni de tek bir karenin birçok farklı dünya konumundan oluşmasıdır. Matematikte bu özellik, ToTileCoordinate fonksiyonunu çoktan bire (many-to-one) fonksiyonu yapar.
Her şeyi daha temiz yapmak için ToTileCoordinate’ın başarısızlık kısmını ayrı yap, ayrı olarak IsTileCoordinateOnBoard adında bir fonksiyon tanımla ve onu ToTileCoordinate içinde çağır.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
IsTileCoordinateOnBoard fonksiyonu aşağıdakileri gerçekleştirir:
Girdi kare koordinatının sol (left) bileşeninin tahta sınırları arasında olup olmadığını belirler.
Girdi kare koordinatının ileri (forward) bileşeninin tahta sınırları arasında olup olmadığını belirler.
IsTileCoordinateOnBoard fonksiyonu, girdi kare koordinatının tahta sınırları içinde olması durumunda başarılı, aksi takdirde ise başarısız olur.
ToTileCoordinate fonksiyonu aşağıdakileri gerçekleştirir:
Tahtanın dünya alanı dönüşümünü alır.
Dünya alanından tahta konumunun merkezini alır.
Dünya konumunun göreli konumunu, tahtanın merkezine göre hesaplar.
Göreli dünya konumunu kare koordinatına dönüştürür.
Kare koordinatının tahta üzerinde olup olmadığını belirler.
Kare koordinatı tahta üzerindeyse kare koordinatını döndürür.
ToTileCoordinate fonksiyonu ancak ve ancak IsTileCoordinateOnBoard başarılı olursa başarılı olur.
Örnek
Aşağıdaki bölümde, bir tile_coordinate alıp onu bir vector3’e dönüştürme, ardından aynı vector3’ü alıp onu tekrar bir tile_coordinate’a dönüştürmeyi içeren bir örnek açıklanmaktadır.
Kare Koordinatından Vector3’e
Aşağıdakilere sahip olduğunu varsayalım:
5’e 5 kare boyutunda bir oyun tahtası.
512,0 x 512,0 birim kare boyutunda bir oyun karesi.
Oyun tahtası, dünya alanında X := 5000,0, Y:= 0,0, Z := 1000,0 konumunda yer almaktadır.
Left := -1, Forward := 2,0 kare koordinatlarına sahip kareyi dünya alanına dönüştürme adımları aşağıda verilmiştir.
ToVector3(tile_coordinate{Left := -1, Forward := 2.0})
BoardTransform:transform = GetTransform()
# BoardTransform := transform{Translation := vector3{X := 5000.0, Y := 0.0, Z := 1000.0}, ...}
CenterOfBoard:vector3 = BoardTransform.Translation
# CenterOfBoard := vector3{X := 5000.0, Y := 0.0, Z := 1000.0}
TileOffsetFromCenter:vector3 = vector3:
X := (TileLocation.Forward * TileSize.X)
Sırada ToTileCoordinate fonksiyonunu kullanarak geri dönüştürme işleminin adımları vardır.
ToTileCoordinate(vector3{X := 6024.0, Y := 512.0, Z := 1000.0}):
BoardTransform:transform = GetTransform()
# BoardTransform := transform{Translation := vector3{X := 5000.0, Y := 0.0, Z := 1000.0}, ...}
CenterOfBoard:vector3 = BoardTransform.Translation
# CenterOfBoard := vector3{X := 5000.0, Y := 0.0, Z := 1000.0}
ShiftedWorldLocation:vector3 = WorldLocation - CenterOfBoard
# ShiftedWorldLocation := vector3{X := 6024.0, Y := 512.0, Z := 1000.0} - vector3{X := 5000.0, Y := 0.0, Z := 1000.0}
Bu son tile_coordinate başlangıç değeriyle tamamen aynıdır; yani her şey beklendiği gibi çalışmıştır.
Özet
Özetlemek gerekirse, bu sayfada aşağıdaki adımlar açıklanmıştır:
Tahta alanında bir karenin gösterimini tanımlamak.
Tahta alanının sınırlarını tanımlamak.
Tahta alanının dünya alanı içinde nerede yer aldığını tanımlamak.
Tahta alanı ile dünya alanı arasında dönüştürme yapmak.
Dosyalar
using { /Verse.org/Simulation }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
Left<public>:int = 0
Forward<public>:int = 0
bounds<public> := class<concrete>:
@editable
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
tür