Casuslara titreşimli bir görsel efekt eklemek için oyuncu karakterini art arda gösterip gizleyeceksin. Bir Casusun hasar aldığı her durumda bu efekt oluşmalıdır ancak aynı zamanda bu fonksiyon çağrıldığında kodunun geri kalanının çalışmaya devam ettiğinden emin olman gerekir. Birden fazla Casusunun olduğu zamanlarda bu durum çok daha karmaşık hale gelir. Bir oyun sırasında aynı anda hasar gören birden fazla Casus olabilir, bu yüzden her birini ayrı ayrı ele alabilen bir koda ihtiyacın olacak.
Bunu başarmak için spawn ifadesini yoğun bir şekilde kullanman gerekir. Bir fonksiyonu üretmek, kodunun geri kalanını beklemeye almadan fonksiyonu asenkron bir şekilde çalıştırmana olanak tanır. Her Casus için bir fonksiyon üreterek her Casusun diğerlerinden bağımsız şekilde titrediğinden emin olabilirsin.
Bir Casus hasar aldığında karakterini nasıl titreteceğini öğrenmek için bu adımları izle.
Titreme Döngüsünü Oluşturma
invisibility_manager
sınıf tanımınaFlickerCharacter()
adlı yeni bir fonksiyon ekle. Bu fonksiyon birfort_character
alır ve karakterin görünüp kaybolarak titremesini sağlar. Bu fonksiyona<suspends>
belirleyicisini ekleyerek asenkron şekilde çalışmasına izin ver.# Fort_character'ını yinelemeli şekilde gizleyip göstererek bir aracının (oyuncu veya AI) görünürlüğünü titretir FlickerCharacter(InCharacter:fort_character)<suspends>:void= Logger.Print("FlickerCharacter() çağrıldı")
FlickerCharacter()
içinde,InCharacter
üzerindeHide()
döngüsü uygula, belirli bir süreSleep()
çalıştır (daha önce tanımladığınFlickerRateSeconds
boyunca), karaktereShow()
uygula ve tekrar uyut. Bunu yaptığında; karakter üzerinde, düşman oyuncuların karakteri takip etmesine izin veren ancak kısa süreli görünmezlik nedeniyle zor nişan almalarına neden olan bir titreme efekti oluşturulur.# Fort_character'ını yinelemeli şekilde gizleyip göstererek bir aracının (oyuncu veya AI) görünürlüğünü titretir FlickerCharacter(InCharacter:fort_character)<suspends>:void= Logger.Print("FlickerCharacter() çağrıldı") # Titreşim efekti oluşturmak için karakteri gizleme ve gösterme döngüsü. loop: InCharacter.Hide() Sleep(FlickerRateSeconds) InCharacter.Show() Sleep(FlickerRateSeconds)
Döngüyü Bozma
Karakterin titremesinin durması gerektiğinde bu döngü fonksiyonundan çıkmanın bir yolu gerekir. Daha önce oluşturduğun
PlayerVisibilitySeconds
eşleştirmesi bir oyuncunun daha ne kadar süre titreyeceğini takip eder. Her döngü sırasında bu süreyi azaltman gerekecektir. Kalan süre 0'a ulaştığında oyuncu titremeyi durdurur ve döngüden çıkabilirsin.InCharacter.GetAgent[]
anahtarını kullanıpPlayerVisibilitySeconds
eşleştirmesine erişerek ve bu değeri birTimeRemaining
değişkeninde depolayarak bir oyuncunun daha ne kadar süre titreyeceğini görebilirsin. DeğeriFlickerRateSeconds * 2
kadar azaltarak aynı ifadede eşleştirmenin kalan süresini ayarlayabilirsin. BöyleceTimeRemaining
,set
ifadesi çözümlendikten sonraPlayerVisibilitySeconds
içindeki değer olacaktır. Her döngüde iki kezSleep()
çağrısı yaptığın içinFlickerRateSeconds
değeri 2 ile çarpılmalıdır.# Fort_character'ını yinelemeli şekilde gizleyip göstererek bir aracının (oyuncu veya AI) görünürlüğünü titretir FlickerCharacter(InCharacter:fort_character)<suspends>:void= Logger.Print("FlickerCharacter() çağrıldı") # Titreşim efekti oluşturmak için karakteri gizleme ve gösterme döngüsü. loop: InCharacter.Hide() Sleep(FlickerRateSeconds) InCharacter.Show() Sleep(FlickerRateSeconds) # Her döngüde karakterin titreme miktarı FlickerRateSeconds kadar azalır. # Kalan süre 0'a ulaşırsa döngüden çık. if: TimeRemaining := set PlayerVisibilitySeconds[InCharacter.GetAgent[]] -= FlickerRateSeconds * 2
TimeRemaining
değerinin 0’a eşit veya daha küçük olup olmadığını kontrol et. Bu değer, titremesini durdurmamız gereken karakteri gösterir. Bunu yapmak için karakter üzerindeHide()
fonksiyonunu çağırarak karakteri tekrar görünmez yap vebreak
fonksiyonuyla döngüden çık.FlickerCharacter()
fonksiyonun şu şekilde görünmelidir:# Fort_character'ını yinelemeli şekilde gizleyip göstererek bir aracının (oyuncu veya AI) görünürlüğünü titretir FlickerCharacter(InCharacter:fort_character)<suspends>:void= Logger.Print("FlickerCharacter() çağrıldı") # Titreşim efekti oluşturmak için karakteri gizleme ve gösterme döngüsü. loop: InCharacter.Hide() Sleep(FlickerRateSeconds) InCharacter.Show() Sleep(FlickerRateSeconds) # Her döngüde karakterin titreme miktarı FlickerRateSeconds kadar azalır. # Kalan süre 0'a ulaşırsa döngüden çık. if: TimeRemaining := set PlayerVisibilitySeconds[InCharacter.GetAgent[]] -= FlickerRateSeconds * 2 TimeRemaining <= 0.0 then: InCharacter.Hide() break
Titremeyi Başlatma ve Sıfırlama
Bir Casus zaten titriyorken hasar görürse ne olacağını düşün. Bu durumda sonraki her hasar örneği yeni bir fonksiyon üreteceğinden FlickerCharacter()
fonksiyonları hızlıca kontrolden çıkabilir ve aynı karakter üzerinde düzinelerce fonksiyon çalışabilir. Bunun yerine, oyuncu her hasar aldığında oyuncunun PlayerVisibilitySeconds
değeri sıfırlanmalıdır. Bunu yapmak için bir fonksiyon tanımlayarak oyuncunun titreyip titremediğini kontrol etmelisin. Titriyorsa oyuncunun titremesi gereken süreyi sıfırla. Titremiyorsa bu karakter için yeni bir titreme olayı üret.
invisibility_manager
sınıf tanımına, bir oyuncunun titreyip titremediğini belirlemek için kullanacağınIsFlickering()
adlı yeni bir yardımcı fonksiyon ekle. Bu fonksiyon, bir aracıyı bağımsız değişken olarak alır vePlayerVisibilitySeconds
değeri0.0
sayısından daha büyüksetrue
döndürür. Bu fonksiyonu hem başarısız olabilir hale getirmek hem de başarısızlık durumunda geri alınmasına izin vermek için fonksiyonadecides
vetransacts
belirleyicilerini ekle.# Oyuncunun titreme süresi kalıp kalmadığını döndürür IsFlickering(InAgent:agent)<decides><transacts>:void= PlayerVisibilitySeconds[InAgent] > 0.0
invisibility_manager
sınıf tanımınaStartOrResetFlickering()
adlı yeni bir fonksiyon ekle. Bu fonksiyon, bir aracıyı bağımsız değişken olarak alır ve bir oyuncunun titremeye başlaması veya titremeyi sıfırlaması gerektiğini belirler.# Aracı görünmezse yeni bir titreme olayı başlatır, görünmez değilse # aracının devam eden titremesini sıfırlar. StartOrResetFlickering(InAgent:agent):void=
StartOrResetFlickering()
dizisinde belirtilen aracının titremediğini kontrol et. Titremiyorsa bu aracı için yeni bir titreme olayı başlatman gerekir. Bu aracı içinfort_character
değerini al ve birFortCharacter
değişkenine kaydet.# Aracı görünmezse yeni bir titreme olayı başlatır, görünmez değilse # aracının devam eden titremesini sıfırlar. StartOrResetFlickering(InAgent:agent):void= if (not IsFlickering[InAgent], FortCharacter := InAgent.GetFortCharacter[]): Logger.Print("Bu karakter için YENİ FlickerEvent başlatmayı deniyor")
PlayerVisibilitySeconds
içindeki aracının değeriniVulnerableSeconds
olarak ayarla, sonra bu aracı içinFortCharacter
değerini geçerek yeni birFlickerCharacter()
fonksiyonunaspawn
uygula.if (not IsFlickering[InAgent], FortCharacter := InAgent.GetFortCharacter[]): Logger.Print("Bu karakter için YENİ FlickerEvent başlatmayı deniyor") # Yeni titreşim başlatıldı if (set PlayerVisibilitySeconds[InAgent] = VulnerableSeconds): spawn{FlickerCharacter(FortCharacter)} Logger.Print("Bu karakter için bir FlickerEvent üretildi")
- Aracı zaten titriyorsa yalnızca
PlayerVisibilitySeconds
içindeki değeriniVulnerableSeconds
olarak sıfırlaman gerekir. Daha öncekiFlickerCharacter()
fonksiyonu, bu değeri asenkron bir şekilde okuduğu içinFlickerCharacter()
döngüsü devam ederken değer sıfırlanırsabreak
devreye girmeden döngü devam eder.StartOrResetFlickering()
fonksiyonun şu şekilde görünmelidir:# Aracı görünmezse yeni bir titreme olayı başlatır, görünmez değilse # aracının devam eden titremesini sıfırlar. StartOrResetFlickering(InAgent:agent):void= if (not IsFlickering[InAgent], FortCharacter := InAgent.GetFortCharacter[]): Logger.Print("Bu karakter için YENİ FlickerEvent başlatmayı deniyor") # Yeni titreşim başlatıldı if (set PlayerVisibilitySeconds[InAgent] = VulnerableSeconds): spawn{FlickerCharacter(FortCharacter)} Logger.Print("Bu karakter için bir FlickerEvent üretildi") else: # Devam eden titreşimi sıfırla if (set PlayerVisibilitySeconds[InAgent] = VulnerableSeconds): Logger.Print("Karakterin FlickerTimer süresini VulnerableSeconds değerine sıfırla")
Hasar Gören Casusları Titretme
Bütün bu fonksiyonları birbirine bağlamak için bir Casus hasar gördüğünde ne olacağını belirleyen bir fonksiyon tanımlamalısın. FlickerCharacter()
fonksiyonunda olduğu gibi, hasar alıp almadığını belirlemek için her bir Casusu ayrı ayrı takip etmen gerekir. Her Casus için bir fonksiyon üretebilmen amacıyla bu fonksiyonun asenkron olması gerekir.
invisibility_manager
sınıf tanımınaOnInfiltratorDamaged()
adlı yeni bir fonksiyon ekle. Bu fonksiyon bir aracıyı alır ve bu aracı hasar gördüğündeStartOrResetFlickering()
fonksiyonunu çağırır. Bu fonksiyona<suspends>
belirleyicisini ekleyerek asenkron şekilde çalışmasına izin ver.# Bir aracı (oyuncu veya AI) hasar aldığında görünürlüğünü titretir OnInfiltratorDamaged(InAgent:agent)<suspends>:void= Logger.Print("Bu karakter için titretme başlatılmaya çalışıyor")
- Geçerli oyun alanı için
fort_team_collection
değerini al ve birTeamCollection
değişkenine kaydet. Sonra aracının bu fonksiyona geçirilenfort_character
değerini al.# Bir aracı (oyuncu veya AI) hasar aldığında görünürlüğünü titretir OnInfiltratorDamaged(InAgent:agent)<suspends>:void= Logger.Print("Bu karakter için titretme başlatılmaya çalışıyor") TeamCollection := GetPlayspace().GetTeamCollection() if (FortCharacter := InAgent.GetFortCharacter[]):
- Bu fonksiyonun kendisine geçirilen aracıyı sürekli olarak izlemesi gerektiğinden döngüye girmesi şarttır. Bu döngü, belirtilen karakter her hasar aldığında çalışmalıdır ve fonksiyonun izlediği aracıda
StartOrResetFlickering
fonksiyonunu çağırır.OnInfiltratorDamaged
fonksiyonuna bir döngü ekle.# Bir aracı (oyuncu veya AI) hasar aldığında görünürlüğünü titretir OnInfiltratorDamaged(InAgent:agent)<suspends>:void= Logger.Print("Bu karakter için titretme başlatılmaya çalışıyor") TeamCollection := GetPlayspace().GetTeamCollection() if (FortCharacter := InAgent.GetFortCharacter[]): loop:
- Döngünün içinde
IsVisibilityShared
değerinin true olup olmadığını kontrol et. Değer true ise bu bir casus hasar gördüğünde takımdaki tüm casusların titremeye başlayacağı anlamına gelir. Bu ayar etkinse sırasıylaGetTeam[]
veGetAgents[]
fonksiyonlarını çağırarak hem bu aracının takımını hem de takımdaki oyuncuları al.if (FortCharacter := InAgent.GetFortCharacter[]): loop: if(IsVisibilityShared?, CurrentTeam := TeamCollection.GetTeam[InAgent], TeamAgents := TeamCollection.GetAgents[CurrentTeam]):
- Şimdi bir
for
döngüsünde her takım arkadaşı içinStartOrResetFlickering
çağrısı yap.if(IsVisibilityShared?, CurrentTeam := TeamCollection.GetTeam[InAgent], TeamAgents := TeamCollection.GetAgents[CurrentTeam]): # Her bir takım arkadaşını PlayerVisibility saniye içinde ayarla ve bir FlickerEvent üret for(Teammate:TeamAgents): Logger.Print("Bir Takım Arkadaşı için StartOrResetFlickering çağrılıyor") StartOrResetFlickering(Teammate)
- Görünürlük paylaşılmıyorsa bu fonksiyonun izlediği aracı için
StartOrResetFlickering
çağrısı yap.loop: if(IsVisibilityShared?, CurrentTeam := TeamCollection.GetTeam[InAgent], TeamAgents := TeamCollection.GetAgents[CurrentTeam]): # Her bir takım arkadaşını PlayerVisibility saniye içinde ayarla ve bir FlickerEvent üret for(Teammate:TeamAgents): Logger.Print("Bir Takım Arkadaşı için StartOrResetFlickering çağrılıyor") StartOrResetFlickering(Teammate) else: # Sadece hasar gören karakteri titret Logger.Print("InAgent için StartOrResetFlickering çağrılıyor") StartOrResetFlickering(InAgent)
- Döngünün sonunda son olarak ilgili karakterin
DamagedEvent()
değerineAwait()
uygula. Bu şekilde döngü yalnızca bir karakter hasar gördüğünde yinelenir. Fonksiyon başladığında bu döngünün en az bir kez çalışacağını unutma. Yani en az birStartOrResetFlickering()
çağrısı yapılacaktır. Bunun sonucunda casuslar oyuna titreyerek başlar, sonra görünmez olurlar. Bu durum, casuslara görünmez olduklarını ve aynı zamanda görünmezliğin kalıcı olmadığını hatırlatmaya yardımcı olur.OnInfiltratorDamaged()
fonksiyonun şu şekilde görünmelidir:# Bir aracı (oyuncu veya AI) hasar aldığında görünürlüğünü titretir OnInfiltratorDamaged(InAgent:agent)<suspends>:void= Logger.Print("Bu karakter için titretme başlatılmaya çalışıyor") TeamCollection := GetPlayspace().GetTeamCollection() if (FortCharacter := InAgent.GetFortCharacter[]): loop: if(IsVisibilityShared?, CurrentTeam := TeamCollection.GetTeam[InAgent], TeamAgents := TeamCollection.GetAgents[CurrentTeam]): # Her bir takım arkadaşını PlayerVisibility saniye içinde ayarla ve bir FlickerEvent üret for(Teammate:TeamAgents): Logger.Print("Bir Takım Arkadaşı için StartOrResetFlickering çağrılıyor") StartOrResetFlickering(Teammate) else: # Sadece hasar gören karakteri titret Logger.Print("InAgent için StartOrResetFlickering çağrılıyor") StartOrResetFlickering(InAgent) FortCharacter.DamagedEvent().Await()
Oyun Başlangıcında Karakterler İçin Fonksiyonlar Üretme
StartInvisibilityManager()
fonksiyonuna döndüğünde bir oyuncunun karakteri için Hide()
çağrısı yapmadan önce o karakter için bir OnInfiltratorDamaged()
fonksiyonu üret. Bu şekilde her casusun kendisini asenkron bir şekilde izleyen ve titremesiyle ilgili tüm mantığı işleyen bir fonksiyonu olur. StartInvisibilityManager()
şu şekilde görünmelidir:
StartInvisibilityManager<public>(AllTeams:[]team, AllPlayers:[]player, Infiltrators:team):void=
Logger.Print("Görünmezlik kodu başlatıldı!")
set Teams = GetPlayspace().GetTeamCollection().GetTeams()
for(PlayerSpawner:PlayersSpawners):
PlayerSpawner.SpawnedEvent.Subscribe(OnPlayerSpawn)
# Bir oyuncu casus takımında doğduysa o oyuncu için bir OnInfiltratorDamaged fonksiyonu
# oluştur. Ardından, karakterini görünmez yap.
for (TeamPlayer:AllPlayers):
if:
FortCharacter:fort_character = TeamPlayer.GetFortCharacter[]
CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]
Logger.Print("Bu oyuncunun geçerli takımı alındı")
Teams[0] = CurrentTeam
set PlayerVisibilitySeconds[TeamPlayer] = 0.0
Logger.Print("Oyuncu PlayerVisibilitySeconds değerine eklendi")
then:
spawn{OnInfiltratorDamaged(TeamPlayer)}
Logger.Print("Oyuncu bir casus olarak doğdu, bu da onu görünmez yapıyor")
FortCharacter.Hide()
else:
Logger.Print("Bu oyuncu bir casus değil")
Kodu kaydet, derle ve bölüme oynanış testi uygulamak için UEFN araç çubuğunda Oturumu Başlat düğmesine tıkla. Bölümüne oynanış testi yaptığında kodun başlatılmasıyla her Casus titremeli, sonra görünmez olmalıdır. Casus hasar aldıktan sonra, IsVisibilityShared
fonksiyonunu ayarladığın değere bağlı olarak tek başına ya da takım halinde titremelidir.

Sonraki Adım
Bu eğitimin sonraki adımında sürmekte olan oyuna katılan oyuncuları nasıl işleyeceğini öğreneceksin.