Pętla gry to kod uruchamiany w sposób powtarzalny (zapętlony), aby reagować na dane wejściowe (zwykle interakcje gracza za pomocą kontrolera lub myszy) w celu aktualizacji stanu gry i dostarczenia danych wyjściowych, które pokazują graczowi, że wpłynął na stan gry, na przykład po naciśnięciu przycisku, który włącza światło. Pętla zwykle kończy się, gdy gra zostanie ukończona, na przykład po osiągnięciu celu przez gracza, lub zakończy się niepowodzeniem, na przykład po upłynięciu limitu czasu przed osiągnięciem celu.
Wykonując ten krok w samouczku Próba czasu: Pogoń za pizzą (Time Trial: Pizza Pursuit), nauczysz się tworzyć pętlę gry i zdefiniujesz stany ukończenia i niepowodzenia gry.
Poniżej przedstawiono pseudokod pętli gry w grze Próba czasu: Pogoń za pizzą (Time Trial: Pizza Pursuit):
loop:
race:
loop:
SelectNextPickupZone
WaitForPlayerToCompletePickupZone
block:
WaitForFirstPickup
SelectNextDeliveryZone
WaitForPlayerToCompleteDeliveryZone
Ta pętla powinna się kończyć, gdy licznik czasu odliczania zakończy odliczanie lub gdy w grze wystąpi niespodziewany błąd.
Tworzenie głównej pętli gry
Aby zaktualizować plik game_coordinator_device.verse, wykonaj następujące instrukcje:
- Utwórz metodę o nazwie
PickupDeliveryLoop()
zawierającą specyfikatoryprivate
isuspends
. Przenieś pętlę utworzoną wcześniej w metodzieOnBegin()
do tej nowej metody.OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = var PickupLevel : int = 0 loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() PickupZone.ZoneCompletedEvent.Await() PickupZone.DeactivateZone() else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() DeliveryZone.ZoneCompletedEvent.Await() DeliveryZone.DeactivateZone() else: Print("Nie znaleziono następnej strefy DeliveryZone do wybrania") return
- Określ maksymalną liczbę poziomów odbioru na podstawie długości tablicy tagów i zwiększaj wartość
PickupLevel
za każdym razem, gdy gracz ukończy strefę odbioru, dopóki poziom odbioru nie będzie większy niż maksymalna liczba poziomów odbioru.OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 var PickupLevel : int = 0 loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() PickupZone.ZoneCompletedEvent.Await() PickupZone.DeactivateZone() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return
- Aktywacja strefy dostarczania powinna nastąpić, po ukończeniu przez gracza pierwszego odbioru, jednak mimo to, gracz powinien być w stanie podnosić przedmioty, jeśli zechce, zanim uda się do strefy dostarczania. W związku z tym kody stref odbioru i dostarczania muszą występować równocześnie. W tym przykładzie użyto wyrażenia współbieżności
race
, ponieważ:- Blok dostarczania powinien anulować pętlę strefy odbioru, gdy gracz zakończy dostarczanie.
- Pętla strefy dostarczania powinna anulować blok dostarczania w razie wystąpienia problemu z pętlą odbioru.
Konieczna jest również nieznaczna modyfikacja dezaktywacji strefy. W przypadku anulowania pętli lub bloku dostarczania funkcja
DeactivateZone()
nie powinna być wywoływana, jeśli skrypt oczekiwał na ukończenie strefy.Wiersz dezaktywacji strefy nie zostałby nigdy wykonany, więc strefa pozostałaby aktywna, co prowadziłoby do błędu.
-
Aby naprawić ten problem, można użyć wyrażenia
defer
. Wyrażeniedefer
opóźnia wykonanie zawartych w nim wyrażeń, dopóki zakres, w którym występuje wyrażeniedefer
, nie dobiegnie końca. Wyrażeniedefer
zostanie uruchomione po przekazaniu sterowania programem poza zakres poprzez typowe opuszczenie zakresu (zakończenie funkcji), wczesne zakończenie (na przykład za pomocą wyrażeń return lub break) albo w wyniku dowolnego anulowanego zadania współbieżnego / wyrażenia asynchronicznego (takiego jakrace
). Przypomina to kolejkowanie operacji, które zostaną wykonane na samym końcu, bez względu na to, co się stanie. Zawrzyj każde wywołanie funkcjiDeactivateZone
w wyrażeniudefer
i przenieś je przed odpowiednią funkcjęZoneCompletedEvent.Await()
.PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 var PickupLevel : int = 0 race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return block: if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # Opóźniamy dezaktywację strefy, aby anulowanie pętli PickupDeliveryLoop kończyło się także dezaktywacją każdej aktywnej strefy dostarczania. defer: Logger.Print("Dezaktywacja strefy dostarczania.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Dostarczono", ?Level:=log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level:=log_level.Error) return # Błąd pętli PickupDeliveryLoop
- Kod z poprzedniego przykładu aktywuje strefę dostarczania równocześnie z aktywacją strefy odbioru, jednak aktywacja strefy dostarczania będzie oczekiwać do momentu ukończenia pierwszego odbioru. W tym celu dodaj zdarzenie i skonfiguruj aktywację strefy dostarczania tak, aby następowała dopiero po wystąpieniu zdarzenia.
OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Po pierwszym odbiorze możemy włączyć strefę dostarczania. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # Opóźniamy dezaktywację strefy, aby anulowanie pętli PickupDeliveryLoop kończyło się także dezaktywacją każdej aktywnej strefy dostarczania. defer: Logger.Print("Dezaktywacja strefy dostarczania.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Dostarczono", ?Level:=log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level := log_level.Error) return # Błąd pętli PickupDeliveryLoop
- Zapętl to wyrażenie race strefy odbioru/dostarczania do czasu ukończenia gry, aby gracz mógł odbierać i dostarczać przedmioty.
OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # Opóźniamy dezaktywację strefy, aby anulowanie pętli PickupDeliveryLoop kończyło się także dezaktywacją każdej aktywnej strefy dostarczania. defer: Logger.Print("Dezaktywacja strefy dostarczania.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Dostarczono", ?Level:=log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level:=log_level.Error) return # Błąd pętli PickupDeliveryLoop
-
Otrzymany plik game_coordinator_device.verse powinien wyglądać następująco:
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/Curves } using { /Verse.org/Simulation/Tags } # Tagi stref gry pickup_zone_tag<public> := class(tag): pickup_zone_level_1_tag<public> := class(pickup_zone_tag): pickup_zone_level_2_tag<public> := class(pickup_zone_tag): pickup_zone_level_3_tag<public> := class(pickup_zone_tag): delivery_zone_tag<public> := class(tag): log_pizza_pursuit<internal> := class(log_channel){} game_coordinator_device<public> := class(creative_device): DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{} OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() SetupZones<private>() : void = DeliveryZoneSelector.InitZones(delivery_zone_tag{}) PickupZoneLevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for(PickupZoneTag : PickupZoneLevelTags): PickupZone := tagged_zone_selector{} PickupZone.InitZones(PickupZoneTag) PickupZone PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Nie znaleziono następnej strefy PickupZone do wybrania") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # Opóźniamy dezaktywację strefy, aby anulowanie pętli PickupDeliveryLoop kończyło się także dezaktywacją każdej aktywnej strefy dostarczania. defer: Logger.Print("Dezaktywacja strefy dostarczania.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Dostarczono", ?Level:=log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level:=log_level.Error) return # Błąd pętli PickupDeliveryLoop
Zapisz swoje pliki Verse, skompiluj kod i przeprowadź test gry na swoim poziomie.
W trakcie przeprowadzania testu gry na twoim poziomie jedno z urządzeń generatora przedmiotów zostanie aktywowane na początku gry oraz po tym, jak gracz odbierze przedmiot. Gdy gracz odbierze pierwszy przedmiot, urządzenie generatora przedmiotów zostanie dezaktywowane i nastąpi aktywacja urządzenia strefy punktowanej. Cykl ten będzie kontynuowany, dopóki ręcznie nie zakończysz gry.
Definiowanie stanów ukończenia i niepowodzenia dla pętli gry
Masz już utworzoną główną pętlę gry. Teraz zdefiniuj stan ukończenia i niepowodzenia pętli gry. Ta gra ma się zakończyć, gdy:
- Odliczanie dobiegnie końca lub
- Wystąpi problem z pętlą gry.
Aby skonfigurować stany ukończenia i niepowodzenia dla gry, wykonaj następujące instrukcje:
- Utwórz instancję klasy
countdown_timer
w urządzeniugame_coordinator_device
, stosując specyfikatorprivate
.game_coordinator_device<public> := class(creative_device): @editable EndGame<public> : end_game_device = end_game_device{} var CountdownTimer<private> : countdown_timer = countdown_timer{}
- Konstruktor licznika czasu odliczania
countdown_timer
wymaga odwołania do gracza, więc dodaj opcjonalną zmienną gracza do przechowywania odwołania do gracza w trybie jednego gracza i utwórz funkcję o nazwieFindPlayer()
, która będzie pobierać odwołanie do gracza. Przed skonfigurowaniem stref wywołaj funkcjęFindPlayer()
w metodzieOnBegin()
.game_coordinator_device<public> := class(creative_device): @editable EndGame<public> : end_game_device = end_game_device{} var CountdownTimer<private> : countdown_timer = countdown_timer{} var MaybePlayer<private> : ?player = false OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() FindPlayer<private>() : void = # Gra odbywa się w trybie jednego gracza, dlatego pierwszy gracz (oznaczony indeksem 0) # powinien być jedynym dostępnym graczem. if (FirstPlayer := GetPlayspace().GetPlayers()[0]): set MaybePlayer = option{FirstPlayer} Logger.Print("Znaleziono gracza") else: # Zarejestruj błąd, jeśli nie można znaleźć gracza. # To nie powinno się zdarzyć, ponieważ co najmniej jeden gracz jest zawsze obecny. Logger.Print("Nie znaleziono prawidłowego gracza", ?Level := log_level.Error)
- Utwórz funkcję o nazwie
HandleCountdownEnd()
, a następnie odczekaj, aż licznik czasu odliczania zakończy odliczanie i aktywuje urządzenie końca gry.HandleCountdownEnd<private>(InPlayer : agent)<suspends> : void = CountdownTimer.CountdownEndedEvent.Await() EndGame.Activate(InPlayer)
- Utwórz funkcję o nazwie
StartGame()
, a następnie wywołaj tę funkcję po funkcjiSetupZones()
w metodzieOnBegin()
. Ta funkcja powinna:- Zainicjować licznik czasu odliczania.
game_coordinator_device<public> := class(creative_device): # Od jakiej wartości licznik czasu odliczania rozpocznie odliczanie w dół. @editable InitialCountdownTime<public> : float = 30.0 @editable EndGame<public> : end_game_device = end_game_device{} OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() StartGame() StartGame<private>()<suspends> : void = Logger.Print("Próba rozpoczęcia gry...") <# Konstruujemy nowy licznik czasu odliczania countdown_timer, który po uruchomieniu zacznie odliczać w dół od wartości InitialCountdownTime. Licznik czasu countdown_timer wymaga gracza, któremu może wyświetlić swój UI. Do tej pory powinniśmy już mieć prawidłowego gracza. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Prawidłowy gracz, rozpoczynanie gry...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() else: Logger.Print("Nie znaleziono prawidłowego gracza. Przerwanie uruchamiania gry", ?Level := log_level.Error)
- Za pomocą wyrażenia
race
wywołaj funkcjeHandleCountdownEnd(ValidPlayer)
iPickupDeliveryLoop()
, aby:- Pętla gry została zatrzymana, gdy odliczanie dobiegnie końca, lub
- Odliczanie zostało anulowane, jeśli pętla gry zostanie zatrzymana.
StartGame<private>()<suspends> : void = Logger.Print("Próba rozpoczęcia gry...") <# Konstruujemy nowy licznik czasu odliczania countdown_timer, który po uruchomieniu zacznie odliczać w dół od wartości InitialCountdownTime. Licznik czasu countdown_timer wymaga gracza, któremu może wyświetlić swój UI. Do tej pory powinniśmy już mieć prawidłowego gracza. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Prawidłowy gracz, rozpoczynanie gry...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Czekamy na zakończenie odliczania. # Jednocześnie uruchamiamy również pętlę gry dotyczącą odbioru i dostarczania, która stanowi główną rozgrywkę. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Nie znaleziono prawidłowego gracza. Przerwanie uruchamiania gry", ?Level := log_level.Error)
- Zainicjować licznik czasu odliczania.
- Plik game_coordinate_device.verse powinien teraz wyglądać następująco:
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/Curves } using { /Verse.org/Simulation/Tags } # Tagi stref gry pickup_zone_tag<public> := class(tag): pickup_zone_level_1_tag<public> := class(pickup_zone_tag): pickup_zone_level_2_tag<public> := class(pickup_zone_tag): pickup_zone_level_3_tag<public> := class(pickup_zone_tag): delivery_zone_tag<public> := class(tag): log_pizza_pursuit<internal> := class(log_channel){} game_coordinator_device<public> := class(creative_device): # Od jakiej wartości licznik czasu odliczania rozpocznie odliczanie w dół. @editable InitialCountdownTime<public> : float = 30.0 @editable EndGame<public> : end_game_device = end_game_device{} DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{} OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() StartGame() FindPlayer<private>() : void = # Gra odbywa się w trybie jednego gracza, dlatego pierwszy gracz (oznaczony indeksem 0) # powinien być jedynym dostępnym graczem. if (FirstPlayer := GetPlayspace().GetPlayers()[0]): set MaybePlayer = option{FirstPlayer} Logger.Print("Znaleziono gracza") else: # Zarejestruj błąd, jeśli nie można znaleźć gracza. # To nie powinno się zdarzyć, ponieważ co najmniej jeden gracz jest zawsze obecny. Logger.Print("Nie znaleziono prawidłowego gracza", ?Level := log_level.Error) SetupZones<private>() : void = DeliveryZoneSelector.InitZones(delivery_zone_tag{}) PickupZoneLevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for(PickupZoneTag : PickupZoneLevelTags): PickupZone := tagged_zone_selector{} PickupZone.InitZones(PickupZoneTag) PickupZone StartGame<private>()<suspends> : void = Logger.Print("Próba rozpoczęcia gry...") <# Konstruujemy nowy licznik czasu odliczania countdown_timer, który po uruchomieniu zacznie odliczać w dół od wartości InitialCountdownTime. Licznik czasu countdown_timer wymaga gracza, któremu może wyświetlić swój UI. Do tej pory powinniśmy już mieć prawidłowego gracza. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Prawidłowy gracz, rozpoczynanie gry...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Czekamy na zakończenie odliczania. # Jednocześnie uruchamiamy również pętlę gry dotyczącą odbioru i dostarczania, która stanowi główną rozgrywkę. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Nie znaleziono prawidłowego gracza. Przerwanie uruchamiania gry", ?Level := log_level.Error) HandleCountdownEnd<private>(InPlayer : agent)<suspends> : void = CountdownTimer.CountdownEndedEvent.Await() EndGame.Activate(InPlayer) PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() <# To jedyne wyrażenie defer, jakiego potrzebujemy dla dowolnej aktywowanej strefy PickupZone. Spowoduje ono dezaktywowanie pierwszej strefy PickupZone na końcu każdej pętli zewnętrznej lub dezaktywację dowolnej późniejszej strefy PickupZone. Dzieje się tak dlatego, że wyrażenie jest poddawane ocenie na końcu, gdy zmienna PickupZone została już powiązana z nowszą strefą. #> defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() Logger.Print("Odebrano", ?Level := log_level.Normal) # Po pierwszym odbiorze możemy włączyć strefę dostarczania. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() # Zaktualizuj poziom odbioru if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 # Logger.Print("Zwiększono PickupLevel do {PickupLevel}", ?Level := log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy PickupZone do wybrania", ?Level := log_level.Error) return # Błąd pętli PickupDeliveryLoop block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # Opóźniamy dezaktywację strefy, aby anulowanie pętli PickupDeliveryLoop kończyło się także dezaktywacją każdej aktywnej strefy dostarczania. defer: Logger.Print("Dezaktywacja strefy dostarczania.", ?Level := log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Dostarczono", ?Level := log_level.Normal) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level := log_level.Error) return # Błąd pętli PickupDeliveryLoop
- Zapisz swoje pliki Verse, skompiluj kod i przeprowadź test gry na swoim poziomie.
Podczas testu gry utworzonego poziomu gra działa tak samo, jak w poprzedniej sekcji, jednak teraz dostępny jest licznik czasu odliczania, który zakończy grę po zakończeniu odliczania lub w razie wystąpienia problemu w pętli gry.