Ustalanie, czy gracz jest bezczynny
W tej sekcji dowiesz się, jak sprawdzić, czy gracz przemieścił się o określoną odległość od ostatniej aktualizacji symulacji. Jeśli tak, bieżące położenie gracza jest zapisywane i sprawdzane ponownie. Jeśli nie, pętla zostaje przerwana i metoda zostaje zakończona. Ta metoda używa GetFortCharacter[]
, GetTransform()
i Translation
, aby uzyskać lokalizację gracza. Więcej informacji na ich temat można znaleźć na ich stronach referencyjnych API.
Ta strona zawiera fragmenty Verse, które pokazują, jak wykonać mechanikę rozgrywki wymaganą w tej rozgrywce. Wykonaj poniższe instrukcje i skopiuj pełny skrypt w kroku 6 tego samouczka.
Wykonaj poniższe kroki, aby ustalić, czy gracz jest bezczynny.
-
Utwórz metodę rozszerzającą dla klasy agenta o nazwie
AwaitStopMoving()
. Oznacza to, że dodajesz niestandardową metodę do już zdefiniowanej klasy.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się na odległość mniejszą niż minimalna.")
-
Pobierz początkowe położenie gracza.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się na odległość mniejszą niż minimalna.") # Pobierz początkowe położenia agenta z postaci agenta w scenie. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation
-
Pobierz następne położenie gracza w kolejnej aktualizacji symulacji.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się na odległość mniejszą niż minimalna.") # Pobierz początkowe położenia agenta z postaci agenta w scenie. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Pobierz położenie agenta w następnym tyknięciu gry. NewPosition := Tracked.GetTransform().Translation
- Sprawdź, czy odległość między położeniem początkowym a ostatnim położeniem mieści się w akceptowalnym progu, przekazywanym do funkcji jako parametr
MinimumDistance
.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się na odległość mniejszą niż minimalna.") # Pobierz początkowe położenia agenta z postaci agenta w scenie. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Pobierz położenie agenta w następnym tyknięciu gry. NewPosition := Tracked.GetTransform().Translation # Jeśli odległość nowego położenia w odniesieniu do położenia początkowego jest mniejsza niż MinimumDistance, agent nie poruszył się i przerywamy pętlę. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Agent przemieścił się na odległość mniejszą niż minimalna.") # W przeciwnym razie resetujemy StartPosition, aby upewnić się, że gracz porusza się od nowego położenia. else: set StartPosition = NewPosition
-
Teraz chcemy zapętlić sprawdzanie między położeniem początkowym a ostatnim i wyjść z pętli, gdy odległość między położeniami przekroczy próg
MinimumDistance
.# Wykonuje pętlę do momentu, gdy agent poruszy się na odległość mniejszą niż MinimumDistance. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się na odległość mniejszą niż minimalna.") # Pobierz początkowe położenia agenta z postaci agenta w scenie. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Pobierz położenie agenta w następnym tyknięciu gry. NewPosition := Tracked.GetTransform().Translation # Jeśli odległość nowego położenia w odniesieniu do położenia początkowego jest mniejsza niż MinimumDistance, agent nie poruszył się i przerywamy pętlę. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Agent przemieścił się na odległość mniejszą niż minimalna.") break # W przeciwnym razie resetujemy StartPosition, aby upewnić się, że gracz porusza się od nowego położenia. else: set StartPosition = NewPosition
Odliczanie przed biciem serca
Wykonaj następujące kroki, aby odczekać czas równy HeartBeat.MoveTime - HeartBeat.WarningTime
przed wyświetleniem ostrzeżenia i licznika czasu odliczania, aż upłynie czas odliczania, a następnie wyczyść ostrzeżenie i tekst odliczania.
- Utwórz funkcję o nazwie CountdownTimer().
# Opóźnia do czasu uruchomienia HeartBeatWarningTime. Następnie odlicza przez HeartBeatWarningTime i ustawia tekst odliczania. Czyści tekst w przypadku odroczenia. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Rozpoczynanie odliczania bicia serca.")
-
Najpierw należy spróbować pobrać
heartbeat_warning_ui
dla powiązanego gracza z mapy ustawionej w heartbeat.verse. Jeśli to się uda, należy rozpocząć opóźnienie między zatrzymaniem się gracza a wyświetleniem licznika czasu odliczania.# Opóźnia do czasu uruchomienia HeartBeatWarningTime. Następnie odlicza przez HeartBeatWarningTime i ustawia tekst odliczania. Czyści tekst w przypadku odroczenia. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Rozpoczęcie odliczania bicia serca.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uśpienie na czas przed pojawieniem się ostrzeżenia. Logger.Print("Rozpoczęcie wyświetlania ostrzeżenia o biciu serca.") else: Logger.Print("Nie znaleziono UIData.")
-
Teraz utwórz zmienną, która pojawi się na ekranie i będzie zmniejszana o jeden co sekundę. Nazwij ją
WarningTimeRemaining
. Ustaw ją naWarningTime
z heartbeat.verse. PonieważWarningTimeRemaining
jestint
, aWarningTime
jestfloat
, należy użyć funkcjiCeil[]
, aby utworzyćint
.# Opóźnia do czasu uruchomienia HeartBeatWarningTime. Następnie odlicza przez HeartBeatWarningTime i ustawia tekst odliczania. Czyści tekst w przypadku odroczenia. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Rozpoczęcie odliczania bicia serca.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uśpienie na czas przed pojawieniem się ostrzeżenia. Logger.Print("Rozpoczęcie wyświetlania ostrzeżenia o biciu serca.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("Nie znaleziono UIData.")
-
Przed rozpoczęciem pętli odliczania, użyj wyrażenia
defer
, aby wyczyścić licznik czasu odliczania z interfejsu gracza za każdym razem, gdy funkcjaCountdownTimer()
zakończy działanie. Zostanie ona ukończona dopiero, gdy skończy się czas lub gdy gracz ponownie zacznie się poruszać. Aby dowiedzieć się więcej, patrz defer.# Opóźnia do czasu uruchomienia HeartBeatWarningTime. Następnie odlicza przez HeartBeatWarningTime i ustawia tekst odliczania. Czyści tekst w przypadku odroczenia. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Rozpoczęcie odliczania bicia serca.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uśpienie na czas przed pojawieniem się ostrzeżenia. Logger.Print("Ostrzeżenie o rozpoczęciu bicia serca.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Odroczenie następuje, gdy funkcja zakończy działanie lub zostanie anulowana, np. gdy przegra wyścig. # W tym przypadku tekst ostrzeżenia jest usuwany po zakończeniu odliczania lub jeśli agent rekwizytów poruszy się przed zakończeniem odliczania. defer: UIData.Text.SetText(HeartBeatWarningClear) # Ustaw tekst ostrzeżenia na pozostały czas, odczekaj sekundę, a następnie zmniejsz pozostały czas. Jeśli odliczanie dobiegnie końca, przerwij pętlę. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("Nie znaleziono UIData.")
-
Na koniec utwórz pętlę, która zmniejsza licznik czasu odliczania. Użyj funkcji
SetText()
, aby wyświetlićHeartBeatWarningMessage
zWarningTimeRemaining
. Następnie odczekaj jedną sekundę zSleep()
, przed zmniejszeniem pozostałego czasu. JeśliWarningTimeRemaining
wynosi 0 lub mniej, odliczanie jest zakończone i można przerwać pętlę.# Opóźnia do czasu uruchomienia HeartBeatWarningTime. Następnie odlicza przez HeartBeatWarningTime i ustawia tekst odliczania. Czyści tekst w przypadku odroczenia. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Rozpoczęcie odliczania bicia serca.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uśpienie na czas przed pojawieniem się ostrzeżenia. Logger.Print("Ostrzeżenie o rozpoczęciu bicia serca.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Odroczenie następuje, gdy funkcja zakończy działanie lub zostanie anulowana, np. gdy przegra wyścig. # W tym przypadku tekst ostrzeżenia jest usuwany po zakończeniu odliczania lub jeśli agent rekwizytów poruszy się przed zakończeniem odliczania. defer: UIData.Text.SetText(HeartBeatWarningClear) # Ustaw tekst ostrzeżenia na pozostały czas, odczekaj sekundę, a następnie zmniejsz pozostały czas. Jeśli odliczanie dobiegnie końca, przerwij pętlę. loop: Logger.Print("Bicie serca za {WarningTimeRemaining} sek.") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("Nie znaleziono UIData.")
Odtwarzanie efektów na bezczynnych graczach
Kiedy AwaitStopMoving()
się zakończy, wiesz, że nadszedł czas, aby rozpocząć odliczanie czasu dla gracza, a następnie odtworzyć efekt bicia serca. Ale gdy tylko gracz zacznie się ponownie poruszać, należy anulować licznik czasu lub bicie serca, w zależności od tego, co jest aktualnie uruchomione. Aby to zrobić, potrzebne jest wyrażenie race
, w którym znajdują się dwa wyrażenia wyścigowe:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance)
. -
block
, gdzie następuje odliczanie przed odtworzeniem efektów bicia serca.
Funkcja AwaitStartMoving()
jest potrzebna do wygrania wyścigu i zatrzymania efektów odliczania licznika czasu lub bicia serca.
Wyrażenie block jest używane do zapewnienia, że dwie funkcje w nim zawarte, CountdownTimer()
i StartHeartbeart()
, działają sekwencyjnie i nie ścigają się ze sobą. Licznik czasu odliczania ma na celu poinformowanie gracza rekwizytów, że jego efekt bicia serca rozpocznie się po zakończeniu odliczania czasu, więc nie miałoby sensu uruchamianie zarówno odliczania czasu, jak i bicia serca w tym samym czasie.
Wykonaj poniższe kroki, aby odtworzyć efekty, gdy gracz zbyt długo pozostaje bezczynny.
- Utwórz metodę rozszerzenia o nazwie
AwaitStartMoving()
, której implementacja jest taka sama, z wyjątkiem poniższych:
-
Sprawdza, czy gracz przesunął się o
MinimumDistance
lub więcej od ostatniej aktualizacji symulacji. Zamiast mniej niżMinimumDistance
jak wAwaitStopMoving()
. -
Nie resetuje
StartPosition
po każdej pętli. GdybyStartPosition
było resetowane na końcu każdej pętli, gracz musiałby przesunąć się o całyMinimumDistance
lub więcej w czasie potrzebnym na wykonanie aktualizacji symulacji, co może być niemożliwe.# Wykonuje pętlę do momentu, gdy agent przesunie się o więcej niż MinimumDistance. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Sprawdzanie, czy agent przemieścił się dalej niż minimalna odległość.") # Pobierz początkowe położenia agenta z postaci agenta w scenie. if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Pobierz położenie agenta w następnym tyknięciu gry. NewPosition := Tracked.GetTransform().Translation # Jeśli odległość nowego położenia w odniesieniu do początkowego położenia jest większa lub równa MinimumDistance, agent przemieścił się i przerywamy pętlę. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("Agent przemieścił się na odległość większą lub równą minimalnej odległości.") break
-
Utwórz funkcję o nazwie
RunPropGameLoop()
, która zarządza odtwarzaniem efektu bicia serca, gdy gracz jest zbyt długo bezczynny.# Jeśli agent rekwizytów przestanie się poruszać, użyj wyrażenia race, aby sprawdzić, czy agent rekwizytów poruszy się poza MinimumMoveDistance, licznik czasu bicia serca zostanie zakończony lub agent rekwizytów zostanie zlikwidowany. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Uruchamianie pętli gry agenta rekwizytów.")
-
Poczekaj, aż agent rekwizytów przesunie się na odległość mniejszą niż minimalna, a następnie przejdź dalej.
# Jeśli agent rekwizytów przestanie się poruszać, użyj wyrażenia race, aby sprawdzić, czy agent rekwizytów poruszy się poza MinimumMoveDistance, licznik czasu bicia serca zostanie zakończony lub agent rekwizytów zostanie zlikwidowany. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Uruchamianie pętli gry agenta rekwizytów.") # Wykonuj pętlę w nieskończoność przez zachowanie rekwizytów, aż agent rekwizytów zostanie zlikwidowany lub gracz opuści sesję. loop: # Poczekaj, aż agent rekwizytów przemieści się na odległość mniejszą niż minimalna, a następnie przejdź dalej. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0)
-
Dodaj wyrażenie
race
, aby ścigać się między zakończeniemAwaitStartMoving()
, co oznacza, że gracz zaczął się poruszać, a wyrażeniemblock
z uruchomionymCountdownTimer()
, a następnieStartHeartbeat()
.# Jeśli agent rekwizytów przestanie się poruszać, użyj wyrażenia race, aby sprawdzić, czy agent rekwizytów poruszy się poza MinimumMoveDistance, licznik czasu bicia serca zostanie zakończony lub agent rekwizytów zostanie zlikwidowany. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Uruchamianie pętli gry agenta rekwizytów.") # Wykonuj pętlę w nieskończoność przez zachowanie rekwizytów, aż agent rekwizytów zostanie zlikwidowany lub gracz opuści sesję. loop: # Poczekaj, aż agent rekwizytów przemieści się na odległość mniejszą niż minimalna, a następnie przejdź dalej. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Dopóki agent rekwizytów nie przesunie się poza minimalną odległość, odliczaj do bicia serca, a następnie odtwarzaj bicie serca w nieskończoność. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Gdy wyścig dobiegnie końca (agent rekwizytów poruszy się), uruchom pętlę ponownie.