Si completas este paso del tutorial Puzle de luces marcadas, aprenderás a detectar cuándo el jugador resuelve el puzle para poder generar un objeto y evitar que se siga interactuando con el puzle.
Cómo conmutar luces
Tendrás que crear una asignación entre un botón y el grupo de luces que debe conmutar cuando el jugador interactúe con el botón. Para ello, puedes asignar cada botón a los índices de las luces de la matriz Lights.
Este ejemplo utiliza la siguiente asignación entre botones y luces:
- El botón 1 se asigna a la luz de índice 0 y a la luz de índice 3.
- El botón 2 se asigna a la luz de índice 0, la luz de índice 1 y la luz de índice 2.
- El botón 3 se asigna a la luz de índice 0 y a la luz de índice 1.
- El botón 4 se asigna a la luz de índice 1.
Puedes representar esta asignación con una matriz nombrada ButtonsToLights, donde cada elemento de ButtonsToLights es otra matriz que contiene los índices de las luces. El tipo de ButtonsToLights es entonces [][]int, para especificar que ButtonsToLights es una matriz de matrices de enteros.
| Índice | 0 | 1 | 2 | 3 |
| Elemento | array{0, 3} | array{0, 1, 2} | array{0, 1} | array{1} |
Sigue estos pasos para conmutar las luces:
- Crea una matriz de matrices de enteros nombrada
ButtonsToLightse iníciala con la asignación de índices de botón a luz descrita en la tabla anterior.ButtonsToLights : [][]int = array{array{0, 3}, array{0, 1, 2}, array{0, 1}, array{1}}Los índices de una matriz empiezan en 0 y llegan hasta el número de elementos menos 1. Así, el primer elemento de
ButtonsToLightsestá en el índice 0 y el último en el índice 3. - Añade un nuevo método llamado
ToggleLights()a la clasetagged_lights_puzzle. Este método encenderá/apagará las luces de la matrizLightsbasándose en los índices dados a la función como matriz de enteros (para que coincidan con los elementos de la matrizButtonsToLights) y actualizará los elementos en los mismos índices enButtonsToLights.- Añade el parámetro
LightIndices : []intal métodoToggleLights()e imprime cada índice en el registro de salida utilizando la expresiónfor.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices do: Logger.Print("Cambiando luz a {LightIndex}") - Llama a
ToggleLights()enOnBegin()para probar el método mientras lo creas. Utiliza el primer elemento deButtonsToLightscomo prueba. Como indexar en una matriz es una expresión falible, tendrás que acceder a la matriz desde un contexto de fallo. Este ejemplo utiliza la expresiónifpara el contexto de fallo.
OnBegin<override>()<suspends> : void = SetupPuzzleLights() # Utiliza el primer elemento de ButtonsToLights para probar el método ToggleLights if (LightIndices : []int = ButtonsToLights[0]): ToggleLights(LightIndices) - Añade el parámetro
- Ahora que tienes
LightIndex, accede a las matricesLightsyLightsStateen ese índice para obtener la referencia del dispositivo de Luz personalizable y su estado actual. Conmutar una luz significa que si la luz está encendida, se apaga; y si la luz está apagada, se enciende. Actualiza la sentenciaprintpara que diga cuál será el nuevo estado de la luz.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Encendiendo luz a {LightIndex} {if (IsLightOn?) then "Off" else "On"}") - Ahora actualiza el estado del dispositivo Luz personalizable tanto en el juego como en la matriz
LightsState.- Llama a
TurnOn()en la luz siIsLightOnesfalseyTurnOff()en la luz siIsLightOnestrue. La última expresión de un bloque de código es el resultado, por lo que establecerfalseotruecomo última expresión significa que ese valor se almacenará enNewLightState.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Encendiendo luz a {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true - Actualiza el elemento
LighsStateenLightIndexcon el valor deNewLightState. Dado que la indexación de matrices es una expresión falible, establecerLightsStatedebe ir envuelto en un contexto de fallo. En este ejemplo, el contexto de fallo es la `expresión if. Imprime en el registro de salida que se ha actualizado el estado.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Encendiendo luz a {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Se ha actualizado el estado de la luz en {LightIndex}")
Es buena idea imprimir en el registro de salida cuando utilices contextos de fallo. Si alguna expresión falla en un contexto de fallo, los cambios realizados en el mismo se anulan, como si no hubieran ocurrido. Si imprimes en el registro de salida, puedes volver a comprobar que el cambio se ha realizado si el texto aparece ahí, sin depender únicamente del estado en el juego para verificar si se ha realizado correctamente.
- Llama a
Cómo conectar la pulsación de botones con la conmutación de luces
Ahora que has definido cómo encender o apagar las luces, el siguiente paso es conectar las pulsaciones de los botones con el encendido o apagado de las luces.
Esto es posible suscribiéndose al evento InteractedWithEvent del botón. Consulta Codificación de las interacciones con dispositivos para obtener más información sobre la suscripción a eventos.
InteractedWithEvent espera un controlador de eventos con un parámetro InPlayer : agent y un tipo de retorno void, pero el controlador de eventos también necesita saber a qué luces está conectado el botón que ha enviado el evento y mantener una referencia al dispositivo de Verse tagged_lights_puzzle para poder llamar a su método ToggleLights().
Puedes agrupar toda esta información en un objeto personalizado creando una nueva clase que contenga los índices y la función a la que suscribirse. De este modo, cada botón tiene su propio estado personal y su propio controlador de eventos, representados por esta nueva clase.
Sigue estos pasos para crear un objeto personalizado para el control de eventos:
- Crea una clase nueva llamada
button_event_handler. La definición de la clase debe tener lo siguiente:- Una matriz de enteros nombrada
Indices. - Un campo
tagged_lights_puzzlenombradoPuzzleDevice, que es la referencia a tu dispositivo de Verse, para que puedas llamar al métodoToggleLights(). - Un método nombrado
OnButtonPressed()con el parámetroInPlayer : agenty un tipo de retornovoid, que llama aToggleLights()enPuzzleDevice.button_event_handler := class(): # Posiciones utilizadas para acceder a las luces que controla este botón. Indices : []int # tagged_lights_puzzle que creó este button_event_handler para que podamos llamar a funciones en él. PuzzleDevice : tagged_lights_puzzle OnButtonPressed(InPlayer : agent) : void = # Dile a PuzzleDevice que conmute las luces en las posiciones que controla este botón. PuzzleDevice.ToggleLights(Indices)
- Una matriz de enteros nombrada
- Crea una matriz editable
button_deviceen la clase referenciartagged_lights_puzzle. Haz referencia a los botones con los que el jugador puede interactuar:@editable Buttons : []button_device = array{} - Ahora actualiza
OnBegin()en la clasetagged_lights_puzzlepara crear una instancia debutton_event_handlerpara cada botón. button_event_handler necesita la siguiente información:- Índices de las luces asociadas al botón, que puedes obtener de la matriz
ButtonsToLightsutilizando elButtonIndexproporcionado por la expresiónfor. Puedes obtenerlo como condición de filtro de la expresiónforutilizada para iterar por todos losButtons. Esto también actúa como una salvaguarda que protege el código de la indexación de datos no válidos; si la indexación falla, el programa seguiría siendo válido, ya que esa iteración que falla se salta (este fallo podría ocurrir si olvidaras hacer coincidir el número deButtonsToLightscon el número deButtons). - Una referencia a tu dispositivo de Verse, la instancia de
tagged_lights_puzzle. Para obtener una referencia al objeto actual desde dentro de la definición de una clase, puedes utilizarSelf. - Crear un objeto
button_event_handlercon estos datos tiene el siguiente aspecto:OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: button_event_handler{Indices := LightIndices, PuzzleDevice := Self}
- Índices de las luces asociadas al botón, que puedes obtener de la matriz
- Ahora puedes utilizar la función
OnButtonPressed()del controlador recién creado para suscribirte alInteractedWithEventdel dispositivo Button. Cuando se llama a la funciónOnButtonPressed(), tienes acceso a los índices de las lices y a una referencia al dispositivotagged_lights_puzzleasociado al botón con el que ha interactuado el jugador.OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) - Guarda la secuencia de comandos en Visual Studio Code.
- En la barra de herramientas de UEFN, haz clic en Compilar secuencias de comandos de Verse para actualizar tu dispositivo de Verse en el nivel con tu nuevo código.
- En el esquematizador, selecciona el dispositivo tagged_lights_puzzle para abrir su panel Detalles.
- En el panel Detalles, añade cuatro elementos a la matriz
Buttonsy asigna un botón diferente a cada uno. No es necesario que modifiques las demás propiedades porque la secuencia de comandos las rellenará. - En la barra de herramientas de UEFN, haz clic en Jugar para probar el nivel.
Cuando pruebes tu nivel ahora, deberías poder interactuar con los botones, y cada botón debería activar un conjunto diferente de luces en función de la configuración de ButtonsLightsIndices. Ten en cuenta que GetCreativeObjectsWithTag() no garantiza un orden específico, por lo que las luces que se activan en función del orden en la secuencia de comandos pueden no coincidir con el orden que se ve en el nivel.

Siguiente paso
En el siguiente paso de este tutorial, aprenderás a detectar cuándo se resuelve el puzle para poder generar un objeto y evitar que se siga interactuando.