Bölge, oyuncunun eşyaları alabileceği veya teslim edebileceği bir harita alanıdır (bir cihaz ile gösterilir). Time Trial: Pizza Pursuit eğitimindeki bu adımı tamamlayarak bu alma ve teslim bölgelerini nasıl oluşturacağını ve oyuncu için nasıl etkinleştireceğini/devre dışı bırakacağını öğreneceksin.
Bir Bölge Sınıfı Oluşturmak İçin Soyutlama Kullanma
Soyutlama, kullanıcının ilk bakışta görünür olmayan karmaşık konuları anlamasının gerekmediği durumlarda gereksiz ayrıntıların kullanıcıdan gizlendiği bir programlama ilkesidir. Soyutlama, bir şeyin işleyişini öğretmeden o şeyin ne olduğunu açıklar. Örneğin, bir otomata para koyabilir ve teknik ayrıntıların nasıl işlediğini anlamadan güzel bir yiyecek alabilirsin.
Time Trial: Pizza Pursuit’te iki tür bölge vardır: Eşya Çıkma Yeri cihazını kullanan alma bölgeleri ve Ele Geçirme Alanı cihazını kullanan teslim bölgeleri. Bu bölgeler farklı cihazlar olmasına rağmen aynı şekilde davranacağından (yani her ikisi de etkinleştirilebilir ve devre dışı bırakılabilir) bu davranışı belirli cihaz etkileşimlerini işleyen bir genel bölge objesine çıkarmak için bir sınıf oluşturabilirsin.
Bu davranışın bir sınıfa soyutlanması, kullandığın cihaz türünü tek bir yerden değiştirebileceğin anlamına gelir. Bu sınıfı kullanan herhangi bir kod yalnızca etkinleştirme/devre dışı bırakma işlevlerini bileceği için bu uygulama aynı zamanda diğer kodlarının hiçbirini değiştirmeden spesifik özellikleri değiştirebileceğin anlamına gelir.
Bu bölge sınıfını oluşturmak için şu adımları izle:
pickup_delivery_zone.verse adlı yeni bir boş Verse dosyası oluştur ve Visual Studio Code ile aç.
Verse dosyasında,
publicbelirleyicisi ilebase_zoneadlı yeni bir sınıf oluştur ve şunları ekle:Bölgede kullanılan cihazı depolamak için
publicbelirleyicisi ileActivatorDeviceolarak adlandırılmış bircreative_object_interfacesabiti.Oyuncu eşya alma veya teslim etme gibi eylemlerle bu bölgeyle etkileşime geçtiğinde sinyal vermek için
publicbelirleyicisine sahipZoneCompletedEventadlı bir olay.Bölge için kullanılan cihazı etkinleştirmek için
voiddönüş türüne vepublicbelirleyicisine sahipActivateZone()adlı bir fonksiyon.Bölge için kullanılan cihazı devre dışı bırakmak için
voiddönüş türüne vepublicbelirleyicisine sahipDeactivateZone()adlı bir fonksiyon.Versebase_zone<public> := class: ActivatorDevice<public> : creative_object_interface ZoneCompletedEvent<public> : event(base_zone) = event(base_zone){} ActivateZone<public>() : void = Print("Zone activated") DeactivateZone<public>() : void = Print("Zone deactivated")Bir sınıf ve üyeleri
publicbelirleyicisine sahip olduğunda bu sınıfa ve üyelerine diğer kodlardan evrensel olarak erişilebilir. Daha fazla ayrıntı için Belirleyiciler ve Öznitelikler bölümüne bakabilirsin.
ActivateZone()fonksiyonundaActivatorDevicecihazını farklı türlere dönüştürerekActivatorDevicecihazının bir Ele Geçirme Alanı cihazı mı yoksa Eşya Oluşturma Yeri cihazı mı olduğunu kontrol et ve dönüştürülen cihazdaEnable()fonksiyonunu çağır. Aynı işlemiDeactivateZone()fonksiyonu için de yap ancakDisable()fonksiyonunu çağır.Versebase_zone<public> := class: ActivatorDevice<public> : creative_object_interface ActivateZone<public>() : void = Print("Zone activated") if (CaptureArea := capture_area_device[ActivatorDevice]): CaptureArea.Enable() else if (ItemSpawner := item_spawner_device[ActivatorDevice]): ItemSpawner.Enable()privatebelirleyicisine vesuspendsbelirleyicisine sahipWaitForZoneCompleted()adlı bir fonksiyon oluştur. Bu fonksiyon, cihaza özgü olay gerçekleştiğindeZoneCompletedEventsinyalini verir. Bu ayar sonucunda diğer kodunZoneCompletedEventsinyalini beklemesi ve altta yatan cihazın kullandığı olayın türünü göz ardı etmesi gerekir.VerseWaitForZoneCompleted<private>(ZoneDeviceCompletionEventOpt : ?awaitable(agent))<suspends> : void = if (DeviceEvent := ZoneDeviceCompletionEventOpt?): DeviceEvent.Await() ZoneCompletedEvent.Signal(Self)Bu fonksiyonun
DeviceEvent.Await()çağrısı yapabilmek içinsuspendsefektine sahip olması gerekir.ActivateZone()fonksiyonunu, cihazla etkileşimde bulunan oyuncu için uygun cihaz olayını kullanarakWaitForZoneCompleted()çağrısı yapan birspawnifadesiyle güncelle: Ele geçirme alanı cihazı içinAgentEntersEventve eşya çıkma yeri cihazı içinItemPickedUpEvent.WaitForZoneCompleted,awaitable(agent)türünde biroption(?ile gösterilir) parametresi bekler. Böyleceawaitablearayüzünü uygulayan herhangi bir türü, bu türünagentdeğerine eşit parametrik türüyle geçirebiliriz. HemCaptureArea.AgentEntersEventhem deItemSpawner.ItemPickedUpEventbu koşulla uyumlu olduğu için bunları parametre olarak kullanabiliriz. Bu da soyutlamanın bir diğer örneğidir.VerseActivateZone<public>() : void = Print("Zone activated") if (CaptureArea := capture_area_device[ActivatorDevice]): CaptureArea.Enable() spawn { WaitForZoneCompleted(option{CaptureArea.AgentEntersEvent})} else if (ItemSpawner := item_spawner_device[ActivatorDevice]): ItemSpawner.Enable() spawn { WaitForZoneCompleted(option{ItemSpawner.ItemPickedUpEvent}) }protectedbelirleyicisine sahipZoneDeactivatedEventadlı başka bir olay ekle. Bu olay, oyuncu tamamlamadan bölge devre dışı bırakılırsaWaitForZoneCompleted()fonksiyonunu sonlandırmak için gereklidir. Bu olayıDeactivateZone()fonksiyonunda bildir.VerseZoneDeactivatedEvent<protected> : event() = event(){} DeactivateZone<public>() : void = Print("Zone deactivated") if (CaptureArea := capture_area_device[ActivatorDevice]): CaptureArea.Disable() else if (ItemSpawner := item_spawner_device[ActivatorDevice]): ItemSpawner.Disable() ZoneDeactivatedEvent.Signal()WaitForZoneCompleted()fonksiyonunu, oyuncunun bölgeyi tamamlamasını veya bölgenin devre dışı bırakılmasını bekleyecek şekilde birraceifadesiyle güncelle.raceifadesiyleZoneDeactivatedEvent.Await()asenkron fonksiyon çağrısı, cihaz olayı veZoneCompletedEventsinyali ile deblockifadesi aynı anda çalışır ancak ilk önce tamamlanmayan ifade iptal edilir.VerseWaitForZoneCompleted<private>(ZoneDeviceCompletionEventOpt : ?awaitable(agent))<suspends> : void = if (DeviceEvent := ZoneDeviceCompletionEventOpt?): race: block: DeviceEvent.Await() ZoneCompletedEvent.Signal(Self) ZoneDeactivatedEvent.Await()Son olarak,
base_zonesınıfı içinActivatorDevicealanını başlatacak olan bir oluşturucu yap.VerseMakeBaseZone<constructor><public>(InActivatorDevice : creative_object_interface) := base_zone: ActivatorDevice := InActivatorDevicebase_zonesınıfı için tam kod aşağıdaki gibidir.Verse# A zone is an area of the map (represented by a device) that can be Activated/Deactivated and that provides events to signal when the zone has been "Completed" (can't be completed anymore until next activation). # Zone "Completed" depends on the device type (ActivatorDevice) for the zone. # Suggested usage: ActivateZone() -> ZoneCompletedEvent.Await() -> DeactivateZone() # base_zone<public> := class: ActivatorDevice<public> : creative_object_interface ZoneCompletedEvent<public> : event(base_zone) = event(base_zone){} GetTransform<public>() : transform = ActivatorDevice.GetTransform()
Oynanış Etiketleriyle Çalışma Zamanında Bölge Bulma
Artık bölgeleri oluşturmanın ve etkinleştirmenin/devre dışı bırakmanın yolunu öğrendiğine göre bölümde etiketlediğin tüm bölgeleri başlatma ve etkinleştirilecek bir sonraki bölgeyi seçmenin bir yolunu ekleyelim.
Bu örnek, bu işlemin bölge oluşturmaktan ve etkinleştirilecek bir sonraki bölgeyi seçmekten sorumlu bir sınıfla nasıl yapılacağını gösteriyor.
Bölge oluşturmak ve seçmek üzere sınıf oluşturmak için şu adımları izle:
pickup_delivery_zone.verse dosyasında
tagged_zone_selectoradlı yeni bir sınıf oluştur. Tüm bölgeleri bölümde depolamak için bir değişken dizisi ekle.tagged_zone_selector<public> := class: var Zones<protected> : []base_zone = array{}Söz konusu Oynanış Etiketiyle ilişkili tüm bölgeleri bulmak ve önbelleğe almak için
publicbelirleyicisine ve birtagparametresine sahipInitZones()adlı bir metot ekle.VerseInitZones<public>(ZoneTag : tag) : void = # On creation of a zone selector, find all available zones and cache them so we don't consume time searching for tagged devices every time the next zone is selected. ZoneDevices := GetCreativeObjectsWithTag(ZoneTag) set Zones = for (ZoneDevice : ZoneDevices): MakeBaseZone(ZoneDevice)Yöntemin başka bir bölge bulması veya başarısız olması için
decidesvetransactsbelirleyicisine sahipSelectNext()adlı bir metot ekle. Dizin içinGetRandomInt(0, Zones.Length - 1)kullanarak dizideki rastgele bir dizinde bulunan bölgeyi seç.VerseSelectNext<public>()<transacts><decides> : base_zone = Zones[GetRandomInt(0, Zones.Length - 1)]pickup_delivery_zone.verse dosyasının tam kodu şu anda böyle görünmelidir:
Verseusing { /Verse.org/Simulation } using { /Verse.org/Random } using { /Verse.org/Concurrency } using { /Verse.org/Simulation/Tags } using { /UnrealEngine.com/Temporary/SpatialMath } using { /Fortnite.com/Devices } <# A zone is an area of the map (represented by a device) that can be Activated/Deactivated and that provides events to signal when the zone has been "Completed" (can't be completed anymore until next activation). Zone "Completed" depends on the device type (ActivatorDevice) for the zone.
Alma ve Teslim Bölgelerini Test Etme
Artık iki sınıf oluşturduğuna göre bölge seçiminin beklediğin gibi çalıştığından emin olmak için kodunu test etmende yarar var.
game_coordinator_device.verse dosyanı güncellemek için şu adımları izle:
game_coordinator_devicecihazına teslim bölgesi seçici için bir sabit, alma bölgesi seçicileri için de bir değişken dizi ekle. Oyun her pizza alımından sonra alma seviyesini yükselteceğinden oyunda istediğin her alma seviyesi için birtagged_zone_selectorve dolayısıylaPickupZoneSelectorsdizisi gerekecektir. Her bölge seçici, belirli bir seviyenin tüm alma bölgelerini tutar. Bunun bir değişken olması gerekir çünkü ayarı,PickupZoneLevelTagsiçindekipickup_zone_tagetiketlerinin sayısına göre belirlenir.Kodda minimum değişiklik yaparak alma seviyelerinin sayısını artırmak için bu ayarı kullan: Tek yapman gereken
PickupZoneLevelTagsfonksiyonunupickup_zone_tagetiketinden türetilen etiketlerle güncellemek, ardından editörde cihazları etiketlemek.Versegame_coordinator_device<public> := class<concrete>(creative_device): DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{}SetupZones()adlı bir metot oluştur veOnBegin()fonksiyonunda metodu çağır:Metodu
privatebelirleyicisine vevoiddönüş türüne sahip olacak şekilde ayarla.Teslim bölgesi seçiciyi
delivery_zone_tagile başlat.Alma bölgesi seviye etiketlerini oluştur ve alma bölgesi seçicileri başlat.
VerseOnBegin<override>()<suspends> : void = SetupZones() SetupZones<private>() : void = DeliveryZoneSelector.InitZones(delivery_zone_tag{}) PickupZoneLevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for(PickupZoneTag : PickupZoneLevelTags): PickupZone := tagged_zone_selector{}
OnBegin()içinde bir sonraki alma bölgesini seçen, etkinleştiren, oyuncunun bölgeyi tamamlamasını bekleyen ve sonra bölgeyi devre dışı bırakan bir döngü oluştur.VerseOnBegin<override>()<suspends> : void = SetupZones() var PickupLevel : int = 0 loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() PickupZone.ZoneCompletedEvent.Await() PickupZone.DeactivateZone()Verse dosyalarını kaydet, kodunu derle ve bölümüne oynanış testi uygula.
Bölümüne oynanış testi uyguladığında oyunun başlangıcında Eşya Oluşturma Yeri cihazlarından biri etkinleşir. Eşya aldıktan sonra Eşya Oluşturma Yeri cihazı devre dışı kalır ve sonra bir Ele Geçirme Alanı cihazı etkinleşir. Bu döngü sen oyunu manuel olarak sonlandırana kadar devam eder.