Wykonując ten krok w samouczku Łamigłówka z otagowanymi światłami, nauczysz się wykrywać, gdy gracz rozwiąże łamigłówkę, aby wówczas zespawnować przedmiot i uniemożliwić graczowi dalszą interakcję z łamigłówką.
Wykrywanie rozwiązanej łamigłówki
W tej sekcji przedstawiono, w jaki sposób wykryć, gdy gracz rozwiąże łamigłówkę przez znalezienie właściwej kombinacji świateł. Gdy łamigłówka zostanie rozwiązania, urządzenie generatora przedmiotów powinno się włączyć, aby zespawnować przedmiot.
Aby wykryć, kiedy gracz rozwiąże łamigłówkę, wykonaj następujące instrukcje:
- Dodaj edytowalne pole
item_spawner_device
o nazwieItemSpawner
do klasytagged_lights_puzzle
, aby utworzyć reprezentację urządzenia generatora przedmiotów.@editable ItemSpawner : item_spawner_device = item_spawner_device{}
- Następnie zdefiniuj stan świateł odpowiadający rozwiązaniu łamigłówki. Reprezentacją stanu świateł jest tablica
logic
, dlatego stan świateł odpowiadający rozwiązaniu także powinien być tablicąlogic
, aby móc łatwo porównać dwie tablice. Utwórz edytowalne pole tablicylogic
o nazwieSolvedLightsState
w klasietagged_lights_puzzle
. W tym przykładzie gracz musi włączyć wszystkie światła, aby rozwiązać łamigłówkę, więc zainicjuj każdy element wartościątrue
, aby uzyskać reprezentację zaświeconego światła.@editable SolvedLightsState : []logic = array{true, true, true, true}
- Zapisz plik w Visual Studio Code.
- Na pasku narzędzi UEFN kliknij opcję Kompiluj skrypty Verse, aby zaktualizować urządzenie Verse w poziomie.
- W obszarze Outliner wybierz tagged_lights_puzzle, aby otworzyć jego panel Szczegóły.
- W panelu Szczegóły ustaw we właściwości Generator przedmiotów Urządzenie generatora przedmiotów zastosowane w poziomie.
- Następnie napisz kod, który sprawdza, czy bieżący stan świateł
LightsState
jest zgodny ze stanem rozwiązaniaSolvedLightsState
. Dodaj nową metodę o nazwieIsPuzzleSolved()
do klasytagged_lights_puzzle
. Metoda ta powinna zakończyć się powodzeniem, jeśli łamigłówka została rozwiązana, i niepowodzeniem, jeśli jej nie rozwiązano, aby informować wywoływacza o wyniku sprawdzenia. To oznacza, że metodę należy oznaczyć jako zawodną za pomocą specyfikatoradecides
. Metoda zawiera specyfikatordecides
, więc musi również zawierać specyfikatortransacts
, co oznacza, że akcje wykonywane przez tę metodę można cofnąć (uzyskując efekt, jakby akcje te nigdy nie zostały wykonane), jeśli dowolny fragment metody okaże się zawodny.IsPuzzleSolved()<decides><transacts> : void = Logger.Print(“Sprawdzanie, czy łamigłówka została rozwiązana”)
Język Verse wykorzystuje powodzenie/niepowodzenie do podejmowania decyzji. Aby dowiedzieć się więcej na temat zastosowania niepowodzenia w języku Verse, patrz Niepowodzenie.
- Kiedy urządzenie powinno sprawdzać, czy łamigłówka została rozwiązana? Najlepszy moment jest tuż po każdej aktualizacji tablicy
LightsState
, która ma miejsce w obrębie metodyToggleLights()
. Gdy wyrażeniefor
zakończy aktualizowanie tablicyLightsState
, wywołaj metodęIsPuzzleSolved[]
, aby ustalić, czy łamigłówka została rozwiązana i należy zespawnować przedmiot (wywołując w tym celu funkcjęItemSpawner.Enable()
).IsPuzzleSolved[]
jest wyrażeniem zawodnym (dlatego przy wywoływaniu metody należy posłużyć się nawiasem[]
, a nie()
), w związku z czym należy je wywoływać w kontekście niepowodzenia. W tym przykładzie kontekstem niepowodzenia jest wyrażenieif
, aby móc warunkowo wykonywać wyrażenia w zależności od tego, czy łamigłówka została rozwiązana.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Światło pod indeksem {LightIndex} {if (IsLightOn?) then "– wyłączanie" else "– włączanie"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Zaktualizowano stan światła pod indeksem {LightIndex}") if (IsPuzzleSolved[]): Logger.Print("Łamigłówka została rozwiązana!") ItemSpawner.Enable()
- Następnie skonfiguruj metodę
IsPuzzleSolved()
do wykrywania, czy łamigłówka została rozwiązana.IsPuzzleSolved()
jest kontekstem niepowodzenia, dlatego możesz wykorzystać wyrażenia zawodne w ciele metody bez konieczności używania kolejnego kontekstu niepowodzenia, jak w przypadku wyrażeniaif
. W tym przypadku musisz sprawdzić, czy stan każdego światła odpowiada stanowi rozwiązania łamigłówki. Aby przetestować, czy dwie wartościlogic
są takie same, możesz użyć operatora równości=
będącego wyrażeniem zawodnym. Przy pierwszej sytuacji, w której dwie sprawdzane wartości nie będą takie same, wyrażenie zakończy się niepowodzeniem, a zatem metoda również się nie powiedzie i nastąpi powrót do kontekstu jej wywoływacza (w tym przypadku wyrażeniaif
w metodzieToggleLights()
).IsPuzzleSolved()<decides><transacts> : void = Logger.Print(“Sprawdzanie, czy łamigłówka została rozwiązana”) for: LightIndex -> IsLightOn : LightsState IsLightOnInSolution := SolvedLightsState[LightIndex] do: IsLightOn = IsLightOnInSolution
- Zapisz zmiany w Visual Studio Code.
- Na pasku narzędzi UEFN kliknij opcję Kompiluj skrypty Verse, aby skompilować swój kod.
- Na pasku narzędzi UEFN kliknij przycisk Odtwórz, aby przetestować poziom w grze.
Podczas testowania poziomu w grze z zastosowaniem ustawień przedstawionych w tym przykładzie jednorazowa interakcja ze wszystkimi przyciskami powinna rozwiązać łamigłówkę i spowodować zespawnowanie przedmiotu.

Usuwanie interakcji z przyciskiem po rozwiązaniu łamigłówki
Gdy gracz rozwiąże łamigłówkę, powinien utracić możliwość interakcji z przyciskami oraz włączania/wyłączania świateł. W tej sekcji opisano, w jaki sposób anulować subskrypcję zdarzenia tak, aby w przypadku interakcji gracza z przyciskiem procedury obsługi zdarzeń nie był już wywoływany.
Wywołanie funkcji Subscribe()
na rzecz zdarzenia urządzenia będzie miało wynik cancelable
. Wywołanie funkcji Cancel()
na rzecz zmiennej cancelable
spowoduje anulowanie subskrypcji funkcji wywoływanej po wystąpieniu zdarzenia, dzięki czemu funkcja nie będzie już wywoływana po wysłaniu zdarzenia.
Aby usunąć możliwość interakcji z przyciskami po rozwiązaniu łamigłówki, wykonaj następujące instrukcje:
- Dodaj pole zmiennej tablicy
cancelable
o nazwieButtonSubscriptions
do klasytagged_lights_puzzle
, aby zapisać wynik subskrypcji każdego zdarzenia przycisku, a następnie zainicjuj pole z użyciem pustej tablicy.var ButtonSubscriptions : []cancelable = array{}
- Jest to ostatnia instrukcja wyrażenia
for
, dlatego zwracane przez nią wartości dla wszystkich pomyślnych iteracji są gromadzone w tablicy typu informacji zwrotnych wyrażenia. Zgodnie z przedstawionym powyżej objaśnieniem typem informacji zwrotnej dla wywołaniaSubscribe
zdarzenia jestcancelable
. Odwołuje się to do wyników wyrażeniafor
w tablicy wartościcancelable
([]cancelable
) dla metody ToggleLights. Jest to zgodne z typemButtonsSubscription
, co pozwala przypisać wynik wyrażeniafor
do tablicyButtonsSubscription
. Dodaj ten kod w funkcjiOnBegin
po członieSetupPuzzleLights
:OnBegin<override>()<suspends> : void = SetupPuzzleLights() set ButtonSubscriptions = for: ButtonIndex -> Button : Buttons LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed)
- Trzeba również pamiętać o wyłączeniu przycisku, aby gracz nie mógł już zmienić stanu
LightsState
. W tym celu trzeba anulować subskrypcję procedury obsługiInteractedWithEvent
każdego przycisku za pomocą wywołania ich subskrypcjicancelable
. Te subskrypcjeButtonSubscriptions
zostały zapisane po utworzeniu procedur obsługi zdarzeń w metodzieOnBegin
. Teraz wystarczy przeprowadzić iterację po tej tablicy i wywołać anulowanie przy każdej subskrypcjiButtonSubcription
:ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Światło pod indeksem {LightIndex} {if (IsLightOn?) then "– wyłączanie" else "– włączanie"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Zaktualizowano stan światła pod indeksem {LightIndex}") if (IsPuzzleSolved[]): Logger.Print("Łamigłówka została rozwiązana!") ItemSpawner.Enable() for (ButtonSubscription : ButtonSubscriptions): ButtonSubscription.Cancel()
- Zapisz zmiany w Visual Studio Code.
- Na pasku narzędzi UEFN kliknij opcję Kompiluj skrypty Verse, aby skompilować swój kod.
- Na pasku narzędzi UEFN kliknij przycisk Odtwórz, aby przetestować poziom w grze.
Jeśli zastosuje się właściwości domyślne, jednorazowa interakcja ze wszystkimi przyciskami powinna rozwiązać łamigłówkę i spowodować zespawnowanie przedmiotu oraz wyłączenie możliwości dalszej interakcji z przyciskiem.
Następny krok
W ostatnim kroku tego samouczka zobaczysz kompletny skrypt omawianego w nim zagadnienia i poznasz pomysły na dalszą modyfikację przykładu.