Time Trial: Pizza Pursuit eğitimindeki bu adımı tamamlayarak, bir oyuncu eşyaları aldığında ve teslim ettiğinde puanı nasıl yöneteceğini ve kullanıcı arayüzünü puanları gösterecek şekilde güncellemeyi öğreneceksin. Verse’te oyun içi kullanıcı arayüzü oluşturma hakkında daha fazla bilgi edinmek için oyun içi kullanıcı arayüzü oluşturma bölümüne bakabilirsin.
Puan yöneticisi şunları takip edecek ve gösterecektir:
- Toplam Puan: Oyuncunun oyun içinde aldığı toplam puanı ifade eder.
- Bekleyen Puanlar: Oyuncunun mevcut alma kümesi için biriktirdiği puanları ifade eder.
- Alma Seviyesi: Mevcut alma seviyesini ifade eder.

Kullanıcı Arayüzü Oluşturma
Verse’te puan yöneticisi kullanıcı arayüzünü oluşturmak için şu adımları izle:
- Yeni bir boş Verse dosyası oluştur ve score_manager.verse olarak adlandır.
score_manager
adlı yeni bir sınıf oluştur ve aşağıdaki alanları sınıfa ekle:- Oyuncuya bir referans kaydetmek için
MaybePlayer
adlı isteğe bağlı biragent
.MaybePlayer<internal> : ?agent = false
- Oyuncunun kullanıcı arayüzüne bir referans kaydetmek için
MaybePlayerUI
adlı isteğe bağlı birplayer_ui
.MaybePlayerUI<internal> : ?player_ui = false
- Bu sınıfın üzerine kurulu olduğu Puan Yöneticisi için bir referans kaydetmeye yarayan bir
score_manager_device
. (Verse ile oluşturulangame_coordinator_device
cihazına bağlı olması gerektiğinden bunun düzenlenebilir bir referans olmadığını unutma.)ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}
- Oyuncunun oyunda genel olarak kazandığı tüm puanları temsil eden
TotalGameScore
adlı bir tamsayı değişkeni.var TotalGameScore<private> : int = 0
- Oyuncunun bu alma kümesi için şu anda biriktirmiş olduğu puanları temsil eden
PendingScore
adlı bir tamsayı değişkeni.var PendingScore<private> : int = 0
- Mevcut alma seviyesini temsil eden
PickupLevel
adlı bir tamsayı değişkeni.var PickupLevel<private> : int = 0
- Oyuncuya bir referans kaydetmek için
- score_manager class tanımın şu anda böyle görünmelidir:
score_manager := class: MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0
- Sınıf ilk oluşturulduğunda kullanıcı arayüzünü oluştur. Sınıf tanımına, sınıfın bir örneğini her oluşturduğunda yürütülecek bir
block
ifadesi ekleyerek bunu yapabilirsin. Kullanıcı arayüzü oluşturmak için aşağıdaki değişkenleri ekle:- Özel tuval widget’ını depolamak için
internal
belirleyicisine sahipCanvas
adlı bircanvas
değişkeni.var Canvas<internal> : canvas = canvas{}
- Oyuncunun oyun genelinde aldığı ve
TotalGameScore
değişkeniyle ifade edilen tüm puanları görüntülemek amacıyla metin widget’ını kaydetmek içininternal
belirleyicisine sahipTotalGameScoreWidget
adlı birtext_block
. Metin bloğunun varsayılan metin rengini beyaz olarak ayarla.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}
- Oyuncunun bu alma kümesi için biriktirdiği ve
PendingScore
değişkeniyle ifade edilen puanları görüntülemek amacıyla metin widget’ını kaydetmek içininternal
belirleyicisine sahipPendingScoreWidget
adlı birtext_block
. Metin bloğunun varsayılan metin rengini beyaz olarak ayarla.PendingScoreWidget<internal> : text_block = text_block{}
PickupLevel
değişkeniyle ifade edilen mevcut alma seviyesini görüntülemek amacıyla metin widget’ını kaydetmek içininternal
belirleyicisine sahipPickupLevelWidget
adlı birtext_block
. Metin bloğunun varsayılan metin rengini beyaz olarak ayarla.PickupLevelWidget<internal> : text_block = text_block{}
- Oyuncunun oyunda aldığı toplam puanlar için kullanıcı arayüzünde görüntülenebilecek yerelleştirilebilir metinler oluşturan
TotalGameScoreText
adlı birmessage
döndüren işlev.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Toplam Puan: {CurrentTotalGameScore}"
- Oyuncunun bu alma kümesi için biriktirmiş olduğu puanlarla ilgili olarak kullanıcı arayüzünde görüntülenebilecek yerelleştirilebilir metinler oluşturan
PendingScoreText
adlı birmessage
döndüren işlev.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Bekleyen Puanlar: {CurrentPendingScore}"
- Mevcut alma seviyesi için kullanıcı arayüzünde görüntülenebilecek yerelleştirilebilir metinler oluşturan
PickupLevelText
adlı birmessage
döndüren işlev.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Alma Seviyesi: {CurrentPickupLevel}"
- Tuval widget’ını oluşturan ve metni ekranın solunda dikey yönde yığılmış halde konumlandıran bir
block
ifadesi ekle.<# Puan yöneticisi yaşam süresi boyunca tuvali oluşturmayacağımız için bu işlemi bu türden bir obje oluşturulduğunda bir kez yapmalısın. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget
- Özel tuval widget’ını depolamak için
score_manager
kodun şu anda böyle görünmelidir:using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/UI } using { /Verse.org/Colors } score_manager := class: var Canvas<internal> : canvas = canvas{} TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PendingScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} PickupLevelText<private><localizes>(InLevel : int) : message = "Alma Seviyesi: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Bekleyen Puanlar: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : tamsayı) : mesaj = "Total Points: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# Puan yöneticisi yaşam süresi boyunca tuvali oluşturmayacağımız için bu işlemi bu türden bir obje oluşturulduğunda bir kez yapmalısın. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget
- Kullanıcı arayüzündeki metni en son puan değerleri ve mevcut alma seviyesi ile güncelleyen
private
belirleyicisine sahipUpdateUI()
adlı bir fonksiyon oluştur.UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))
- Oyuncunun kullanıcı arayüzünü özel puan yöneticisi kullanıcı arayüzü ile güncelleyen
AddScoreManagerToUI()
adlı bir fonksiyon oluştur.AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()
- Oyun döngüsünün değerleri güncelleyebilmesi amacıyla kullanıcı arayüzünde gösterilen her bir değer için bir fonksiyon oluştur:
public
belirleyicisine sahipAddPendingScoreToTotalScore()
adlı bir işlev. Bu işlev beklemedeki puanı toplam oyun puanına eklemeli ve beklemedeki puan değerini0
olarak ayarlamalıdır.defer
ifadesiylePendingScore
değerini sıfırlamayı ve kullanıcı arayüzünü güncellemeyiTotalGameScore
değişkeninin güncellenmesi sonrasına geciktirebilirsin. Bunu yapmakPendingScore
sıfırlanmadan önce değerini tutmak için geçici bir değişken kullanmak zorunda kalmamanı sağlar.<# PendingScore değerini TotalGameScore değerine ekler ve PendingScore değerini 0 yapar.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScore
public
belirleyicisine sahipUpdatePendingScore()
adlı bir işlev ve işlevin mevcut beklemedeki puana ekleyeceğiPoints
adlı bir tamsayı parametresi.<# Belirtilen miktarda puanı beklemedeki puanlara ekler. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()
public
belirleyicisine sahipUpdatePickupLevel
adlı bir işlev ve mevcut alma seviyesi için yeni değeri ifade edenLevel
adlı bir tamsayı parametresi.UpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()
public
belirleyicisine sahipAwardScore()
adlı bir işlev oluştur. Bu işlev, Puan Yöneticisi cihazını kullanarak puanı oyuncuya verir ve cihazı etkinleştirir.<# Puan Yöneticisi cihazını etkinleştirerek puanı oyuncuya verir. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer)
score_manager
sınıfın şu anda böyle görünmelidir:score_manager := class: <# Puan yöneticisi yaşam süresi boyunca tuvali oluşturmayacağımız için bu işlemi bu türden bir obje oluşturulduğunda bir kez yapmalısın. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI() <# PendingPickupPoints değerini TotalPickupPoints değerine ekler ve PendingPickupPoints değerini 0 yapar. Eklenen toplam Alma Puanı sayısını döndürür. #> AddPendingScoreToTotalScore<public>() : void = set TotalGameScore += PendingScore defer: set PendingScore = 0 UpdateUI() <# Belirtilen miktarda puanı beklemedeki puanlara ekler. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI() UpdatePickupLevel<public>(Level : int) : void= set PickupLevel = Level UpdateUI() <# Puan Yöneticisi cihazını etkinleştirerek puanı oyuncuya verir. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer) MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} var Canvas<internal> : canvas = canvas{} TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PendingScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelText<private><localizes>(InLevel : int) : message = "Alma Seviyesi: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Bekleyen Puanlar: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : tamsayı) : mesaj = "Total Points: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))
score_manager
sınıfını ekledikten sonra oyundan oyuncu değişkenlerini başlatmak için sınıfa ait bir oluşturucu yarat. Oyuncunun kullanıcı arayüzüne bir referans elde etmek için oyuncu referansı türünüagent
değerindenplayer
değerine dönüştürmen gerektiğini unutma.MakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
- score_manager.verse dosyası şimdi şöyle görünmelidir:
using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/Devices } using { /Fortnite.com/UI } using { /Verse.org/Colors } using { /Verse.org/Simulation } MakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]} score_manager := class: <# Puan yöneticisi yaşam süresi boyunca tuvali oluşturmayacağımız için bu işlemi bu türden bir obje oluşturulduğunda bir kez yapmalısın. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI() <# PendingPickupPoints değerini TotalPickupPoints değerine ekler ve PendingPickupPoints değerini 0 yapar. Eklenen toplam Alma Puanı sayısını döndürür. #> AddPendingScoreToTotalScore<public>() : int = set TotalGameScore += PendingScore defer: set PendingScore = 0 UpdateUI() return PendingScore <# Belirtilen miktarda puanı beklemedeki puanlara ekler. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI() UpdatePickupLevel<public>(Level : int) : void= set PickupLevel = Level UpdateUI() <# Puan Yöneticisi cihazını etkinleştirerek puanı oyuncuya verir. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer) MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} var Canvas<internal> : canvas = canvas{} TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PendingScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelText<localizes><internal>(CurrentPickupLevel : int) : message = "Alma Seviyesi: {CurrentPickupLevel}" PendingScoreText<localizes><internal>(CurrentPendingScore : int) : message = "Bekleyen Puanlar: {CurrentPendingScore}" TotalGameScoreText<localizes><internal>(CurrentTotalGameScore : int) : message = "Toplam Puan: {CurrentTotalGameScore}" var TotalGameScore<private> : int = 0 var PendingScore<private>:int = 0 var PickupLevel<private>:int = 0 UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))
Oyun Döngüsünde Puanı ve Kullanıcı Arayüzünü Güncelleme
game_coordinator_device.verse dosyasında oyun sırasındaki kullanıcı arayüzünü oluşturmak ve güncellemek için aşağıdaki adımları izle:
- Aşağıdaki özellikleri
game_coordinator_device
sınıfına ekle:private
belirleyicisine sahipScoreManager
adlı birscore_manager
değişkeni. Bu örnek, oyuncunun puanını ve Kullanıcı Arayüzünü yönetir.var ScoreManager<private> : score_manager = score_manager{}
- Bölümde Puan Yöneticisi cihazına ayarlayabileceğin, düzenlenebilir bir
score_manager_device
.score_manager
sınıfı bu cihazı kullanacaktır.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}
- Oyuncunun her bir alma seviyesinde kazanabileceği puanları belirlemek için
public
belirleyicisine sahipPointsForPickupLevel
adlı düzenlenebilir bir tamsayı dizisi.@editable # Bir alma işleminin alma seviyesine göre kaç puan değerinde olduğunu belirler. PointsForPickupLevel<public> : []int = array{1, 2, 3}
-
StartGame
işlevinde oyuncuya ve Puan Yöneticisi cihazına bir referanslaMakeScoreManager()
oluşturucusunu çağırarak puan yöneticisi değişkenini başlat ve oyuncunun görmesi için kullanıcı arayüzünü oluştur.StartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") <# Başlatıldığında InitialCountdownTime değerinden geri sayacak yeni bir countdown_timer oluşturuyoruz. Ayrıca oyuncunun puanını ve alma seviyesini takip edecek yeni bir score_manager oluştur. countdown_timer ve score_manager arayüzün gösterileceği bir oyuncu bulunmasını gerektirir. Şu ana kadar araca giren, oyun başlangıcını tetikleyen geçerli bir oyuncuya sahip olmalıyız. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...") set ScoreManager = MakeScoreManager(ValidPlayer, ScoreManagerDevice) ScoreManager.AddScoreManagerToUI() set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Geri sayımın sona ermesini bekleriz. # Aynı zamanda, temel oynanışı oluşturan Alma ve Teslim oyun döngüsünü çalıştırırız. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Can't find valid player. Aborting game start", ?Level := log_level.Error)
- Oyun döngüsünün
PickupDeliveryLoop()
işlevinde alma seviyesi her değiştiğinde ve oyuncu bir alma veya teslimi tamamladığında kullanıcı arayüzünü güncelle:PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true <# Döngü her başladığında ScoreManager aracılığıyla alma seviyesi kullanıcı arayüzünü sıfırlamalıyız. Kullanıcı Arayüzündeki alma seviyesi 1’den başlar (0’dan değil). 0’dan başlarsa bazı oyuncuların aklı karışabilir. Dizini oluşturmaya 0’dan başlarız. Bu yüzden PickupLevel=0, Kullanıcı Arayüzündeki 1. Seviyedir. #> ScoreManager.UpdatePickupLevel(PickupLevel + 1) race: loop: if (PickupZone:base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() <# Etkinleştirdiğimiz PickupZone için gereken tek geciktirme (defer) budur. Her dış döngünün sonunda ilk PickupZone bölgesini devre dışı bırakacak veya sonraki herhangi bir PickupZone’u devre dışı bırakacaktır. Bunun nedeni, ifadenin en sonda PickupZone değişkeni daha yeni bir bölgeye bağlandığında değerlendirilmesidir. #> defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() Logger.Print("Picked up", ?Level:=log_level.Normal) # İlk alımdan sonra teslim bölgesini etkinleştirebiliriz. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() if (PickupPoints := PointsForPickupLevel[PickupLevel]): ScoreManager.UpdatePendingScore(PickupPoints) # Alma seviyesini ve ScoreManager değerini güncelle. if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 ScoreManager.UpdatePickupLevel(PickupLevel + 1) else: Logger.Print("Seçilecek bir sonraki PickupZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level := log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level := log_level.Normal) ScoreManager.AddPendingScoreToTotalScore() else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
- Şimdi geri sayım bittiğinde oyuncuya puanını ver.
HandleCountdownEnd()
içindeScoreManager.AwardScore()
fonksiyonunu çağır.HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)
- game_coordinator_device.verse dosyan şu anda böyle görünmelidir:
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /EpicGames.com/Temporary/Curves } using { /Verse.org/Simulation/Tags } # Oyun bölgeleri etiketleri pickup_zone_tag<public> := class(tag): pickup_zone_level_1_tag<public> := class(pickup_zone_tag): pickup_zone_level_2_tag<public> := class(pickup_zone_tag): pickup_zone_level_3_tag<public> := class(pickup_zone_tag): delivery_zone_tag<public> := class(tag): log_pizza_pursuit<internal> := class(log_channel){} game_coordinator_device<public> := class(creative_device): # Geri sayım süreölçerinin ne kadar süre geri saymaya başlayacağı. @editable InitialCountdownTime<public> : float = 30.0 @editable EndGame<public> : end_game_device = end_game_device{} @editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{} @editable # Bir alma işleminin alma seviyesine göre kaç puan değerinde olduğunu belirler. PointsForPickupLevel<public> : []int = array{1, 2, 3} OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() StartGame() Logger<private> : log = log{Channel := log_pizza_pursuit} var MaybePlayer<private> : ?agent = false var CountdownTimer<private> : countdown_timer = countdown_timer{} var ScoreManager<private> : score_manager = score_manager{} DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{} FindPlayer<private>() : void = # Bu bir tek oyunculu deneyim olduğundan ilk oyuncu (0) # tek kullanılabilir oyuncu olmalıdır. Playspace := Self.GetPlayspace() if (FirstPlayer := Playspace.GetPlayers()[0]): set MaybePlayer = option{FirstPlayer} Logger.Print("Player found") else: # Bir oyuncu bulamazsak günlüğe bir hata kaydet. # Her zaman en az bir oyuncu mevcut olduğundan böyle bir durum yaşanmamalıdır. Logger.Print("Geçerli oyuncu bulunamıyor", ?Level := log_level.Error) SetupZones<private>() : void = # Zorluk seviyesine göre ölçeklendirilmediği için yalnızca bir tür teslim bölgesi vardır. DeliveryZoneSelector.InitZones(delivery_zone_tag{}) # Bölgeleri (cihazlarla temsil edilir) zorluk seviyesine göre seçmek için oynanış etiketlerini kullanırız. # Dizi kullanmak, zorluk seviyelerini değiştirmeyi kolaylaştırır: Koda dokunmadan # daha fazla bölüm ekleyebilir, ayrıntı seviyesini artırabilir/azaltabilir veya sırasını değiştirebiliriz. # Aynı etikete (aynı zorluk seviyesine) sahip tüm cihazların aynı seçim havuzunda olması için her bir zorluk seviyesi etiketi için # bir one tagged_zone_selector oluştur. LevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for (ZoneTag : LevelTags): NewZone := tagged_zone_selector{} NewZone.InitZones(ZoneTag) NewZone StartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") <# Başlatıldığında InitialCountdownTime değerinden geri sayacak yeni bir countdown_timer oluşturuyoruz. Ayrıca oyuncunun puanını ve alma seviyesini takip edecek yeni bir score_manager oluştur. countdown_timer ve score_manager arayüzün gösterileceği bir oyuncu bulunmasını gerektirir. Şu ana kadar araca giren, oyun başlangıcını tetikleyen geçerli bir oyuncuya sahip olmalıyız. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...") set ScoreManager = MakeScoreManager(ValidPlayer, ScoreManagerDevice) ScoreManager.AddScoreManagerToUI() set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Geri sayımın sona ermesini bekleriz. # Aynı zamanda, temel oynanışı oluşturan Alma ve Teslim oyun döngüsünü çalıştırırız. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Can't find valid player. Aborting game start", ?Level := log_level.Error) HandleCountdownEnd<private>(InPlayer : agent)<suspends> : void = CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer) PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true <# Döngü her başladığında ScoreManager aracılığıyla alma seviyesi kullanıcı arayüzünü sıfırlamalıyız. Kullanıcı Arayüzündeki alma seviyesi 1’den başlar (0’dan değil). 0’dan başlarsa bazı oyuncuların aklı karışabilir. Dizini oluşturmaya 0’dan başlarız. Bu yüzden PickupLevel=0, Kullanıcı Arayüzündeki 1. Seviyedir. #> ScoreManager.UpdatePickupLevel(PickupLevel + 1) race: loop: if (PickupZone:base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() <# Etkinleştirdiğimiz PickupZone için gereken tek geciktirme (defer) budur. Her dış döngünün sonunda ilk PickupZone bölgesini devre dışı bırakacak veya sonraki herhangi bir PickupZone’u devre dışı bırakacaktır. Bunun nedeni, ifadenin en sonda PickupZone değişkeni daha yeni bir bölgeye bağlandığında değerlendirilmesidir. #> defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() Logger.Print("Picked up", ?Level := log_level.Normal) # İlk alımdan sonra teslim bölgesini etkinleştirebiliriz. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() if (PickupPoints := PointsForPickupLevel[PickupLevel]): ScoreManager.UpdatePendingScore(PickupPoints) # Alma seviyesini ve ScoreManager değerini güncelle. if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 ScoreManager.UpdatePickupLevel(PickupLevel + 1) else: Logger.Print("Seçilecek bir sonraki PickupZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level := log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level := log_level.Normal) ScoreManager.AddPendingScoreToTotalScore() else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata