In diesem Schritt des „Tagged Lights“-Rätsel-Tutorials erfährst du, wie du eine Gruppe von Lichtern ein-/ausschaltest je nachdem, mit welcher Taste der Spieler interagiert.
Lichter ein-/ausschalten
Du musst eine Zuordnung zwischen einer Taste und der Gruppe von Lichtern erstellen, die ein-/ausgeschaltet werden sollen, wenn der Spieler die Taste betätigt. Dazu kannst du jede Taste den Indizes zuordnen, welche die Lichter im Array Lights aufweisen.
In diesem Beispiel wird folgende Zuordnung zwischen Tasten und Lichtern verwendet:
- Taste 1 ist dem Licht bei Index 0 sowie dem Licht bei Index 3 zugeordnet
- Taste 2 ist dem Licht bei Index 0, dem Licht bei Index 1 sowie dem Licht bei Index 2 zugeordnet
- Taste 3 ist dem Licht bei Index 0 sowie dem Licht bei Index 1 zugeordnet
- Taste 4 ist dem Licht bei Index 1 zugeordnet
Du kannst diese Zuordnung mit einem Array namens ButtonsToLights repräsentieren, in dem jedes Element von ButtonsToLights ein eigenes Array mit den Indizes der Lichter ist. Der Typ von ButtonsToLights ist [][]int, um anzugeben, dass ButtonsToLights ein Array von ganzzahligen Arrays ist.
| Index | 0 | 1 | 2 | 3 |
| Element | Array{0, 3} | Array{0, 1, 2} | Array{0, 1} | Array{1} |
Führe folgende Schritte aus, um die Lichter ein-/auszuschalten:
- Erstelle an Array von ganzzahligen Arrays namens
ButtonsToLightsund initialisiere es mit der Zuordnung von Taste-und-Licht-Indizes aus der Tabelle oben.ButtonsToLights : [][]int = array{array{0, 3}, array{0, 1, 2}, array{0, 1}, array{1}}Die Indizes eines Arrays beginnen bei 0 und enden bei der Anzahl der Elemente minus 1. Das erste Element von
ButtonsToLightsist also bei Index 0, das letzte bei Index 3. - Füge der
tagged_lights_puzzle-Klasse eine neue Methode namensToggleLights()hinzu. Mit dieser Methode werden die Lichter imLights-Array je nach den Indizes ein-/ausgeschaltet, welche der Funktion als ganzzahliges Array (passend zu den Elementen des ArraysButtonsToLights) zugeordnet sind, und die Elemente an den entsprechenden Indizes inLightsStatewerden aktualisiert.- Füge der Methode
ToggleLights()den ParameterLightIndices : []inthinzu und drucke jeden Index mithilfe desfor-Ausdrucks ins Output-Log.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices do: Logger.Print("Licht bei {LightIndex} wird ein-/ausgeschaltet") - Rufe
ToggleLights()inOnBegin()auf, um die Methode beim Erstellen zu testen. Verwende das erste Element vonButtonsToLightsals Test. Das Indizieren in ein Array ist ein fehlbarer Ausdruck, daher musst du von einem Fehlerkontext aus auf das Array zugreifen. In diesem Beispiel wird derif-Ausdruck für den Fehlerkontext verwendet.
OnBegin<override>()<suspends> : void = SetupPuzzleLights() # Verwende das erste Element von „ButtonsToLights“, um die Methode „ToggleLights“ zu testen if (LightIndices : []int = ButtonsToLights[0]): ToggleLights(LightIndices) - Füge der Methode
- Nun liegt
LightIndexvor. Greife bei diesem Index auf die ArraysLightsundLightsStatezu, um die Referenz Benutzerdefiniertes-Licht-Gerät und ihren aktuellen Zustand zu erhalten. Licht ein-/ausschalten bedeutet: Ist das Licht eingeschaltet, so wird es ausgeschaltet; ist das Licht ausgeschaltet, so wird es eingeschaltet. Aktualisiere die Druckanweisung, um den neuen Zustand des Lichts anzugeben.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Licht bei {LightIndex} wird {if (IsLightOn?) then "aus" else "an"}geschaltet") - Aktualisiere jetzt den Zustand des Benutzerdefiniertes-Licht-Geräts sowohl im Spiel als auch im
LightsState-Array.- Rufe
TurnOn()beim Licht auf, wennIsLightOnden Wertfalseaufweist, und rufeTurnOff()beim Licht auf, wennIsLightOnden Werttrueaufweist. Der letzte Ausdruck in einem Codeblock ist das Ergebnis. Das Einstellen vonfalseodertrueals letzten Ausdruck bedeutet also, dass der Wert inNewLightStategespeichert wird.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices Light := Lights[LightIndex] IsLightOn := LightsState[LightIndex] do: Logger.Print("Licht bei {LightIndex} wird {if (IsLightOn?) then "aus" else "an"}geschaltet") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true - Aktualisiere das Element
LightsStatebeiLightIndexmit dem Wert inNewLightState. Das Indizieren in ein Array ist ein fehlbarer Ausdruck, daher benötigtLightsStateeinen Fehlerkontext. In diesem Beispiel ist der Fehlerkontext derif-Ausdruck. Drucke ins Output-Log, dass der Zustand aktualisiert wurde.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Licht bei {LightIndex} wird {if (IsLightOn?) then "aus" else "an"}geschaltet") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Zustand von Licht bei {LightIndex} aktualisiert")
Es ist ratsam, ins Output-Log zu drucken, wenn Fehlerkontexte verwendet werden. Wenn ein Ausdruck in einem Fehlerkontext fehlschlägt, werden alle Änderungen im Fehlerkontext zurückgenommen, als hätten sie nicht stattgefunden. Wenn du ins Output-Log druckst, kannst du dich vergewissern, dass die Änderung erfolgreich war, sofern der Text im Output-Log erscheint, und musst dich dazu nicht ausschließlich auf den Spielzustand verlassen.
- Rufe
Tastendrücke mit Ein-/Ausschalten von Lichtern verbinden
Nun hast du definiert, wie die Lichter ein-/ausgeschaltet wrden. Im nächsten Schritt verbindest du Tastendrücke mit dem Ein-/Ausschalten von Lichtern.
Abonniere dazu das InteractedWithEvent der Taste. Siehe [Code für Geräteinteraktionen] (coding-device-interactions-in-verse) für weitere Einzelheiten zum Ereignisabonnement.
Das InteractedWithEvent erwartet einen Event-Handler mit einem Parameter InPlayer : agent und einem void-Rückgabetyp. Er muss außerdem wissen, mit welchen Lichtern die Taste verbunden ist, die das Event gesendet hat, sowie eine Referenz auf dein Verse-Gerät tagged_lights_puzzle enthalten, um die Methode ToggleLights() aufrufen zu können.
Du kannst all diese Informationen in einem benutzerdefinierten Objekt zusammenfassen, indem du eine neue Klasse erstellst, welche die Indizes und die zu abonnierende Funktion enthält. So weist jede Schaltfläche ihren eigenen Zustand und ihren eigenen Event-Handler auf wie in dieser neuen Klasse repräsentiert.
Führe folgende Schritte aus, um ein benutzerdefiniertes Objekt zum Event-Handling zu erstellen:
- Erstelle eine neue Klasse namens
button_event_handler. Die Klassendefinition muss Folgendes enthalten:- Ein ganzzahliges Array namens
Indices. - Ein Feld
tagged_lights_puzzlenamensPuzzleDevice, das als Referenz auf dein Verse-Gerät dient, damit du dieToggleLights()-Methode aufrufen kannst. - Eine Methode namens
OnButtonPressed()mit dem ParameterInPlayer : agentund einemvoid-Rückgabetyp, derToggleLights()beimPuzzleDeviceaufruft.button_event_handler := class(): # Positionen, die zum Zugreifen auf die Lichter dienen, die von dieser Schaltfläche gesteuert werden. Indices : []int # tagged_lights_puzzle, das diesen button_event_handler erstellt hat, damit du Funktionen darauf aufrufen kannst PuzzleDevice : tagged_lights_puzzle OnButtonPressed(InPlayer : agent) : void = # Teile dem PuzzleDevice mit, dass es die Lichter an den Positionen ein-/ausschalten soll, welche von dieser Schaltfläche gesteuert werden. PuzzleDevice.ToggleLights(Indices)
- Ein ganzzahliges Array namens
- Erstelle ein bearbeitbares
button_device-Arrayfeld in dertagged_lights_puzzle-Klsse, um die Tasten zu referenzieren, mit denen der Spieler interagieren kann:@editable Buttons : []button_device = array{} - Aktualisiere jetzt
OnBegin()in dertagged_lights_puzzle-Klasse, um einebutton_event_handler-Instanz für jede Taste zu erstellen. Der button_event_handler benötigt folgende Informationen:- Indizes der Lichter, die mit der Taste verknüpft sind. Du erhältst sie über das
ButtonsToLights-Array mithilfe desButtonIndex, der vomfor-Ausdruck bereitgestellt wird. Du kannst ihn als Filterbedingung desfor-Ausdrucks abrufen, der zum Iterieren durch alleButtonsverwendet wird. Er dient auch als Schutz des Codes vor dem Indizieren ungültiger Daten; wenn das Indizieren fehlschlägt, wäre das Programm dennoch gültig, da die fehlerhafte Iteration übersprungen würde (zu so einem Fehlschlag könnte es kommen, wenn du vergisst, die Anzahl derButtonsToLightsmit der Anzahl derButtonsabzugleichen). - Eine Referenz auf dein Verse-Gerät, die Instanz von
tagged_lights_puzzle. Um eine Referenz auf das aktuelle Objekt innerhalb einer Klassendefinition zu erhalten, kannst duSelfverwenden. - Das Erstellen eines
button_event_handler-Objekts mit diesen Daten sieht folgendermaßen aus:OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Schaltfläche : Schaltflächen LightIndices := ButtonsToLights[ButtonIndex] do: button_event_handler{Indices := LightIndices, PuzzleDevice := Self}
- Indizes der Lichter, die mit der Taste verknüpft sind. Du erhältst sie über das
- Du kannst nun die
OnButtonPressed()-Funktion des neu erstellten Handlers verwenden, um dasInteractedWithEventdes Tastengeräts zu abonnieren. Wenn dieOnButtonPressed()-Funktion aufgerufen wird, hast du Zugriff auf die Licht-Indizes sowie eine Referenz auf dastagged_lights_puzzle-Gerät, das mit der Taste verknüpft ist, mit welcher der Spieler interagiert hat.OnBegin<override>()<suspends> : void = SetupPuzzleLights() for: ButtonIndex -> Schaltfläche : Schaltflächen LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) - Speichere das Script in Visual Studio Code.
- Klicke in der UEFN-Symbolleiste auf Verse-Scripte erstellen, um dein Verse-Gerät im Level mit deinem neuen Code zu aktualisieren.
- Wähle im Outliner das Gerät tagged_lights_puzzle aus, um sein Detail-Panel zu öffnen.
- Füge dem
Buttons-Array im Detail-Panel vier Elemente hinzu und weise jedem eine andere Taste zu. Die anderen Eigenschaften musst du nicht ändern, weil das Script diese Eigenschaften auffüllt. - Klicke in der UEFN-Symbolleiste auf Spielen, um das Level einem Spieltest zu unterziehen.
Wenn du dein Level jetzt testest, solltest du mit den Schaltflächen interagieren können und jede Schaltfläche sollte je nach Einstellung der ButtonsLightsIndices ein anderes Set an Lichtern umschalten. Denke daran, dass GetCreativeObjectsWithTag() keine bestimmte Reihenfolge garantiert, so dass die Lichter, die aufgrund der Reihenfolge im Script umgeschaltet werden, möglicherweise nicht mit der Reihenfolge übereinstimmen, die du im Level siehst.

Nächster Schritt
Im nächsten Schritt dieses Tutorials erfährst du, wie du erkennst, ob das Rätsel gelöst wurde, sodass ein Gegenstand gespawnt wird und keine weitere Interaktionen mit dem Rätsel möglich sind.