Podrías usar el dispositivo de cronómetro para que ejecute una cuenta regresiva, pero crear tu propio cronómetro de cuenta regresiva en Verse es una forma de personalizar su comportamiento para que se ajuste exactamente a tus necesidades.
En este tutorial, aprenderás a crear tu propio temporizador con Verse, y a utilizar una llamada cuando se añada tiempo a la cuenta atrás. Empieza de forma sencilla, y encontrarás formas de mejorarlo, proyecto a proyecto.
Funciones usadas del lenguaje Verse
if: La expresión
ifprueba condiciones y accede a valores que podrían fallar.block: en este ejemplo, se usa la expresión de
bloquepara inicializar la IU cuando se crea el temporizador de cuenta regresiva.loop: la expresión
loopactualiza la IU y finaliza cuando la cuenta regresiva llega a cero.spawn: Una expresión
spawncomienza una expresión asíncrona en cualquier contexto.mensaje: el tipo message (mensaje) significa que el texto puede localizarse, y la cadena que utilizas para inicializar una variable de mensaje es el texto y el idioma predeterminados del mensaje.
clase: en este ejemplo, se crea una clase) de Verse que administra y muestra la cuenta regresiva.
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 especificador de acceso para establecer el nivel de acceso de tu código.
API de Verse utilizadas
Dormir: con la API de
Sleep(), puedes elegir el período entre actualizaciones de IU.Eventos: en Verse, puedes crear tus propios eventos y agregar funciones personalizadas cuando se producen.
IU de Verse: Crea una IU personalizada en el juego para mostrar información acerca del jugador y el juego.
Instrucciones
Realiza estos pasos para aprender cómo crear tu propio temporizador personalizado. La secuencia de comandos completa se incluye al final de esta guía como referencia.
Configuración del nivel
En este ejemplo, se utilizan la utilería y los dispositivos que aparecen a continuación.
1 x dispositivo de botón: Cuando el jugador interactúa con el dispositivo, se agrega más tiempo a la cuenta regresiva.
1 x dispositivo de terminar partida: cuando termina la cuenta regresiva, este dispositivo hace que la partida termine.
Realiza estos pasos para configurar el nivel:
Añade un dispositivo de botón y un dispositivo de terminar partida a tu nivel.
Crea un nuevo dispositivo de Verse y asígnale el nombre
countdown_timer_examplecon el explorador de Verse. Consulta Cómo crear tu propio dispositivo con Verse para conocer los pasos.Agrega una referencia editable al dispositivo de Botón en
countdown_timer_exampley asígnale elnombre AddMoreTimeButton. Consulta Personaliza las propiedades del dispositivo para obtener información.Versecountdown_timer_example := class(creative_device): @editable AddMoreTimeButton : button_device = button_device{}Agrega una referencia editable al dispositivo de terminar partida en
countdown_timer_exampley asígnale 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 > Crear código de Verse para actualizar tu dispositivo en el nivel y ver los cambios en el panel de detalles correspondiente.
Comenzando la cuenta regresiva
En este ejemplo, crearás una clase de Verse que dibuje su propia IU y administre su propia cuenta regresiva.
Sigue los pasos a continuación para crear el temporizador personalizado:
Crea un archivo vacío de Verse y asígnale el nombre countdown_timer.verse.
Agrega 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 asígnale el nombre
countdown_timer;luego, agrega las siguientes variables:Una variable float denominada
RemainingTimee inicializada en0.0.Versevar RemainingTime : float = 0.0Una variable de widget de lienzo denominada
Canvas.Versevar Canvas : canvas = canvas{}Un widget de texto denominado
RemainingTimeWidgetcon un color de texto blanco predeterminado.VerseRemainingTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White}Una función que devuelve un mensaje denominado
RemainingTimeTextque 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 enfalso.VerseMaybePlayerUI : ?player_ui = false
Tu clase debería verse de la siguiente manera:
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}"Agrega una expresión
blockpara crear la IU donde el tiempo aparece en la parte media superior de la pantalla. Una expresión de bloque en una definición de clase se ejecuta solo cuando la clase se instancia, por lo que podemos crear la IU una vez en esta expresión debloque.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}Agrega 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 de jugador y el tiempo de cuenta regresiva inicial. Llama aStartCountdown()enOnBegin()para que la cuenta regresiva aparezca tan pronto como se inicia 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 realizas una prueba de juego ahora, la IU no mostrará el tiempo restante cuando se inicia la cuenta regresiva, por lo tanto, en countdown_timer.verse, crea una función con el nombre
UpdateUI()que actualice el valor actual de la cuenta regresiva en la IU. LlamarUpdateUI()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 regresiva inicial aparece en la IU, pero el valor no se actualiza cada segundo. Para hacer esto:
Agrega la variable float
TimerTickPeriodpara representar con qué frecuencia en segundos se actualiza la IU. En este ejemplo, se usa un segundo.VerseTimerTickPeriod : float = 1.0 # The timer "precision": how often, in seconds, it ticks.Crea una función con el nombre
RunCountdown()que tenga el especificador suspends, y llámala desdeStartCountdown(). Haz queRunCountdown()espere aTimerTickPeriodantes de actualizar la IU y repite esto en bucle. Establece el bucle para que finalice y para que la cuenta regresiva 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 realizas una prueba de juego, la cuenta regresiva tiene que iniciarse en 30 y actualizarse cada segundo hasta que el temporizador llegue a 0 y la cuenta regresiva desaparezca de la IU.
Cómo añadir más tiempo
Con este temporizador de cuenta regresiva, deberás incorporar una forma personalizada de agregar más tiempo y de llamar al tiempo agregado. En este ejemplo, se muestra cómo agregar más tiempo a la cuenta regresiva y mostrar el tiempo agregado cuando el jugador interactúa con el dispositivo Botón.
Sigue estos pasos para agregar más tiempo a la cuenta regresiva cuando el jugador interactúa con el dispositivo Botón:
En countdown_timer.verse, crea una nueva función denominada
AddRemainingTime()que actualice la variableRemainingTimecon el valor transferido a la función en el parámetro float denominadoTiempoy que, posteriormente, actualice la IU para mostrar el tiempo restante nuevo.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, suscribe al
InteractedWithEventdel dispositivo Botón y llamaAddRemainingTime()cuando el jugador interactúa con el dispositivo 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{}Agrega un widget a la clase
countdown_timerpara saber cuánto tiempo se suma a la cuenta regresiva cuando el jugador interactúa con el botón.VerseAddedTimeWidget : text_block = text_block{DefaultTextColor := NamedColors.White} AddedTimeText<localizes>(AddedTime : int) : message = " +{AddedTime}!"Usa los mismos valores de posicionamiento que el widget RemainingTime para el widget AddedTimeWidget nuevo, pero cambia los siguientes valores para que el tiempo de la llamada se muestre en la parte superior derecha del temporizador de cuenta regresiva:
Para AddedTimeWidget, establece el margen izquierdo de los desplazamientos en
50.0.Para RemainingTimeWidget, establece el margen superior 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 función nueva llamada
AddedTimeCallout()que actualice el valor en AddedTimeWidget y muestre la llamada dos segundos antes de ocultar otra vez 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 realizas una prueba de juego, la cuenta regresiva tiene que iniciarse en 30 y actualizarse cada segundo hasta que el temporizador llegue a 0 y la cuenta regresiva desaparezca de la IU. Cuando el jugador interactúa con el botón, se agregan 20 segundos a la cuenta regresiva y aparece una llamada durante dos segundos que muestra el tiempo adicional agregado.
Cómo indicar el fin del temporizador de cuenta regresiva
Anteriormente en este tutorial, usaste el dispositivo Botón InteractedWithEvent para saber cuándo el jugador presionó el botón y agregó más tiempo al temporizador de cuenta regresiva. Pero también puedes crear eventos personalizados propios que otros pueden usar para saber cuando sucede algo en el código.
En este ejemplo, se muestra cómo usar el siguiente comportamiento de eventos personalizados:
Signal():esta función permite que cualquier usuario que espera el evento sepa que el evento ocurrió.Await():esta función asíncrona bloquea la ejecución de su contexto envolvente hasta que se indique el evento.
En este ejemplo, agregarás un evento al temporizador de cuenta regresiva para indicar el momento en que finaliza la cuenta regresiva a fin de poder activar el dispositivo de terminar partida.
Sigue estos pasos para agregar un evento para la finalización de la cuenta regresiva:
Agrega 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 u objeto instancia. Este es el motivo por el cual el tipo esevent(), y por el cual es necesario inicializar la constanteCountdownEndedEventconevent(){}para imitar el modo en que se instancia una clase.Actualiza
RunCountdown()para indicar el eventoCountdownEndedEventy permitir que otro código sepa que la cuenta regresiva finalizó antes de interrumpir el 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 con elCountdownTimery después activa el dispositivo de terminar partida (porque sabemos que la cuenta regresiva finalizó cuando ocurre 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 realizas una prueba de juego, la cuenta regresiva tiene que iniciarse en 30 y actualizarse cada segundo hasta que el temporizador llegue a 0. Tan pronto como finaliza la cuenta regresiva, esta desaparece de la IU y el juego termina. Cuando el jugador interactúa con el botón, se agregan 20 segundos a la cuenta regresiva y aparece una llamada durante dos segundos que muestra el tiempo agregado.
Cómo preparar la clase que se usará con otro código
Ahora creaste tu propia clase de temporizador de cuenta regresiva personalizada y usaste un dispositivo creado con Verse para instanciar y controlar el temporizador.
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 temporizador de cuenta regresiva debe poder crear y cambiar su IU. En Verse, puedes usar especificador de acceso para establecer el nivel de acceso de tu código.
Agrega el especificador public a todos los identificadores a los que deseas que otros accedan, porque public (público) significa que el identificador es de acceso universal. En este ejemplo, se utilizan todos los siguientes en el dispositivo countdown_timer_example y, por lo tanto, deben tener acceso público:
CountdownEndedEvent<public> : event() = event(){}StartCountdown()<public>: void =AddRemainingTime(Time<public>: float) : void =
Agrega el especificador private a todos los identificadores a los que no deseas que otros accedan, porque private significa que solo se puede acceder al identificador en el ámbito envolvente inmediato (que, en este caso, es la clase countdown_timer).
En este ejemplo, deben tener acceso privado los siguientes identificadores:
RemainingTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeWidget<private> : text_block = text_block{DefaultTextColor := NamedColors.White}AddedTimeText(AddedTime<localizes><private>: int) : message = "{AddedTime}+!"RemainingTimeText(CurrentRemainingTime<localizes><private>: int) : message = "{CurrentRemainingTime}"var Canvas<private> : canvas = canvas{}TimerTickPeriod<private> : float = 1.0RunCountdown()<private> <suspends> : void =<private>AddedTimeCallout(Time : float)<suspends> : void =UpdateUI()<private>: void =
Es una buena idea agrupar el código por acceso. Se recomienda ordenar el código de mayor a menor, según la cantidad de acceso:
público
Interno
protegido
privado
Puedes usar un constructor para establecer } valores iniciales para una nueva clase instancia 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 establecidas en el constructor no tienen que tener acceso público, pero no pueden tener acceso privado si están establecidas en un constructor. Puedes usar el especificador internal para estas variables, lo que significa que solo es posible acceder al identificador en el módulo envolvente inmediato existente.
MaybePlayerUI<internal> : ?player_ui = falsevar RemainingTime<internal> : float = 0.0
Código completo
El siguiente es el código completo para crear un temporizador de cuenta regresiva personalizado.
En este ejemplo, se crearon dos archivos de Verse.
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, has aprendido cómo crear un temporizador de cuenta regresiva personalizado.
Con lo que aprendiste, intenta hacer lo siguiente:
Cambia la velocidad de tics del temporizador y agrega un evento para cada tic.
Agrega una pausa, reanuda y reinicia la funcionalidad en el temporizador.