Yarış oyunlarında oyuncuların önceki rauntta gösterdikleri performansa göre farklı bir başlangıç konumunda olmaları yaygındır. Bu özellik, oyuncuları birinci olmasalar bile diğer oyuncuların önünde başlamak için yarışı hızla bitirmeye teşvik eder.
Bunu gerçekleştirmek için oyunun, oyuncuların o anda hangi rauntta olduğunu bilmesi ve yarışçı bitiş sırasının tüm oyun oturumlarında olmasa da tüm rauntlarda devam etmesi gerekir. Verse’te oturum zayıf harita değişkeni, verilerini her rauntta sıfırlar, bu yüzden bu raunt bilgileri bir oyuncu zayıf harita değişkeni kullanılarak her oyuncuyla birlikte depolanmalı ve oyun sona erdikten sonra sıfırlanmalıdır.
Şu anda bir projede en fazla iki oyuncu zayıf harita değişkeni olabilir. Projende zaten bir oyuncu zayıf harita değişkeni varsa her zaman kalıcı olması gereken verileri oyun bittikten veya bir oyuncu oturumdan ayrıldıktan sonra sıfırlayacağın verilerden ayırt etmek için raunt bilgilerini ikincisine kaydettirmen iyi bir fikirdir.
Ayrıca raunda özgü mantığı uygulamak ve son rauntta raunt bilgisini sıfırlamak için oyuncuların o anda hangi rauntta olduğunu bilmek de önemlidir. Şu anda geçerli raundu öğrenmeyi sağlayan bir API olmadığı için bu bilginin her oyuncu için kalıcı hale getirilebilir verilere kaydedilmesi gerekir.
Özetle, en az aşağıdaki bilgileri içeren bir oyuncu zayıf harita değişkenine ihtiyacın olacak:
Bitirme sırası
Son tamamlanan raunt
Sıradaki bölümlerde bu verileri ve raunt mantığını nasıl ayarlayacağını göreceksin. Tam kodu sayfanın sonunda bulabilirsin.
Son Tamamlanan Raundu Kaydet
Her oyuncu için kalıcı hale getirilebilir veriler ayarlamak ve son tamamlanan raundu kaydetmek üzere aşağıdaki adımları izle.
Rauntlar arasında oyuncu bilgilerini depolamak için
player_circuit_infoadlı kalıcı hale getirilebilir bir sınıf oluştur. Bu sınıfta oyuncunun son bitirme sırasınıLastRoundFinishOrderve tamamladığı son raunduLastCompletedRoundtemsil eden alanlar bulunmalıdır. Bu alanlar geçersiz değerleri temsil etmek üzere-1ile başlatılır, böylece bu alanların gerçekten faydalı bilgiler içerdiğini bilirsin.Verse# Tracks the number of and in what order a player finished the previous round. player_circuit_info<public> := class<final><persistable>: Version:int = 0 LastRoundFinishOrder:int = -1 LastCompletedRound<public>:int = -1Raunt bilgilerini oyuncularla birlikte kalıcı hale getirmek için
player_circuit_infosınıfını kullanarak bir oyuncu zayıf harita değişkeni oluştur.Verse# A persistable map that maps each player to # what order they finished the previous round. var CircuitInfo<public>:weak_map(player, player_circuit_info) = map{}Kalıcı hale getirilebilir verilerle çalışırken örnek bir uygulama olarak, kalıcı hale getirilebilir sınıfın her bir oyuncuyu kolayca güncelleyebilmesi için bir oluşturucu üret. Daha ayrıntılı bilgi için kısmi güncellemeler için oluşturucuları kullanma bölümüne bak.
Verse# Creates a new player_circuit_info from the given older player_circuit_info. MakePlayerCircuitInfo<constructor>(OldPlayerCircuitInfo:player_circuit_info)<transacts> := player_circuit_info: Version := OldPlayerCircuitInfo.Version LastRoundFinishOrder := OldPlayerCircuitInfo.LastRoundFinishOrder LastCompletedRound := OldPlayerCircuitInfo.LastCompletedRoundBu verilerin yapılarını tanımladığına göre bir oyuncunun bitirme sırasını kaydetmek ve kalıcı verilerini güncellemek için bir fonksiyon ekle. Bu fonksiyon, seni ilgilendiren tek bilgi olan bitirme sırası verilerini kısmen güncellemek üzere önceki adımda hazırlanan oluşturucuyu kullanır.
Verse# Creates a new player_circuit_info for the given player with the order they finished the round in. RecordPlayerFinishOrder<public>(Agent:agent, FinishOrder:int)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo:player_circuit_info = if: Info := CircuitInfo[Player] then: Info else: player_circuit_info{}Oyuncunun yalnızca son tamamladığı raundu güncellemek için başka bir fonksiyon oluştur.
Verse# Updates a player's player_circuit_info with their last completed round. UpdateRound<public>(Agent:agent, CompletedRound:int)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] set CircuitInfo[Player] = player_circuit_info: MakePlayerCircuitInfo<constructor>(PlayerCircuitInfo) LastCompletedRound := CompletedRoundArtık oyuncunun son tamamladığı raundu kaydedebildiğine göre, hangi oyuncuların son kaydedilmiş raundu tamamladığını kontrol ederek oyun için son tamamlanan raundu hesaplayacağın bir fonksiyon oluştur. Sürmekte olan oturuma katılmış olabilecek oyuncuları hesaba katmak için tüm oyuncuları kontrol etmelisin. Son tamamlanan raunt değişkeni, geçersiz verileri temsil etmek üzere
-1ile başlatılır. Herhangi bir oyuncunun-1’den büyük bir değeri varsa raunt tamamlanmıştır.Verse# Returns the highest last completed round among all players. GetLastCompletedRound<public>(Players:[]player, TotalRounds:int)<transacts>:int= var LastCompletedRound:int = -1 for: Player : Players Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] do: # Update LastCompletedRound if this player has the highest last completed round. else if:Raunt ve oyuncu bitirme sırasının beklendiği gibi çalıştığını test etmek için bir Verse cihazı oluştur. Ada Ayarları menüsünde Toplam Raunt Sayısı özelliğini ayarlayarak projenin birden fazla raunt için ayarlandığından emin ol.
Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= Players := GetPlayspace().GetPlayers() CurrentRound := GetLastCompletedRound(Players) + 1 Print("Current round is {CurrentRound}") for:
Oyuncu Ayrıldığında Raunt Bilgilerini Sıfırla
Bir oyuncu oyun sırasında ayrıldığında oyuncunun raunt bilgileri için kalıcı verileri sıfırlanmalıdır. Oyuncunun ne zaman ayrıldığını bilmek için oyun alanının PlayerRemovedEvent olayına bağlanabilirsin.
Bir oyuncu ayrıldığında raunt bilgilerini sıfırlamak için aşağıdaki adımları izle:
Oyuncunun raunt bilgileri için kalıcı verilerini sıfırlayan bir fonksiyon oluştur. Bunun anlamı, geçersiz değerleri temsil etmesi için değerleri
-1veya istediğin başka bir değere ayarlamaktır. Bu uygulama, burada sıfırlanmaması gereken diğer bilgileri daha sonra kalıcı sınıfa eklemen durumunda hangi verilerin sıfırlanması gerektiğine karar verir.Verse# Resets a player's player_circuit_info. ResetCircuitInfo<public>(Agent:agent)<decides><transacts>:void= Player := player[Agent] Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] set CircuitInfo[Player] = player_circuit_info: MakePlayerCircuitInfo<constructor>(PlayerCircuitInfo) LastRoundFinishOrder := -1 LastCompletedRound := -1Bir oyuncu ayrıldığında raunt bilgilerini sıfırlamak için
OnPlayerRemovedadlı bir fonksiyon oluştur.Verse# When a player is removed from the race, reset their circuit to prevent their # stats from showing up on billboards and player references. OnPlayerRemoved(Player:player):void= # Reset circuit info when player leaves the game. if: ResetCircuitInfo[Player] else: Print("Unable to reset circuit info for player")GetPlayspace().PlayerRemovedEvent()olayına bağlanarak bir oyuncu oyundan ayrıldığında çağrılacakOnPlayerRemovedfonksiyonunu ayarla.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved) Players := GetPlayspace().GetPlayers() CurrentRound := GetLastCompletedRound(Players) + 1Oyundan ayrılan oyuncunun bilgisinin sıfırlandığını doğrulamak için test et.
Oyun Bittiğinde Raunt Bilgilerini Sıfırla
Bir Verse cihazı için OnBegin fonksiyonu her raundun başında çalışır. Bir oyuncunun son tamamladığı raundun toplam raunt sayısıyla aynı olması gibi beklenmeyen kalıcı veriler olup olmadığını belirlemek için bu an iyi bir zamandır. Böyle bir sorun varsa oyuncunun verilerini sıfırlaman gerekir. Şu anda bir oyundaki toplam raunt sayısını bilmeye yönelik bir API bulunmamaktadır. Bunun yerine Verse kodundaki toplam raunt sayısı için Verse cihazına düzenlenebilir bir özellik eklemen ve bu özelliğin Ada Ayarları içindeki Toplam Raunt Sayısı özelliğiyle eşleştiğinden emin olman gerekir.
Oyun bittiğinde raunt bilgilerini sıfırlamak için aşağıdaki adımları izle:
Oyundaki toplam raunt sayısı için Verse cihazına düzenlenebilir bir özellik ekle. TotalRounds değeri
0veya daha küçük olmamalıdır, bu yüzden özelliğin değerini1veya daha büyük olacak şekilde kısıtla.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)Oyuncunun son tamamlanan raunt için kalıcı verileri oyunda beklenen raunt sayısından daha büyükse bu verileri sıfırlamak için
GetLastCompletedRoundfonksiyonunu güncelle.Verse# Returns the highest last completed round among all players. GetLastCompletedRound<public>(Players:[]player, TotalRounds:int)<transacts>:int= var LastCompletedRound:int = -1 for: Player : Players Player.IsActive[] PlayerCircuitInfo := CircuitInfo[Player] do: # If player's recorded info is greater than the total rounds for whatever reason, # then need to reset the player's circuit info because they shouldn't have more than what's allowed.Toplam raunt sayısını bir bağımsız değişken olarak geçirmek için
GetLastCompletedRoundçağrısını güncelle ve oyuncu raunt bilgileri beklenmeyen bir durumdaysa sıfırla.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)Tüm rauntlar oynanıp tamamlandıktan sonra bile oyuncu raunt bilgilerinin sıfırlandığını doğrulamak için test et.
Geçerli Raunda Göre Mantık Ekleme
Şimdi bu bilgileri kullanarak oyuncuların bulunduğu raunda göre özel mantık oluşturabilirsin. Örneğin bir oyunun birinci raundu için yerel sıralama gösterebilirsin.
Hangi raundun oynandığını bilmek için her defasında GetLastCompletedRound() çağrısı yapmak ideal bir durum değil. Onun yerine bunu her rauntta bir kez yapabilir ve raunt bilgilerini bir oturum zayıf harita değişkenine kaydedebilirsin. Böylece projedeki tüm Verse kodları, her defasında yeniden hesaplamak zorunda olmadan bu değere her zaman erişebilir.
Oturum zayıf harita değişkeni ve oyuncu zayıf harita değişkenini kodunda kullanmanın farklarını ve gerekçelerini göstermek için güzel bir örnek verelim:
Oturum zayıf harita değişkenleri tek rauntlar için ve her defasında yeniden hesaplamak istemediğin geçerli raunt verilerini depolamak için faydalıdır.
Oyuncu zayıf harita değişkenleri ise birden fazla raunt ve oyun oturumunda kalıcı olması gereken bilgiler için tasarlanmıştır ancak bireysel oyuncularla ilişkilendirilmelidir.
Geçerli raundu depolamak üzere bir oturum zayıf harita değişkeni ayarlamak için aşağıdaki adımları izle.
Raunt bilgilerinin depolanacağı bir sınıf oluştur. En azından bir
CurrentRoundalanına ihtiyacın var ancak oyuncuların başlangıç pozisyonları ve araçları gibi tüm Verse koduna kaydetmek istediğin diğer raunt bilgilerini de dahil edebilirsin. Geçersiz veriyi temsil etmek üzereCurrentRoundalanını-1değeriyle başlat.Verseround_info := class: CurrentRound:int = -1Raunt bilgilerini oturumla birlikte depolamak için
round_infosınıfını kullanarak bir oturum zayıf harita değişkeni oluştur.Verse# Maps the current session to its associated round info. var RoundInfo:weak_map(session, round_info) = map{}Oturum zayıf harita değişkeninden geçerli raundu almak için bir alıcı fonksiyon ekle.
VerseGetRound<public>()<decides><transacts>:int= RoundInfo[GetSession()].CurrentRoundGeçerli raundu almak ve oturum zayıf harita değişkeninde depolamak için bir fonksiyon ekle.
VerseRecordCurrentRound<public>(Players:[]player, TotalRounds:int):void= var CurrentRoundInfo:round_info = if: Info := RoundInfo[GetSession()] then: Info else: LastCompletedRound := GetLastCompletedRound(Players, TotalRounds) round_info: CurrentRound := LastCompletedRound + 1Verse cihazını, hangi rauntta olduğunu bilmen gerektiğinde yeni
RecordCurrentRoundfonksiyonunu kullanacak veGetRoundçağrısı yapacak şekilde güncelle.Verse# A Verse-authored creative device that can be placed in a level test_round_info_device := class(creative_device): # The total number of rounds in the race. @editable TotalRounds:type {Rounds:int where 1 <= Rounds} = 3 # Runs when the device is started in a running game OnBegin<override>()<suspends>:void= GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)
Artık bu bilgiler bir oturum zayıf harita değişkeninde depolandığına göre rauntlar için kolayca özel mantık ekleyebilirsin. Örneğin, mevcut raundun birinci raunt olup olmadığını kontrol edebilir ve oyuncular için bir lobi ve sıralama görüntüleme alanı oluşturabilirsin.
# Returns true if this is the first round of the game.
IsFirstRound<public>(RoundToCheck:int)<decides><transacts>:void=
RoundToCheck <= 0Kendi Kendine Yapabileceklerin
Bu kodun bir yarış oyununda oyuncuların başlangıç sırasını belirlemek için nasıl kullanılacağı hakkında bilgi için Verse Sürekliliğiyle Pist Yarışı Şablonu bölümüne göz at.
Şablona göz attıktan sonra aşağıdakileri dene:
Oyuncuya hangi aracın atandığı gibi ilave raunt bilgilerini ekle.
Her raundun başlangıcında oyuncuları haritanın farklı alanlarına ışınla.
Raunda özel mantığı kullanan başka oyunlar aklına geliyor mu?
Tam Kod
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# A persistable map that maps each player to
# what order they finished the previous round.
var CircuitInfo<public>:weak_map(player, player_circuit_info) = map{}
# Maps the current session to its associated round info.
var RoundInfo:weak_map(session, round_info) = map{}