Al completar este paso del tutorial Prueba contrarreloj: Reparto de pizzas, obtendrás Más información sobre cómo gestionar la puntuación cuando un jugador recoge objetos y entregarlos, y cómo actualiza la interfaz de usuario para que muestre las puntuaciones. Para informarte sobre cómo crear una interfaz de usuario para el juego en Verse, consulta Crear una interfaz de usuario en el juego.
El gestor de puntuación hará un seguimiento y mostrará:
Total de puntos: representa el total de puntos que el jugador ha conseguido en el juego.
Puntos pendientes: representa los puntos que el jugador ha acumulado para el conjunto actual de recogidas.
Nivel de recogida: representa el nivel de recogida actual.
Cómo crear la IU
Sigue estos pasos para crear la interfaz de usuario del gestor de puntuación en Verse:
Crea un nuevo archivo de Verse vacío y nómbralo score_manager.verse.
Crea una nueva clase nombrada
score_managery añade los siguientes campos a la clase:Un
agentopcional nombradoMaybePlayerpara almacenar una referencia al jugador.MaybePlayer<internal> : ?agent = falseUn
player_uiopcional nombradoMaybePlayerUIpara almacenar una referencia a la IU del jugador.MaybePlayerUI<internal> : ?player_ui = falseUn
score_manager_devicepara almacenar una referencia al dispositivo Gestor de puntuación en torno al cual se construye esta clase (ten en cuenta que no es una referencia editable, ya que debe estar conectada al dispositivogame_coordinator_devicecreado con Verse).ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}Una variable entera nombrada
TotalGameScoreque representa todos los puntos que el jugador ha conseguido en el juego en general.var TotalGameScore<private> : int = 0Una variable entera nombrada
PendingScoreque representa los puntos que el jugador ha acumulado actualmente para este conjunto de recogidas.var PendingScore<private> : int = 0Una variable entera nombrada
PickupLevelque representa el nivel de recogida actual.var PickupLevel<private> : int = 0
Ahora, la definición de tu clase score_manager debería tener el siguiente aspecto:
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 = 0Crea la interfaz de usuario cuando se cree la clase por primera vez. Puedes hacerlo añadiendo una expresión
blocka la definición de la clase, que se ejecutará siempre que crees una instancia de la clase. Añade las siguientes variables para generar la IU:Una variable
canvasnombradaCanvasque tenga el especificadorinternalpara almacenar el widget del lienzo personalizado.var Canvas<internal> : canvas = canvas{}Un
text_blocknombradoTotalGameScoreWidgetcon el especificadorinternal, con el fin de almacenar el widget de texto para mostrar todos los puntos que ha conseguido el jugador durante toda la partida, representados por la variableTotalGameScore. Establece el color predeterminado del texto del bloque de texto en blanco.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}Un
text_blocknombradoPendingScoreWidgetcon el especificadorinternal, con el fin de almacenar el widget de texto para mostrar los puntos que el jugador ha acumulado actualmente para este conjunto de recogidas, representado por la variablePendingScore. Establece el color predeterminado del texto del bloque de texto en blanco.PendingScoreWidget<internal> : text_block = text_block{}Un
text_blockllamadoPickupLevelWidgetcon el especificadorinternal, con el fin de almacenar el widget de texto para mostrar el nivel de recogida actual, representado por la variablePickupLevel. Establece el color predeterminado del texto del bloque de texto en blanco.PickupLevelWidget<internal> : text_block = text_block{}Una función que devuelve un
messagenombradoTotalGameScoreTextque crea un texto localizable para mostrar en la interfaz de usuario todos los puntos que el jugador ha conseguido en el juego en general.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total de puntos: {CurrentTotalGameScore}"Una función que devuelve un
messagenombradoPendingScoreTextque crea un texto localizable para mostrar en la interfaz de usuario los puntos que el jugador ha acumulado actualmente para este conjunto de recogidas.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Puntos pendientes: {CurrentPendingScore}"Una función que devuelve un
messagenombradoPickupLevelTextque crea un texto localizable para mostrar en la interfaz de usuario el nivel de recogida actual.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Nivel de recogida: {CurrentPickupLevel}"Añade una expresión
blockque cree el widget del lienzo y posicione el texto apilado verticalmente a la izquierda de la pantalla.<# Como no volveremos a crear el lienzo mientras dure el gestor de puntuación, hazlo una vez cada vez que se cree un objeto de este tipo. #> 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
Ahora tu código para
score_managerdebería tener el siguiente aspecto: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 = "Nivel de recogida: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Puntos pendientes: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : int) : message = "Total de puntos: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# Como no volveremos a crear el lienzo mientras dure el gestor de puntuación, hazlo una vez cada vez que se cree un objeto de este tipo. #> 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 := PickupLevelWidgetCrea una función nombrada
UpdateUI()que tenga el especificadorprivate, que actualice el texto de la IU con los últimos valores de puntuación y el nivel de recogida actual.UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))Crea una función nombrada
AddScoreManagerToUI()que actualice la IU del jugador con la IU personalizada del gestor de puntuación.AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()Crea una función para cada valor que se muestre en la interfaz de usuario, de modo que el bucle de juego pueda actualizar los valores:
Una función nombrada
AddPendingScoreToTotalScore()que tenga el especificadorpublic. Esta función debe añadir la puntuación pendiente a la puntuación total del juego y restablecer el valor de la puntuación pendiente a0. Puedes aplazar condeferel restablecimiento dePendingScorey actualizar la IU después de que se actualiceTotalGameScore. Esto evita utilizar una variable temporal para mantener el valor dePendingScoreantes de que se reinicie.Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScoreUna función nombrada
UpdatePendingScore()que tenga el especificadorpublicy un parámetro entero llamadoPointsque la función añadirá a la puntuación pendiente actual.Verse<# Adds the given amount of points to the pending points. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()Una función nombrada
UpdatePickupLevelque tenga el especificadorpublicy un parámetro entero llamadoLevelcorrespondiente al nuevo valor del nivel de recogida actual.VerseUpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()Crea una función nombrada
AwardScore()que tenga el especificadorpublic. Esta función otorga la puntuación al jugador mediante el dispositivo Gestor de puntuación y lo activa.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)
Ahora tu clase
score_managerdebería tener el siguiente aspecto: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 := trueAhora que ya tienes creada la clase
score_manager, crea un constructor para la clase que inicialice las variables del jugador del juego. Ten en cuenta que debes hacer casting de tipo de la referencia del jugador deagentaplayerpara obtener referencias a la IU del jugador.VerseMakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}Tu archivo score_manager debería tener ahora el siguiente aspecto:
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]]}
Cómo actualizar la puntuación y la IU en el bucle de juego
Sigue estos pasos para crear y actualizar tu IU durante el juego en el archivo game_coordinator_device.verse:
Añade las siguientes propiedades a la clase
game_coordinator_device:Una variable
score_managernombradaScoreManagerque tenga el especificadorprivate. Esta instancia gestiona la puntuación del jugador y la IU.var ScoreManager<private> : score_manager = score_manager{}Un dispositivo editable
score_manager_deviceque puedes establecer en el dispositivo Gestor de puntuación del nivel. Este es el dispositivo que utilizará la clasescore_manager.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}Una matriz de enteros editable nombrada
PointsForPickupLevelque tiene el especificadorpublic, para definir los puntos que el jugador puede conseguir en cada nivel de recogida.@editable # Asigna cuántos puntos vale una recogida en función de su nivel de recogida. PointsForPickupLevel<public> : []int = array{1, 2, 3}
En la función
StartGame, inicializa la variable del gestor de puntuación llamando al constructorMakeScoreManager()con una referencia al jugador y al dispositivo Gestor de puntuación, y genera la IU para que la vea el jugador.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...")En la función del bucle del juego
PickupDeliveryLoop(), actualiza la IU siempre que cambie el nivel de recogida y el jugador termine una recogida o una 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.Ahora, cuando termine la cuenta atrás, concede al jugador su puntuación. En
HandleCountdownEnd(), llama aScoreManager.AwardScore().HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)Tu archivo game_coordinator_device.verse debería tener ahora el siguiente aspecto:
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 }