Los faroles del tutorial de Scene Graph utilizan varios componentes creados por Verse para crear prefabricados dinámicos e interactivos. Esto es posible mediante la programación del movimiento y la interactividad en un componente creado con Verse.
Simulando movimiento simple
El prefabricado de poste de luz utiliza dos componentes diferentes para simular el movimiento del farol. Ambos están unidos a la entidad Punto de traslación, que proporciona un punto de traslación para mover el farol. En primer lugar, el componente keyframed_movement_component te permite crear animaciones a partir de fotogramas clave y luego reproducirlos para animar una entidad. Sin embargo, este componente no puede actuar solo y necesita otro contenido de código que proporcione los fotogramas clave e inicie la animación. Aquí es donde entra en juego el componente simple_movement_component personalizado. Esta secuencia de comandos se reutiliza en todo el proyecto para controlar cómo se mueven los distintos objetos del juego en la escena.
Para obtener más información sobre el uso de animaciones para mover objetos, consulta Cómo animar el movimiento de los elementos.
Echemos un vistazo más de cerca al simple_movement_component. Abre la secuencia de comandos SimpleMovementComponent.verse desde el explorador de Verse en Visual Studio Code para empezar.
Las animaciones utilizan diferentes modos de reproducción para definir lo que debe hacer la animación cuando se completa. Se definen en la parte superior del archivo, en la enum movement_mode:
Una toma - El objeto deja de moverse cuando termina la animación.
Loop - El objeto reinicia la animación desde el principio cuando llega al final.
Ping-pong: el objeto reproduce la animación a la inversa, yendo y viniendo desde el principio hasta el final.
movement_mode<public> := enum:
OneShot
Loop
PingPongLa clase basic_movement_component también define las variables necesarias para construir animaciones. Cada uno de ellos tiene el atributo @editable para que puedas editarlos desde el esquematizador:
Fotogramas clave: matriz dekeyframed_movement_deltautilizada para construir la animación. Cada una de estas pistas sigue el cambio en la transformación en este fotograma clave concreto, la duración del fotograma clave y el tipo de aceleración de movimiento utilizado.AutoPlay: variablelógicaque dicta si la entidad debe animarse cuando comienza la simulación.MovementMode: el comportamiento de movimiento que exhibe la entidad.
# A Verse-authored component that can be added to entities
basic_movement_component<public> := class<final_super>(component):
@editable
var Keyframes<public>: []keyframed_movement_delta = array{}
@editable
var AutoPlay: logic = true
El código de OnSimulate() comienza a ejecutarse siempre que el componente se añade a la escena y cuando comienza el juego. Aquí, el código utiliza primero una breve llamada a Sleep() para asegurarse de que todas las entidades y componentes se inicializan correctamente antes de continuar. A continuación, en una expresión if, comprueba si la entidad tiene un componente keyframed_movement_component.
Si es así, llama a la función InitializeKeyFramedMovementComponent() para establecer el componente con los valores adecuados. ¿Qué ocurre si la entidad no tiene keyframed_movement_component? En ese caso, puedes crear uno dinámicamente en tiempo de ejecución y añadirlo a la entidad mediante la función AddComponents(). De este modo te aseguras de que tu entidad esté configurada correctamente cuando empiece la partida.
OnSimulate<override>()<suspends>:void =
Sleep (0.1)
if:
KeyframedMovementComponent := Entity.GetComponent[keyframed_movement_component]
then:
InitializeKeyframedMovementComponent(KeyframedMovementComponent)
else:
NewKeyFramedMovementComponent := keyframed_movement_component { Entity := Entity }
Entity.AddComponents of array { NewKeyFramedMovementComponent }
InitializeKeyframedMovementComponent(NewKeyFramedMovementComponent)La función InitializeKeyframedMovementComponent() establece el componente de movimiento de fotogramas clave con valores basados en los que asignas en el editor. En primer lugar, crea una nueva variable keyframed_movement_playback_mode para determinar el modo de reproducción utilizado durante esta animación. Se inicializa con el valor oneshot_keyframed_movement_playback_mode, lo que significa que la animación se reproducirá solo una vez.
InitializeKeyframedMovementComponent(InKeyframedMovementComponent:keyframed_movement_component):void =
var PlaybackMode:keyframed_movement_playback_mode = oneshot_keyframed_movement_playback_mode{}A continuación, utiliza una declaración case para establecer el modo de reproducción en función del valor de MovementMode establecido en el editor. Cada valor de la enum MovementMode corresponde a un modo de reproducción diferente definido en el módulo SceneGraph/KeyframedMovement.
case (MovementMode):
movement_mode.OneShot =>
set PlaybackMode = oneshot_keyframed_movement_playback_mode{}
movement_mode.Loop =>
set PlaybackMode = loop_keyframed_movement_playback_mode{}
movement_mode.PingPong =>
set PlaybackMode = pingpong_keyframed_movement_playback_mode{}Por último, la función establece los fotogramas clave y el modo de movimiento en el componente de movimiento con fotogramas clave, y la animación está lista para reproducirse. Si la variable Reproducción automática se establece en true, la animación comienza inmediatamente al llamar a la función Play() del componente de movimiento con fotogramas clave.
InKeyframedMovementComponent.SetKeyframes(Keyframes, PlaybackMode)
if:
AutoPlay?
then:
InKeyframedMovementComponent.Play()De vuelta en el editor, el simple_movement_component se añade a la entidad Pivot y se establece con los siguientes valores. Ahora, cuando empiece el juego, el farol empezará a balancearse de un lado a otro.
Secuencia de comandos completa
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph/KeyframedMovement }
movement_mode<public> := enum:
OneShot
Loop
Interactuar con el farol
El farol puede balancearse adelante y atrás, pero necesitarás otro contenido para que tu jugador pueda interactuar con él. Esto se hace añadiendo un componente Intratable a la entidad Farol y un componente personalizado de Verse farol_interaction_component al poste de luz que te permite encender y apagar el farol.
Abre la secuencia de comandos LanternInteractionComponent.verse desde el explorador de Verse. Esta secuencia de comandos comienza importando el módulo LightPost definido en Assets.digest.verse. Aquí es donde se almacenan todos los recursos relacionados con el poste de luz, como el prefabricado. También importa el módulo LightPost.Materials para acceder a los materiales y mallas del poste de luz y del farol.
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
LightPost := module:
Materials<public> := module:
La clase lantern_interaction_component comienza definiendo una variable llamada MaterialInstance, que se inicializa como LightPost.Materials.MI_Lantern_01. Esta es la instancia de material que contiene todas las variables relacionadas con el material del farol.
lantern_interaction_component<public> := class<final_super>(component):
var MaterialInstance:LightPost.Materials.MI_Lantern_01 = LightPost.Materials.MI_Lantern_01{}En OnBeginSimulation(), la secuencia de comandos empieza por encontrar cada componente en sus entidades descendientes con un interactable_component adjunto. Debido a que lantern_interaction_component está unida al poste de luz, esto devolverá el componente interactable_component de la entidad Linterna, ya que es descendiente del poste de luz.
OnBeginSimulation<override>():void =
(super:)OnBeginSimulation()
InteractabeleComponents := Entity.FindDescendantComponents(interactable_component)A continuación, en una expresión for, la secuencia de comandos itera por cada componente interactivo encontrado y suscribe su SucceededEvent a la función OnInteractFinished() que se define más adelante en este archivo. Ahora, cuando un jugador termine de interactuar con el farol, se activará OnInteractFinished().
InteractabeleComponents := Entity.FindDescendantComponents(interactable_component)
for (InteractableComponent : InteractabeleComponents):
InteractableComponent.SucceededEvent.Subscribe(OnInteractFinished)A continuación, la función OnBeginSimulation() llama de nuevo a FindDescendantComponents para encontrar cada entidad que tenga un componente LightPost.SM_Lightpost_Lantern_01 adjunto. Este es el componente de la malla unido a la linterna. A continuación, establece el componente de la malla en la MaterialInstance definida anteriormente, garantizando que la malla del farol se inicialice correctamente.
MeshComponents := Entity.FindDescendantComponents(LightPost.SM_Lightpost_Lantern_01)
for (MeshComponent : MeshComponents):
set MeshComponent.M_Lantern = MaterialInstanceLa función OnInteractFinished() toma al agente, o jugador, como instigador de la interacción. Esta función simplemente llama a la función ToggleLight() para encender y apagar el farol.
La función ToggleLight() hace el trabajo pesado de encender y apagar la linterna. Primero, en una expresión if, comprueba si el nivel emisivo de MaterialInstance es 0,0, lo que indica que la luz está apagada. Si es así, establece el nivel de emisor en 1,0. A continuación, en dos expresiones for, encuentra cada light_component y particle_system_component en Entidades descendientes y los activa llamando a Enable() y reproducir() respectivamente.
ToggleLight():void =
if (MaterialInstance.Emissive_Multiply = 0.0):
set MaterialInstance.Emissive_Multiply = 1.0
for:
Light : Entity.FindDescendantComponents(light_component)
do:
Light.Enable()
for:
Si la luz ya estaba encendida, la función hace lo contrario dentro de la sentencia else. Establece los niveles emisivos del material en 0,0 y desactiva cualquier componente del sistema de partículas y luz en las Entidades descendientes.
else:
set MaterialInstance.Emissive_Multiply = 0.0
for:
Light : Entity.FindDescendantComponents(light_component)
do:
Light.Disable()
for:
Particle : Entity.FindDescendantComponents(particle_system_component)
Las funciones de esta secuencia de comandos se combinan para hacer que el farol sea dinámico, encendiendo y apagando múltiples componentes cuando un jugador interactúa con él. Ten en cuenta que, aunque el farol es el que se enciende y apaga, su Entidad principal del poste de luz es la que proporciona el lantern_interaction_component.
Piensa en lo que tendrías que hacer para tener un poste de luz con varias luces, encendiéndolas y apagándolas con solo pulsar un botón. Como este código funciona encontrando Entidades descendientes con un tipo de componente concreto, no necesitarías un código Verse adicional para implementar esta función. Siempre que cada entidad subordinada del farol tuviera un componente de luz o un componente de partículas, estarías listo.
Secuencia de comandos completa
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
LightPost := module:
Materials<public> := module: