Completando questo passaggio del tutorial Puzzle delle luci con tag, imparerai ad attivare/disattivare un gruppo di luci in base al pulsante con cui il giocatore interagisce.
Attivare/disattivare le luci
Dovrai creare una mappatura tra un pulsante e il gruppo di luci che deve attivare/disattivare, quando il giocatore interagisce con il pulsante. Per eseguire questa operazione, puoi associare ogni pulsante agli indici delle luci nell'array Lights.
Questo esempio utilizza la seguente mappatura tra pulsanti e luci:
- Il pulsante 1 si associa alla luce dell'indice 0 e alla luce dell'indice 3
- Il pulsante 2 si associa alla luce dell'indice 0, alla luce dell'indice 1 e alla luce dell'indice 2
- Il pulsante 3 si associa alla luce dell'indice 0 e alla luce dell'indice 1
- Il pulsante 4 si associa alla luce dell'indice 1
Puoi rappresentare questa mappatura con un array denominato ButtonsToLights, dove ogni elemento di ButtonsToLights è un altro array che contiene gli indici delle luci. Il tipo di ButtonsToLights è quindi [][]int, per specificare che ButtonsToLights è un array di array di interi.
| Indice | 0 | 1 | 2 | 3 |
| Elemento | array{0, 3} | array{0, 1, 2} | array{0, 1} | array{1} |
Per attivare/disattivare le luci, procedi come segue:
- Crea un array di interi denominato
ButtonsToLightse inizializzalo con la mappatura degli indici dei pulsanti e delle luci descritta nella tabella precedente.ButtonsToLights : [][]int = array{array{0, 3}, array{0, 1, 2}, array{0, 1}, array{1}}Gli indici di un array partono da 0 e arrivano fino al numero di elementi meno 1. Quindi il primo elemento di
ButtonsToLightsè all'indice 0 e l'ultimo elemento è all'indice 3. - Aggiungi un nuovo metodo chiamato
ToggleLights()alla classetagged_lights_puzzle. Questo metodo accende/spegne le luci nell'arrayLightsin base agli indici forniti alla funzione come array di interi (per corrispondere agli elementi dell'arrayButtonsToLights) e aggiorna gli elementi agli stessi indici inLightsState.- Aggiungi il parametro
LightIndices : []intal metodoToggleLights()e stampa ogni indice nel registro di output utilizzando l'espressionefor.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices do: Logger.Print("Attivazione/disattivazione delle luci a {LightIndex}") - Chiama
ToggleLights()inOnBegin()per eseguire il test del metodo mentre lo crei. Utilizza il primo elemento diButtonsToLightscome test. Poiché l'indicizzazione in un array è un'espressione fallibile, dovrai accedere all'array da un contesto di fallimento. Questo esempio utilizza l'espressioneifper il contesto di fallimento.
OnBegin<override>()<suspends> : void = SetupPuzzleLights() # Utilizza il primo elemento di ButtonsToLights per eseguire il test del metodo ToggleLights if (LightIndices : []int = ButtonsToLights[0]): ToggleLights(LightIndices) - Aggiungi il parametro
- Ora che disponi di
LightIndex, esegui l'accesso agli arrayLightseLightsStatesu quell'indice per ottenere il riferimento al dispositivo Luce personalizzabile e al relativo stato corrente. Attivare/disattivare una luce significa: se la luce è accesa, spegnila, se la luce è spenta, accendila. Aggiorna l'istruzione di stampa per indicare il nuovo stato della luce.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Impostazione delle luci su {LightIndex} {if (IsLightOn?) then "Off" else "On"}") - Ora aggiorna lo stato del dispositivo Luce personalizzabile, sia nel gioco che nell'array
LightsState.- Chiama
TurnOn()sulla luce seIsLightOnèfalseeTurnOff()sulla luce seIsLightOnètrue. L'ultima espressione di un blocco di codice è il risultato, quindi impostarefalseotruecome ultima espressione significa che quel valore sarà memorizzato inNewLightState.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Impostazione delle luci su {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() falso else: Light.TurnOn() vero - Aggiorna l'elemento
LighsStateaLightIndexcon il valore inNewLightState. Poiché l'indicizzazione dell'array è un'espressione fallibile, deve essere eseguito il wrapping dell'impostazione diLightsStatein un contesto di fallimento. In questo esempio, il contesto di fallimento è l'espressioneif. Stampa nel registro di output che lo stato è stato aggiornato.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Impostazione delle luci su {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() falso else: Light.TurnOn() vero if (set LightsState[LightIndex] = NewLightState): Logger.Print("Stato per le luci a {LightIndex} aggiornato")
È sempre una buona idea stampare sul registro di output quando si utilizzano contesti di fallimento. Se un'espressione fallisce in un contesto di fallimento, viene eseguito il rollback di tutte le modifiche apportate nel contesto di fallimento, come se non fossero mai avvenute. Se stampi sul registro di output, puoi controllare che la modifica sia stata effettuata se il testo viene visualizzato nel registro di output, senza affidarti esclusivamente allo stato nel gioco per verificare se la modifica è andata a buon fine.
- Chiama
Collegamento della pressione dei tasti all'attivazione/disattivazione delle luci
Dopo aver definito come attivare/disattivare le luci, il passaggio successivo è collegare la pressione dei pulsanti all'accensione o allo spegnimento delle luci.
Puoi eseguire questa operazione sottoscrivendo all'InteractedWithEvent del pulsante. Per maggiori dettagli sulla sottoscrizione agli eventi, vedi Codificare le interazioni tra dispositivi.
L'evento InteractedWithEvent si aspetta un gestore eventi con un parametro InPlayer : agent e un tipo restituito void, ma il gestore eventi deve anche sapere a quali luci è collegato il pulsante che ha inviato l'evento e contenere anche un riferimento al dispositivo Verse tagged_lights_puzzle per poter chiamare il relativo metodo ToggleLights().
Puoi raggruppare tutte queste informazioni in un oggetto personalizzato, creando una nuova classe che contenga gli indici e la funzione da sottoscrivere. In questo modo, ogni pulsante ha il suo stato personale e il relativo gestore eventi, rappresentato da questa nuova classe.
Per creare un oggetto personalizzato per la gestione eventi, attieniti ai passaggi seguenti:
- Crea una nuova classe denominata
button_event_handler. La definizione della classe deve avere le seguenti caratteristiche:- Un array di interi denominato
Indices. - Un campo
tagged_lights_puzzledenominatoPuzzleDevice, che è il riferimento al tuo dispositivo Verse, per poter chiamare il metodoToggleLights(). - Un metodo denominato
OnButtonPressed()con il parametroInPlayer : agente un tipo restituitovoid, che chiamaToggleLights()sulPuzzleDevice.button_event_handler := class(): # Posizioni utilizzate per accedere alle luci controllate da questo pulsante. Indices : []int # tagged_lights_puzzle che ha creato questo button_event_handler, in modo da poter chiamare le funzioni su di esso. PuzzleDevice : tagged_lights_puzzle OnButtonPressed(InPlayer : agent) : void = # Indica al PuzzleDevice di attivare/disattivare le luci nelle posizioni controllate da questo pulsante. PuzzleDevice.ToggleLights(Indices)
- Un array di interi denominato
- Crea un campo array modificabile
button_devicenella classetagged_lights_puzzleper fare riferimento ai pulsanti con cui il giocatore può interagire:@editable Buttons : []button_device = array{} - Ora aggiorna
OnBegin()nella classetagged_lights_puzzleper creare un'istanzabutton_event_handlerper ogni pulsante. La funzione button_event_handler richiede le seguenti informazioni:- Indici delle luci associate al pulsante, che si possono ottenere dall'array
ButtonsToLightsutilizzando ilButtonIndexfornito dall'espressionefor. Lo puoi ottenere come condizione di filtro dell'espressioneforutilizzata per scorrere tutti iButtons. Questa operazione agisce anche come una misura di sicurezza che protegge il codice dall'indicizzazione di dati non validi, se l'indicizzazione fallisce, il programma sarebbe comunque valido, poiché l'iterazione non riuscita viene saltata. Questo errore potrebbe verificarsi se dimentichi di far corrispondere il numero diButtonsToLightsal numero diButtons). - Un riferimento al tuo dispositivo Verse, l'istanza di
tagged_lights_puzzle. Per ottenere un riferimento all'oggetto corrente dall'interno di una definizione di classe, puoi utilizzareSelf. - La creazione di un oggetto
button_event_handlercon questi dati è simile a quanto segue:OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: button_event_handler{Indices := LightIndices, PuzzleDevice := Self}
- Indici delle luci associate al pulsante, che si possono ottenere dall'array
- Ora puoi utilizzare la funzione
OnButtonPressed()del gestore appena creato per eseguire la sottoscrizione all'eventoInteractedWithEventdel dispositivo Pulsante. Quando viene richiamata la funzioneOnButtonPressed(), avrai accesso agli indici delle luci e a un riferimento al dispositivotagged_lights_puzzleassociato al pulsante con cui il giocatore ha interagito.OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) - Salva lo script in Visual Studio Code.
- Nella barra degli strumenti UEFN, fai clic su Compila gli script di Verse per aggiornare il tuo dispositivo di Verse nel livello con il nuovo codice.
- In Outliner, seleziona il dispositivo tagged_lights_puzzle per aprire il relativo pannello Dettagli.
- Nel pannello Dettagli, aggiungi quattro elementi all'array
Buttonse assegna a ciascuno un pulsante diverso. Non dovrai modificare le altre proprietà, perché sarà lo script a popolarle. - Nella barra degli strumenti di UEFN, fai clic su Gioca per eseguire il playtest del tuo livello.
Quando esegui il playtest del livello, dovresti essere in grado di interagire con i pulsanti e ogni pulsante dovrebbe attivare/disattivare un diverso set di luci, in base all'impostazione ButtonsLightsIndices. Tieni presente che GetCreativeObjectsWithTag() non garantisce un ordine specifico, quindi le luci che vengono attivate/disattivate in base all'ordine nello script potrebbero non corrispondere all'ordine che vedi nel livello.

Passaggio successivo
Nel passaggio successivo di questo tutorial, imparerai a riconoscere quando il giocatore risolve il puzzle, in modo da poter generare un oggetto e impedire ulteriori interazioni con il puzzle