Podrías utilizar el cronómetro que ejecuta un cronómetro de cuenta atrás, pero crear tu propio cronómetro de cuenta atrás en Verse es una forma de personalizar su comportamiento para que se ajuste exactamente a lo que necesitas.
Este tutorial te enseñará a crear tu propio cronómetro con Verse, y a utilizar una llamada cuando se añada tiempo a la cuenta atrás. Empieza con algo sencillo y encontrarás formas de mejorarlo, proyecto a proyecto.
Funciones del lenguaje Verse utilizadas
if: la expresión
ifcomprueba condiciones y accede a valores que podrían fallar.block: este ejemplo utiliza la expresión
blockpara inicializar la IU cuando se crea el cronómetro de cuenta atrás.loop: la expresión
loopactualiza la IU y finaliza cuando la cuenta atrás llega a cero.spawn: una expresión
spawninicia una expresión asíncrona en cualquier contexto.message: el tipo `message` significa que el texto se puede localizar, y la cadena que utilices para inicializar una variable `message` es el texto y el idioma predeterminado para el mensaje.
class: este ejemplo crea una clase de Verse que gestiona y muestra la cuenta atrás.
constructor: un constructor es una función especial que crea una instancia de la clase a la que está asociado.
Especificadores de acceso: puedes utilizar especificadores de acceso para establecer el nivel de acceso de tu código.
API de Verse utilizadas
Sleep: con la API
Sleep(), puedes elegir el periodo entre actualizaciones de la IU.Eventos: puedes crear tus propios eventos en Verse y añadir funciones personalizadas cuando se produzcan.
IU de Verse: crea una IU personalizada en el juego para mostrar información sobre el jugador y el juego.
Instrucciones
Sigue estos pasos para aprender a crear tu propio cronómetro personalizado. La secuencia de comandos completa se incluye al final de esta guía como referencia.
Cómo configurar el nivel
Este ejemplo utiliza los siguientes elementos y dispositivos.
Un dispositivo de botón: cuando el jugador interactúa con el dispositivo, se añade más tiempo a la cuenta atrás.
Un dispositivo de fin de partida: cuando finaliza la cuenta atrás, este dispositivo hace que el juego termine.
Sigue estos pasos para configurar tu nivel:
Añade un dispositivo de botón y un dispositivo de fin de partida a tu nivel.
Crea un nuevo dispositivo de Verse y dale el nombre
countdown_timer_exampleusando el explorador de Verse. Consulta Cómo crear tu propio dispositivo con Verse para ver los pasos.Añade una referencia editable al dispositivo de botón en
countdown_timer_exampley dale el nombreAddMoreTimeButton.. Consulta Cómo personalizar las propiedades de un dispositivo para ver los pasos.Versecountdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{}Añade una referencia editable al dispositivo de fin de partida en
countdown_timer_exampley dale el nombreEndGame.Versecountdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}Guarda tu archivo de Verse. En el menú principal de UEFN elige Verse > Compilar código de Verse para actualizar tu dispositivo en el nivel y ver los cambios en el panel Detalles del dispositivo.
Inicio de la cuenta atrás
En este ejemplo, crearás una clase de Verse que dibuje su propia interfaz de usuario y gestione su propia cuenta atrás.
Sigue estos pasos para aprender a crear tu propio cronómetro personalizado:
Crea un archivo de Verse vacío y dale el nombre countdown_timer.verse.
Añade los siguientes módulos de Verse en la parte superior del archivo:
Verseusing { /UnrealEngine.com/Temporary/UI } using { /UnrealEngine.com/Temporary/SpatialMath } using { /Fortnite.com/UI } using { /Verse.org/Colors } using { /Verse.org/Simulation }Crea una clase y dale el nombre
countdown_timer. Luego añade las siguientes variables:Una variable flotante denominada
RemainingTimee inicializada a0.0.Versevar RemainingTime : float = 0.0Una variable del widget de lienzo denominada
Canvas.Versevar Canvas : canvas = canvas{}Un widget de texto denominado
RemainingTimeWidgetcon un color de texto predeterminado blanco.VerseRemainingTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White}Una función que devuelve un mensaje denominado
RemainingTimeTexty que toma un parámetro entero para mostrar el valor representado porRemainingTime.VerseRemainingTimeText<localizes>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"Una IU de jugador opcional denominada
MaybePlayerUIe inicializada afalse.VerseMaybePlayerUI : ?player_ui = false
Tu clase debería tener el siguiente aspecto:
Versecountdown_timer := class: MaybePlayerUI : ?player_ui = false var RemainingTime : float = 0.0 var Canvas : canvas = canvas{} RemainingTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White} RemainingTimeText<localizes>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"Añade una expresión
blockpara crear la IU en la que la hora aparezca en la parte superior central de la pantalla. Una expresión block en la definición de una clase se ejecuta solo cuando se instancia la clase, por lo que podemos crear la IU una vez en esta expresiónblock.Versecountdown_timer := class: block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors: Minimum := vector2{X := 0.5, Y := 0.05} Maximum := vector2{X := 0.5, Y := 0.05} Alignment := vector2{X := 0.5, Y := 0.0} Offsets := margin{Top := 0.0, Left := 0.0, Bottom := 0.0, Right := 0.0}Añade la función
StartCountdown()para mostrar la IU.VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas)En countdown_timer_example.verse, crea una instancia de
countdown_timercon una referencia a la IU del jugador y el tiempo inicial de la cuenta atrás. Llama aStartCountdown()enOnBegin()para que la cuenta atrás aparezca en cuanto empiece el juego.Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } countdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}Si pruebas ahora, la IU no mostrará el tiempo restante cuando empiece la cuenta atrás, así que crea en countdown_timer.verse una función y dale el nombre
UpdateUI()para que actualice el valor actual de la cuenta atrás en la IU. Llama aUpdateUI()enStartCountdown().VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) # Update the UI when we start the timer to see the initial RemainingTime on screen UpdateUI() UpdateUI() : void =Ahora, la cuenta atrás inicial aparece en la interfaz de usuario, pero el valor no se actualiza cada segundo. Para ello:
Añade la variable flotante
TimerTickPeriodpara representar la frecuencia en segundos con la que se actualiza la IU. Este ejemplo utiliza un segundo.VerseTimerTickPeriod : float = 1.0 # The timer "precision": how often, in seconds, it ticks.Crea una función y dale el nombre
RunCountdown()para que tenga el especificador suspends y llámala desdeStartCountdown(). Haz queRunCountdown()espere elTimerTickPeriodantes de actualizar la IU y repite esto en bucle. Establece que el bucle termine y que la cuenta atrás desaparezca de la IU cuando llegue a0.0.VerseStartCountdown() : void = Print("Starting countdown") if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) # Update the UI when we start the timer to see the initial RemainingTime on screen UpdateUI() spawn:
Cuando hagas la prueba, deberías ver que la cuenta atrás empieza en 30 y se actualiza cada segundo hasta que el cronómetro llega a 0 y la cuenta atrás desaparece de la interfaz de usuario.
Cómo añadir más tiempo
Con este cronómetro de cuenta atrás, quieres añadir una forma personalizada de agregar más tiempo y llamar al tiempo añadido. Este ejemplo muestra cómo añadir más tiempo a la cuenta atrás y mostrar el tiempo añadido cuando el jugador interactúa con el dispositivo de botón.
Sigue estos pasos para añadir más tiempo al cronómetro de cuenta atrás cuando el jugador interactúe con el dispositivo Botón:
En countdown_timer.verse, crea una nueva función denominada
AddRemainingTime()que actualice la variableRemainingTimecon el valor pasado a la función en el parámetro flotante denominadoTime, y luego actualiza la IU para mostrar el nuevo tiempo restante.VerseAddRemainingTime(Time : float) : void = set RemainingTime += Time # Immediately update the UI for better player feedback when time is added. UpdateUI()En countdown_timer_example.Verse, suscríbete al
InteractedWithEventdel dispositivo de botón y llama aAddRemainingTime()cuando el jugador interactúe con el dispositivo de botón.Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } countdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{} @editable EndGame : end_game_device = end_game_device{}Añade un widget a la clase
countdown_timerque indique cuánto tiempo se añade a la cuenta atrás cuando el jugador interactúa con el botón.VerseAddedTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White} AddedTimeText<localizes>(AddedTime : int) : message = " +{AddedTime}!"Utiliza los mismos valores de posicionamiento que en el widget RemainingTime para el nuevo AddedTimeWidget, pero cambia los siguientes valores para que el tiempo de llamada se muestre en la parte superior derecha del cronómetro de cuenta atrás:
Para AddedTimeWidget, establece el margen izquierdo (Left) en Offsets en
50.0.Para RemainingTimeWidget, establece el margen superior (Top) en Offsets en
25.0.Versecountdown_timer := class: <# This block runs for each instance of the countdown_timer class. We can setup the canvas once here. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors: Minimum := vector2{X := 0.5, Y := 0.05} Maximum := vector2{X := 0.5, Y := 0.05}
Crea una nueva función con el nombre
AddedTimeCallout()que actualice el valor de AddedTimeWidget y muestre la llamada durante dos segundos antes de volver a ocultar el widget. Llama aAddedTimeCallout()enAddRemainingTime().VerseAddRemainingTime(Time : float) : void = set RemainingTime += Time # Immediately update the UI for better player feedback when time is added. UpdateUI() # Fire a simple callout to show the time being added. spawn: AddedTimeCallout(Time)Cuando hagas la prueba, deberías ver que la cuenta atrás empieza en 30 y se actualiza cada segundo hasta que el cronómetro llega a 0 y la cuenta atrás desaparece de la interfaz de usuario. Cuando el jugador interactúa con el botón, se añaden veinte segundos a la cuenta atrás y aparece un aviso durante dos segundos que muestra el tiempo adicional añadido.
Cómo señalar el final del cronómetro de cuenta atrás
Anteriormente en este tutorial, utilizaste la función InteractedWithEvent de un dispositivo de botón para saber cuándo el jugador pulsaba el botón y añadir más tiempo al cronómetro de cuenta atrás. Pero también puedes crear tus propios eventos personalizados que otros puedan utilizar para saber cuándo ocurre algo en tu código.
Este ejemplo muestra cómo utilizar el siguiente comportamiento de los eventos personalizados:
Signal(): esta función permite que cualquiera que esté esperando el evento sepa que este se ha producido.Await(): esta función asíncrona bloquea la ejecución de su contexto envolvente hasta que se señala el evento.
En este ejemplo, añadirás un evento al cronómetro de cuenta atrás para señalar cuándo finaliza la cuenta atrás y poder activar el dispositivo Fin de partida.
Sigue estos pasos para añadir un evento para el final de la cuenta atrás.
Añade un campo de evento denominado
CountdownEndedEventa la clasecountdown_timer:VerseCountdownEndedEvent : event() = event(){}event()es un tipo paramétrico, lo que significa que devuelve una clase o interfaz en lugar de un valor o una instancia de objeto. Por eso el tipo esevent()y por eso tienes que inicializar tu constanteCountdownEndedEventconevent(){}para imitar la forma de instanciar una clase.Actualiza
RunCountdown()para señalar elCountdownEndedEventpara que otro código sepa que la cuenta atrás ha terminado antes de salir del bucle.VerseRunCountdown()<suspends> : void = # We loop with the TimerTickPeriod. # The UI is also updated each time. loop: Sleep(TimerTickPeriod) set RemainingTime -= TimerTickPeriod UpdateUI() # Timer End if (RemainingTime <= 0.0):En countdown_timer_example.verse, espera en el
CountdownEndedEventasociado alCountdownTimer, luego activa el dispositivo de fin de partida porque sabemos que la cuenta atrás terminó cuando se produce el evento.VerseOnBegin<override()<suspends> : void = AddMoreTimeButton.InteractedWithEvent.Subscribe(OnButtonInteractedWith) if: FirstPlayer := Self.GetPlayspace().GetPlayers()[0] PlayerUI := GetPlayerUI[player[FirstPlayer]] then: set CountdownTimer = countdown_timer{MaybePlayerUI := option{PlayerUI}, RemainingTime := InitialCountdownTime} CountdownTimer.StartCountdown() CountdownTimer.CountdownEndedEvent.Await()Cuando hagas la prueba, deberías ver que la cuenta atrás empieza en 30 y se actualiza cada segundo hasta que el cronómetro llega a 0. En cuanto termina la cuenta atrás, esta desaparece de la IU y el juego termina. Cuando el jugador interactúa con el botón, se añaden veinte segundos a la cuenta atrás y aparece un aviso durante dos segundos que muestra el tiempo añadido.
Cómo preparar tu clase para que la utilice otro código
Ya has creado tu propia clase de cronómetro de cuenta atrás personalizado y has utilizado un dispositivo de Verse para instanciar y controlar el cronómetro.
Cuando creas tus propias clases personalizadas (y, en realidad, cualquier código), es importante especificar quién puede acceder a lo que creas. Por ejemplo, solo el cronómetro de cuenta atrás debería poder crear y cambiar su IU. En Verse, puedes utilizar especificadores de acceso para establecer el nivel de acceso de tu código.
Añade el especificador public a cualquier identificador al que quieras que otros accedan (public significa que el identificador es de acceso universal). En este ejemplo, todos los siguientes se utilizan en el dispositivo countdown_timer_example y, por tanto, deben tener acceso público:
CountdownEndedEvent<public> : event() = event(){}StartCountdown<public>() : void =AddRemainingTime<public>(Time : float) : void =
Añade el especificador private a cualquier identificador al que no quieras que accedan otros (private significa que solo se puede acceder al identificador en el ámbito actual) inmediatamente adyacentes (que en este caso es la clase countdown_timer).
En este ejemplo, lo siguiente debe tener acceso privado:
RemainingTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeText<localizes><private>(AddedTime : int) : message = " +{AddedTime}!"RemainingTimeText<localizes><private>(CurrentRemainingTime : int) : message = "{CurrentRemainingTime}"var Canvas<private> : canvas = canvas{}TimerTickPeriod<private> : float = 1.0RunCountdown<private>()<suspends> : void =AddedTimeCallout<private>(Time : float)<suspends> : void =UpdateUI<private>() : void =
Es buena idea agrupar tu código por acceso. Recomendamos ordenar tu código de mayor a menor cantidad de acceso:
público
Interno
protegido
privado
Puedes utilizar un constructor para establecer los valores iniciales de una nueva instancia de clase sin exponer las variables de una clase. Un constructor es una función especial que crea una instancia de la clase a la que está asociado.
Crea un constructor para la clase countdown_timer que actualice las variables RemainingTime y MaybePlayerUI.
MakeCountdownTimer<constructor><public>(MaxTime : float, InPlayer : agent) := countdown_timer:
RemainingTime := MaxTime
MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
Las variables RemainingTime y MaybePlayerUI que se establecen en el constructor no deberían tener acceso público, pero no pueden tener acceso privado si se establecen en un constructor. Puedes utilizar el especificador internal para estas variables, lo que significa que solo se puede acceder al identificador en el módulo actual, inmediatamente adyacente.
MaybePlayerUI<internal> : ?player_ui = falsevar RemainingTime<internal> : float = 0.0
Código completo
El código siguiente es el código completo para crear un cronómetro de cuenta atrás personalizado.
Hay dos archivos de Verse creados en este ejemplo:
countdown_timer.verse
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Simulation }
using { /Fortnite.com/UI }
MakeCountdownTimer<constructor><public>(MaxTime : float, InPlayer : agent) := countdown_timer:
RemainingTime := MaxTime
MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
countdown_timer_example.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
countdown_timer_example := class(creative_device):
@editable
AddMoreTimeButton : button_device = button_device{}
@editable
Por tu cuenta
Al completar esta guía, habrás aprendido a crear un cronómetro de cuenta atrás personalizado.
Con lo que has aprendido, intenta hacer lo siguiente:
Cambia la velocidad del tic del cronómetro y añade un evento para cada tic.
Añade al cronómetro las funciones de pausa, reanudación y reinicio.