Al completar este paso del tutorial Contrarreloj: Persecución de pizza, aprenderás a gestionar el puntaje cuando un jugador recoge objetos y los entrega, y a actualizar la IU para mostrar las puntuaciones. Para obtener más información sobre cómo crear una IU en el juego en Verse, consulta Cómo crear una IU en el juego.
El administrador de puntaje rastreará y mostrará lo siguiente:
Puntos totales: representa los puntos totales que el jugador obtuvo en el juego.
Puntos pendientes: representa los puntos que el jugador acumuló para el conjunto actual de recolecciones.
Nivel de recolección: representa el nivel de recolección actual.
Cómo crear la IU
Sigue estos pasos a fin de crear la IU del administrador de puntaje en Verse:
Crea un nuevo archivo de Verse vacío y asígnale el nombre score_manager.verse.
Crea una nueva clase llamada
score_managery añade los siguientes campos a la clase:Un
agente opcionaldenominadoMaybePlayerpara almacenar una referencia al jugador.MaybePlayer<internal> : ?agent = falseUna
player_uiopcional denominadaMaybePlayerUIpara almacenar una referencia a la IU del jugador.MaybePlayerUI<internal> : ?player_ui = falseUn
score_manager_devicepara almacenar una referencia del dispositivo administrador de puntaje en torno al cual se construyó esta clase. (Ten en cuenta que esta no es una referencia editable porque debe conectarse al dispositivo creado con Versegame_coordinator_device.ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}Una variable entera denominada
TotalGameScoreque representa todos los puntos que el jugador obtuvo en todo el juego.var TotalGameScore<private> : int = 0Una variable entera denominada
PendingScoreque representa los puntos que el jugador acumuló actualmente para este conjunto de recolecciones.var PendingScore<private> : int = 0Una variable entera denominada
PickupLevelque representa el nivel de recolección actual.var PickupLevel<private> : int = 0
Ahora, tu definición de clase score_manager debería verse de la siguiente manera:
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 IU cuando se crea la clase por primera vez. Para hacer esto, puedes añadir una expresión
blocka la definición de la clase, que se ejecutará cada vez que crees una instancia de la clase. Añade las siguientes variables para generar la IU:Una variable
canvasdenominadaCanvasque tiene el especificadorinternal, para guardar el widget de lienzo personalizado.var Canvas<internal> : canvas = canvas{}Un
text_blockdenominadoTotalGameScoreWidgetque tiene el especificadorinternal, para almacenar el widget de texto a fin de mostrar todos los puntos que el jugador acumuló en todo el juego, según lo representado por la variableTotalGameScore. Establece en blanco el color de texto predeterminado del bloque de texto.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}Un
text_blockdenominadoPendingScoreWidgetque tiene el especificadorinternal, para almacenar el widget de texto a fin de mostrar los puntos que el jugador acumuló actualmente para este conjunto de recolecciones, según lo representado por la variablePendingScore. Establece en blanco el color de texto predeterminado del bloque de texto.PendingScoreWidget<internal> : text_block = text_block{}Un
text_blockdenominadoPickupLevelWidgetque tiene el especificadorinternal, para almacenar el widget de texto a fin de mostrar el nivel de recolección actual, representado por la variablePickupLevel. Establece en blanco el color de texto predeterminado del bloque de texto.PickupLevelWidget<internal> : text_block = text_block{}Una función que devuelve un
messagedenominadoTotalGameScoreTexty permite crear texto localizable que se puede mostrar en la IU para todos los puntos que el jugador obtuvo en el juego.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total Points: {CurrentTotalGameScore}"Una función que devuelve un
messagedenominadoPendingScoreTexty permite crear texto localizable que se puede mostrar en la IU para los puntos que el jugador acumuló actualmente para este conjunto de recolecciones.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Pending Points: {CurrentPendingScore}"Una función que devuelve un
messagedenominadoPickupLevelTexty permite crear texto localizable que se puede mostrar en la IU para el nivel de recolección actual.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Pickup Level: {CurrentPickupLevel}"Añade una expresión
blockque te permita crear el widget de canvas y colocar el texto apilado verticalmente a la izquierda de la pantalla.<# Ya que no recrearemos el lienzo durante la vida útil del administrador de puntaje, 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
Tu código para
score_managerahora debería verse de la siguiente manera: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 = "Pickup Level: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Pending Points: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : int) : message = "Total Points: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# Ya que no recrearemos el lienzo durante la duración del administrador de puntaje, 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 denominada
UpdateUI()que tenga el especificadorprivate, que actualiza el texto de la IU con los valores de puntaje más recientes y el nivel de recolección actual.UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))Crea una función llamada
AddScoreManagerToUI()que actualice la IU del jugador con la IU personalizada del administrador de puntaje.AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()Crea una función para cada valor que se muestra en la IU para que el bucle de juego pueda actualizar los valores:
Una función denominada
AddPendingScoreToTotalScore()que tiene el especificadorpublic. Esta función debería sumar la puntuación pendiente a la puntuación total del juego y restablecer el valor de la puntuación pendiente a0. Si deseas usardefer, restablecePendingScorey actualiza la IU después de que se actualiceTotalGameScore. Esto evita el uso de una variable temporal para mantener el valor dePendingScoreantes de que se restablezca.Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScoreUna función denominada
UpdatePendingScore()que tiene el especificadorpublicy un parámetro entero denominadoPointsque 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 denominada
UpdatePickupLevelque tiene el especificadorpublicy un parámetro entero denominadoLevelque es el nuevo valor para el nivel de recolección actual.VerseUpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()Crea una función llamada
AwardScore()que tenga el especificadorpublic. Esta función otorga el puntaje al jugador mediante el administrador de puntaje y activa el dispositivo.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)
Tu clase
score_managerahora debería verse de la siguiente manera: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 creaste la clase
score_manager, crea un constructor para la clase a fin de inicializar las variables de jugador del juego. Ten en cuenta que debes realizar una conversión de tipo en la referencia del jugador deagentaplayerpara obtener una referencia a la IU del jugador.VerseMakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}El archivo score_manager.verse ahora debería verse de la siguiente manera:
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 el puntaje 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_managerdenominadaScoreManagerque tiene el especificadorprivate. Esta instancia administra la puntuación y la IU del jugador.var ScoreManager<private> : score_manager = score_manager{}Un
score_manager_deviceeditable que puedes establecer en el dispositivo administrador de puntaje en el nivel. Este es el dispositivo que utilizará la clasescore_manager.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}Una matriz de enteros editable denominada
PointsForPickupLevelque tiene el especificadorpublic, para definir los puntos que el jugador puede obtener en cada nivel de recolección.@editable # Mapea cuántos puntos vale una recolección en función de su nivel de recolección. PointsForPickupLevel<public> : []int = array{1, 2, 3}
En la función
StartGame, llama al constructorMakeScoreManager()para inicializar la variable del administrador de puntaje con una referencia al jugador y al dispositivo administrador de puntaje, y genera la IU para que el jugador la vea.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 de bucle de juego
PickupDeliveryLoop(), actualiza la IU cada vez que cambie el nivel de recolección y el jugador termine de recolectar o entregar: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 regresiva, otorga la puntuación al jugador. En
HandleCountdownEnd(), llama aScoreManager.AwardScore().HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)El archivo game_coordinator_device.verse ahora debería verse de la siguiente manera:
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 }