Ao concluir esta etapa no tutorial Prova de tempo: Em busca da pizza, você aprenderá a gerenciar a pontuação quando um jogador coleta itens e os entrega, e a atualizar a IU para exibir as pontuações. Para saber mais sobre como criar uma IU de jogo em Verse, consulte Como criar uma IU no jogo.
O gerenciador de pontuação rastreará e exibirá o seguinte:
Total de pontos: representa o total de pontos que o jogador marcou no jogo.
Pontos pendentes: representa os pontos que o jogador acumulou para esse conjunto de retiradas.
Nível de retirada: representa o nível de retirada atual.
Como criar a IU
Siga estas etapas para criar a IU do gerenciador de pontuação no Verse:
Crie um novo arquivo vazio do Verse e chame-o de score_manager.verse.
Crie uma nova classe chamada
score_managere adicione os seguintes campos à classe:Um
agentopcional chamadoMaybePlayerpara armazenar uma referência ao jogador.MaybePlayer<internal> : ?agent = falseUm
player_uiopcional chamadoMaybePlayerUIpara armazenar uma referência à IU.MaybePlayerUI<internal> : ?player_ui = falseUm
score_manager_devicepara armazenar uma referência ao dispositivo Gerenciador de Pontuação em torno do qual essa classe foi construída. (Observe que essa não é uma referência editável porque precisa ser conectada ao dispositivo de autoria do Versegame_coordinator_device.ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}Uma variável inteira chamada
TotalGameScoreque representa todos os pontos que o jogador marcou no jogo em geral.var TotalGameScore<private> : int = 0Uma variável inteira chamada
PendingScoreque representa os pontos que o jogador acumulou atualmente para esse conjunto de retiradas.var PendingScore<private> : int = 0Uma variável inteira chamada
PickupLevelque representa o nível de retirada atual.var PickupLevel<private> : int = 0
A definição da sua classe score_manager agora deve ter a seguinte aparência:
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 = 0Crie a IU quando a classe for criada pela primeira vez. Para fazer isso, adicione uma expressão
blockà definição da classe, que será executada sempre que você criar uma instância da classe. Adicione as seguintes variáveis para gerar a IU:Uma variável
canvaschamadaCanvasque tem o especificadorinternalpara armazenar o widget de tela personalizado.var Canvas<internal> : canvas = canvas{}Um
text_blockchamadoTotalGameScoreWidgetque tem o especificadorinternalpara armazenar o widget de texto para exibição de todos os pontos que o jogador marcou no jogo em geral, conforme representado pela variávelTotalGameScore. Defina a cor de texto padrão do bloco de texto como branco.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}Um
text_blockchamadoPendingScoreWidgetque tem o especificadorinternalpara armazenar o widget de texto para exibição dos pontos que o jogador acumulou atualmente para esse conjunto de capturas, conforme representado pela variávelPendingScore. Defina a cor de texto padrão do bloco de texto como branco.PendingScoreWidget<internal> : text_block = text_block{}Um
text_blockchamadoPickupLevelWidgetque tem o especificadorinternalpara armazenar o widget de texto de exibição do nível de retirada atual, conforme representado pela variávelPickupLevel. Defina a cor de texto padrão do bloco de texto como branco.PickupLevelWidget<internal> : text_block = text_block{}Uma função que retorna uma
messagechamadaTotalGameScoreTextque cria um texto localizável que pode ser exibido na IU para todos os pontos que o jogador marcou no jogo.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total de pontos: {CurrentTotalGameScore}"Uma função que retorna uma
messagechamadaPendingScoreTextque cria um texto localizável que pode ser exibido na IU para os pontos que o jogador acumulou atualmente para esse conjunto de retiradas.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Pontos pendentes: {CurrentPendingScore}"Uma função que retorna uma
messagechamadaPickupLevelTextque cria texto localizável que pode ser exibido na IU para o nível de retirada atual.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Nível de retirada: {CurrentPickupLevel}"Adicione uma expressão
blockque cria o widget de tela e posiciona o texto empilhado verticalmente à esquerda da tela.<# Como não recriaremos a tela durante a vida útil do gerenciador de pontuação, faça-o uma vez sempre que um objeto desse tipo for criado. #> 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
Seu código para
score_manageragora deve ter a seguinte aparência: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 = "Nível de retirada: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Pontos pendentes: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : int) : message = "Total de pontos: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# Como não recriaremos a tela durante a vida útil do gerenciador de pontuação, faça-o uma vez sempre que um objeto desse tipo for criado. #> 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 := PickupLevelWidgetCrie uma função chamada
UpdateUI()que tenha o especificadorprivate, que atualiza o texto na IU com os valores de pontuação mais recentes e o nível de retirada atual.UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))Crie uma função chamada
AddScoreManagerToUI()que atualiza a IU do jogador com a IU personalizada do gerenciador de pontuação.AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()Crie uma função para cada valor exibido na interface do usuário para que o loop do jogo possa atualizar os valores:
Uma função chamada
AddPendingScoreToTotalScore()que tem o especificadorpublic. Essa função deve adicionar a pontuação pendente à pontuação total do jogo e redefinir o valor da pontuação pendente para0. Você pode usardeferpara redefinirPendingScoree atualizar a interface após a atualização deTotalGameScore. Isso evita o uso de uma variável temporária para manter o valor dePendingScoreantes que ela seja restaurada.Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScoreUma função chamada
UpdatePendingScore()que tem o especificadorpublice um parâmetro de número inteiro chamadoPointsque a função adicionará à pontuação pendente atual.Verse<# Adds the given amount of points to the pending points. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()Uma função chamada
UpdatePickupLevelque tem o especificadorpublice um parâmetro inteiro chamadoLevel, que é o novo valor para o nível de retirada atual.VerseUpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()Crie uma função chamada
AwardScore()que tenha o especificadorpublic. Essa função concede a pontuação ao jogador usando o dispositivo Gerenciador de Pontuação e o ativa.Verse<# Awards the score to the player with the Score Manager device, by activating it. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer)
Sua classe
score_manageragora deve ter a seguinte aparência:Versescore_manager := class: <# Since we won't recreate the canvas during the score manager lifetime, do it once anytime an object of this type is created.> 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 := trueAgora que você criou sua classe
score_manager, crie um construtor para que a classe inicialize as variáveis do jogador a partir do jogo. Observe que você deve converter digitalmente a referência do jogador deagentparaplayerpara obter uma referência à IU do jogador.VerseMakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}Seu arquivo game_coordinator_device.verse agora deve ter a seguinte aparência:
Verseusing { /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]]}
Como atualizar a pontuação e a IU no loop de jogo
Siga estas etapas para criar e atualizar sua interface de usuário durante o jogo no arquivo game_coordinator_device.verse:
Adicione as seguintes propriedades à classe
game_coordinator_device:Uma variável
score_managerchamadaScoreManagerque tem o especificadorprivate. Essa instância gerencia a pontuação e a IU do jogador.var ScoreManager<private> : score_manager = score_manager{}Um
score_manager_deviceeditável que você pode definir para o dispositivo Gerenciador de Pontuação no nível. Esse é o dispositivo que a classescore_managerusará.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}Uma matriz inteira editável chamada
PointsForPickupLevelque tem o especificadorpublic, para definir os pontos que o jogador pode marcar em cada nível de retirada.@editable # Mapeia quantos pontos uma retirada vale com base em seu nível de retirada. PointsForPickupLevel<public> : []int = array{1, 2, 3}
Na função
StartGame, inicialize a variável do Gerenciador de Pontuação chamando o construtorMakeScoreManager()com uma referência ao jogador e ao dispositivo Gerenciador de Pontuação e gere a IU para o jogador ver.VerseStartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") # We construct a new countdown_timer that'll countdown from InitialCountdownTime once started. # Also construct a new score_manager that'll keep track of the player's score and pickup level. # The countdown_timer and score_manager require a player to show their UI to. # We should have a valid player by now: the one that entered the vehicle, triggering the game start. if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...")Na função
PickupDeliveryLoop()do loop do jogo, atualize a interface sempre que o nível de retirada mudar e o jogador terminar uma retirada ou entrega:VersePickupDeliveryLoop<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 # Every time the loop restarts, we should reset the pickup level UI through the ScoreManager.Agora, quando a contagem regressiva terminar, conceda ao jogador sua pontuação. Em
HandleCountdownEnd(), chameScoreManager.AwardScore().HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)Seu arquivo game_coordinator_device.verse deve ficar assim:
Verseusing { /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 }