Bir Oyuncunun Boşta Olup Olmadığının Belirlenmesi
Bu bölümde, bir oyuncunun son simülasyon güncellemesinden bu yana belirli bir mesafe katedip etmediğini nasıl kontrol edeceğini öğreneceksin. Oyuncu mesafe katetmişse, oyuncunun mevcut konumu kaydedilir ve tekrar kontrol edilir. Katetmemişse döngü kırılır ve metot tamamlanır. Bu metot GetFortCharacter[]
, GetTransform()
ve Translation
kullanarak oyuncunun konumunu alır. Bunlar hakkında, her birinin API Referansı sayfalarından daha fazla bilgi edinebilirsin.
Bu sayfa, bu oynanışta ihtiyaç duyulan oyun mekaniğinin nasıl yürütüleceğini gösteren Verse kod parçacıkları içerir. Aşağıdaki adımları izle ve bu eğitimin 6. adımındaki kodun tamamını kopyala.
Bir oyuncunun hareketsiz olup olmadığını belirlemek için bu adımları izle.
-
AwaitStopMoving()
adlı aracı sınıfı için bir uzantı metodu oluştur. Bu, zaten tanımlanmış olan bir sınıfa özel bir metot eklediğin anlamına gelir.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.")
-
Oyuncunun başlangıç konumunu al.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.") # Aracının başlangıç konumunu, aracının sahnedeki karakterinden al. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation
-
Oyuncunun bir sonraki konumunu, bir sonraki simülasyon güncellemesinde al.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.") # Aracının başlangıç konumunu, aracının sahnedeki karakterinden al. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al. NewPosition := Tracked.GetTransform().Translation
- Başlangıç konumu ile en son konum arasındaki mesafenin, fonksiyona
MinimumDistance
parametresi olarak geçirilen kabul edilebilir bir eşik dahilinde olup olmadığını kontrol et.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.") # Aracının başlangıç konumunu, aracının sahnedeki karakterinden al. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al. NewPosition := Tracked.GetTransform().Translation # Yeni konumun başlangıç konumundan itibaren mesafesi MinimumDistance değerinden azsa, aracı hareket etmemiş demektir ve bu durumda döngüyü kırarız. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Aracı minimum mesafeden daha az hareket etti.") # Aksi takdirde, oyuncunun yeni konumdan hareket ettiğinden emin olmak için StartPosition’ı sıfırlarız. else: set StartPosition = NewPosition
-
Şimdi başlangıç konumları ile en son konumlar arasındaki kontrolü döngüye almamız, konumlar arasındaki mesafe
MinimumDistance
eşiğinin üzerinde olduğunda ise döngüden çıkmamız uygun olacaktır.# Aracı, MinimumDistance’tan daha az hareket edene kadar döngü içinde olur. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.") # Aracının başlangıç konumunu, aracının sahnedeki karakterinden al. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al. NewPosition := Tracked.GetTransform().Translation # Yeni konumun başlangıç konumundan itibaren mesafesi MinimumDistance değerinden azsa, aracı hareket etmemiş demektir ve bu durumda döngüyü kırarız. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Aracı minimum mesafeden daha az hareket etti.") break # Aksi takdirde, oyuncunun yeni konumdan hareket ettiğinden emin olmak için StartPosition’ı sıfırlarız. else: set StartPosition = NewPosition
Kalp Atışından Önce Geri Sayım
Geri sayım süresi dolana kadar bir uyarı ve geri sayım süreölçerini görüntülemeden önce HeartBeat.MoveTime - HeartBeat.WarningTime
süresine eşit bir süreyle beklemek ve ardından uyarı ve geri sayım metnini temizlemek için bu adımları izle.
- CountdownTimer() adlı bir fonksiyon oluştur.
# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Kalp atışı geri sayımı başlatılıyor.")
-
Öncelikle heartbeat.verse içinde ayarladığın haritadan, ilgili oyuncu için
heartbeat_warning_ui
almayı denemen gerekir. Bu başarılı olursa, oynatıcının durması ile geri sayım süreölçerinin görüntülemesi arasındaki gecikmeyi başlatman gerekir.# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Kalp atışı geri sayımı başlatılıyor.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uyarı görünmeden önceki süre boyunca uyu. Logger.Print("Kalp atışı uyarısı başlatılıyor.") else: Logger.Print("UIData bulunamadı.")
-
Şimdi, ekranda görünecek ve her saniyede bir adet azaltılacak olan değişkeni oluştur. Bunu
WarningTimeRemaining
olarak adlandır. heartbeat.verse’tenWarningTime
olarak ayarla.WarningTimeRemaining
birint
,WarningTime
ise birfloat
olduğundan birint
oluşturmak içinCeil[]
fonksiyonunu kullanman gerekir.# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Kalp atışı geri sayımı başlatılıyor.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uyarı görünmeden önceki süre boyunca uyu. Logger.Print("Kalp atışı uyarısı başlatılıyor.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("UIData bulunamadı.")
-
Geri sayım döngüsünü başlatmadan önce,
CountdownTimer()
fonksiyonu her tamamlandığında oyuncunun Kullanıcı Arayüzünden geri sayım süreölçerini temizlemek içindefer
ifadesini kullan. Yalnızca süreölçerin süresi dolduğunda veya oyuncu tekrar hareket etmeye başladığında tamamlanır. Daha fazla bilgi için Defer sayfasına bak.# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Kalp atışı geri sayımı başlatılıyor.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uyarı görünmeden önceki süre boyunca uyu. Logger.Print("Kalp atışı uyarısı başlatılıyor.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Erteleme, fonksiyon tamamlandığında veya iptal edilmesi halinde (örneğin bir yarışı kaybederse) gerçekleşir. # Dolayısıyla bu durumda, geri sayım bittiğinde veya nesne aracısının geri sayım bitmeden hareket etmesi halinde uyarı metni temizlenir. defer: UIData.Text.SetText(HeartBeatWarningClear) # Uyarı metnini kalan süreye ayarla, bir saniye bekle ve ardından kalan süreyi azalt. Geri sayım tamamlanırsa döngüyü kır. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("UIData bulunamadı.")
-
Son olarak, geri sayım süreölçerini azaltan döngüyü oluştur.
HeartBeatWarningMessage
’ıWarningTimeRemaining
ile görüntülemek içinSetText()
fonksiyonunu kullan. Ardından, kalan süreyi azaltmadan önceSleep()
ile bir saniye bekle.WarningTimeRemaining
0 veya daha azsa geri sayım tamamlanmış demektir; bu durumda döngüyü kırabilirsin.# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Kalp atışı geri sayımı başlatılıyor.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uyarı görünmeden önceki süre boyunca uyu. Logger.Print("Kalp atışı uyarısı başlatılıyor.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Erteleme, fonksiyon tamamlandığında veya iptal edilmesi halinde (örneğin bir yarışı kaybederse) gerçekleşir. # Dolayısıyla bu durumda, geri sayım bittiğinde veya nesne aracısının geri sayım bitmeden hareket etmesi halinde uyarı metni temizlenir. defer: UIData.Text.SetText(HeartBeatWarningClear) # Uyarı metnini kalan süreye ayarla, bir saniye bekle ve ardından kalan süreyi azalt. Geri sayım tamamlanırsa döngüyü kır. loop: Logger.Print("{WarningTimeRemaining} saniye içinde kalp atışı.") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("UIData bulunamadı.")
Boştaki Oyuncular üzerinde Efektler Oynatma
AwaitStopMoving()
tamamlandığında, oyuncunun geri sayım süreölçerini ve ardından kalp atışı efektlerini başlatma zamanının geldiğini bilirsin. Ancak tekrar hareket etmeye başladıkları anda, süreölçeri veya kalp atışını (o sırada hangisi çalışıyorsa) iptal etmen uygun olacaktır. Bunu yapmak için bir race
ifadesine ihtiyacın vardır. İki yarış ifadesi şunlardır:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance)
. -
Kalp atışı efektleri oynatılmadan önce geri sayımın olduğu
block
.
Yarışı kazanmak ve geri sayım süreölçerini veya kalp atışı efektlerini durdurmak için AwaitStartMoving()
’e ihtiyaç vardır.
Bunun içindeki iki fonksiyonun (CountdownTimer()) ve 'StartHeartbeart()`ın sırayla çalışmasını ve birbirleriyle yarışmamasını sağlamak için blok ifadesi kullanılır. Geri sayım süreölçerinin, Nesne oyuncusunu, kalp atışı efektlerinin süreölçer tamamlandıktan sonra başlayacağı, dolayısıyla hem süreölçeri hem de kalp atışını aynı anda başlatmanın mantıklı olmayacağı yönünde bilgilendirmesi amaçlanmıştır.
Oyuncu çok uzun bir süre boyunca hareket etmediğinde efektleri oynatmak için bu adımları izle.
- Uygulamanın aşağıdakiler dışında aynı olduğu
AwaitStartMoving()
adında bir uzantı metodu oluştur:
-
Oyuncunun son simülasyon güncellemesinden bu yana
MinimumDistance
kadar mı yoksa daha fazla mı hareket ettiğini kontrol eder.AwaitStopMoving()
’deki gibiMinimumDistance
’tan daha az olması yerine. -
Her döngüden sonra
StartPosition
’ı sıfırlamaz.StartPosition
, her döngünün sonunda sıfırlanmışsa oyuncunun simülasyon güncellemesini yapmak için gereken süredeMinimumDistance
’ın tamamı veya daha fazlası kadar hareket etmesi gerekecektir ki bu imkansız olabilir.# Aracı MinimumDistance’tan daha fazla hareket edene kadar döngü içinde olur. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Aracının minimum mesafeden daha ileriye hareket edip etmediği kontrol ediliyor.") # Aracının başlangıç konumunu, aracının sahnedeki karakterinden al. if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al. NewPosition := Tracked.GetTransform().Translation # Yeni konumun başlangıç konumundan itibaren mesafesi MinimumDistance’tan büyük veya ona eşitse aracı hareket etmiş demektir ve bu sebeple döngüyü kırarız. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("Aracı minimum mesafeden daha fazla veya ona eşit bir mesafe kadar hareket etti.") break
-
Oyuncu çok uzun bir süre boyunca hareketsiz kaldığında kalp atışı efektini oynatmayı sağlayan
RunPropGameLoop()
adında bir fonksiyon oluştur.# Nesne aracısı hareket etmeyi durdurursa nesne aracısının MinimumMoveDistance’ı aştığını ve kalp atışı süreölçerinin tamamlandığını mı yoksa nesne aracısının avlandığını mı görmek için yarış. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Nesne aracısı oyun döngüsü başlatılıyor.")
-
Nesne aracısı minimum mesafeden daha az hareket edene kadar bekle, ardından ilerle.
# Nesne aracısı hareket etmeyi durdurursa nesne aracısının MinimumMoveDistance’ı aştığını ve kalp atışı süreölçerinin tamamlandığını mı yoksa nesne aracısının avlandığını mı görmek için yarış. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Nesne aracısı oyun döngüsü başlatılıyor.") # Nesne aracısı avlanana veya oyuncu oturumdan ayrılana kadar nesne davranışı üzerinden sonsuza kadar döngü halinde çalıştır. loop: # Nesne aracısı minimum mesafeden daha az hareket edene kadar bekle, ardından ilerle. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0)
-
Oyuncunun hareket etmeye başladığı anlamına gelen
AwaitStartMoving()
’in tamamlanması ileCountdownTimer()
’a sahip birblock
ifadesinin, ardından daStartHeartbeat()
’in çalışması arasında yarışmak içinrace
ifadesini ekle.# Nesne aracısı hareket etmeyi durdurursa nesne aracısının MinimumMoveDistance’ı aştığını ve kalp atışı süreölçerinin tamamlandığını mı yoksa nesne aracısının avlandığını mı görmek için yarış. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Nesne aracısı oyun döngüsü başlatılıyor.") # Nesne aracısı avlanana veya oyuncu oturumdan ayrılana kadar nesne davranışı üzerinden sonsuza kadar döngü halinde çalıştır. loop: # Nesne aracısı minimum mesafeden daha az hareket edene kadar bekle, ardından ilerle. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Nesne aracısı minimum mesafenin ötesine geçene kadar kalp atışı için geri sayım yap ve ardından kalp atışını süresiz olarak çal. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Yarış tamamlandığında (nesne aracısı hareket ettiğinde), döngüyü yeniden başlat.