Główna rozgrywka jest już gotowa. Teraz ważne, aby udostępnić graczowi wizualne informacje zwrotne, gdy wykonuje określone akcje, na przykład:
- Znacznik celu wskazujący graczowi, gdzie się udać.
- Zwiększenie wartości na liczniku czasu odliczania, gdy gracz wykona zadanie.
- Rozpoczęcie gry dopiero wówczas, gdy gracz wejdzie do pojazdu.
- Odebranie graczowi dodatkowej pizzy, gdy podniesie nowy przedmiot, aby gracz nie upuszczał pizzy na mapie.
Wykonując ten krok w samouczku Próba czasu: Pogoń za pizzą (Time Trial: Pizza Pursuit), dowiesz się, jak dopracować grę.
Pokazywanie graczowi następnej wybranej strefy odbioru
Aby dodać znacznik celu, który będzie wskazywał graczowi, gdzie ma się udać, wykonaj następujące instrukcje. Zaktualizuj plik game_coordinator_device.verse:
- Dodaj edytowalny obiekt
objective_marker
o nazwiePickupMarker
zawierający specyfikatorpublic
do klasygame_coordinator_device
.@editable PickupMarker<public> : objective_marker = objective_marker{}
- Na początku funkcji
PickupDeliveryLoop()
włącz urządzenie wskaźnika na mapie powiązane z obiektemPickupMarker
i skonfiguruj wyrażeniedefer
, aby dezaktywować i wyłączyć urządzenie po zakończeniu funkcji.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(){} <# Opóźnij wyłączenie urządzenia MapIndicator tak, aby zakończenie pętli PickupDeliveryLoop zawsze kończyło się wyłączeniem znacznika. Wyrażenie defer wykonywane jest także w przypadku anulowania pętli PickupDeliveryLoop. #> defer: if (ValidPlayer := MaybePlayer?): PickupMarker.MapIndicator.DeactivateObjectivePulse(ValidPlayer) PickupMarker.MapIndicator.Disable() PickupMarker.MapIndicator.Enable()
- Po wybraniu kolejnej strefy odbioru przenieś znacznik odbioru do wybranej strefy odbioru i wywołaj funkcję
PickupMarker.MapIndicator.ActivateObjectivePulse()
, aby poprowadzić do niej gracza.race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() Sleep(0.0) PickupMarker.MoveMarker(PickupZone.GetTransform(), ?OverTime := 0.0) if (ValidPlayer := MaybePlayer?): PickupMarker.MapIndicator.ActivateObjectivePulse(ValidPlayer) <# 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)
Zwiększanie wartości na liczniku czasu odliczania, gdy gracz wykona zadanie
Można zachęcić gracza, aby dostarczał przedmioty częściej, nagradzając go przydzieleniem dodatkowego czasu za każdy dostarczony przedmiot.
Postępuj zgodnie z poniższą instrukcją, aby dodać więcej czasu do licznika czasu odliczania:
- W pliku score_manager.verse zmień typ wartości zwracanej przez funkcję
AddPendingScoreToTotalScore()
naint
i dodaj członreturn PendingScore
, aby wykorzystać punkty dodane do całkowitego wyniku w celu zaktualizowania licznika czasu odliczania.AddPendingScoreToTotalScore<public>() : int = set TotalGameScore += PendingScore defer: set PendingScore = 0 UpdateUI() return PendingScore
- W pliku game_coordinator_device.verse dodaj edytowalną wartość typu
float
o nazwieDeliveryBonusSeconds
zawierającą specyfikatorpublic
do definicji klasygame_coordinator_device
. Będzie ona odpowiadała liczbie sekund, jaka ma być dodana do licznika czasu odliczania za każdy punkt uzyskany podczas dostarczenia.# Ile sekund dodać do licznika czasu odliczania, gdy odebrany przedmiot zostanie dostarczony. @editable DeliveryBonusSeconds<public> : float = 20.0
- Zaktualizuj wyrażenie
block
, aby obliczyć premię w postaci czasu i zaktualizować czas pozostały na liczniku czasu odliczania.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) PointsCommitted := ScoreManager.AddPendingScoreToTotalScore() BonusTime : float = DeliveryBonusSeconds * PointsCommitted CountdownTimer.AddRemainingTime(BonusTime) else: Logger.Print("Nie znaleziono następnej strefy DeliveryZone do wybrania.", ?Level := log_level.Error) return # Błąd pętli PickupDeliveryLoop
- W trakcie testu gry widać, że przejście do strefy dostarczania po odebraniu pizzy zwiększa wartość czasu na liczniku czasu odliczania.

Rozpoczynanie gry, gdy gracz wejdzie do pojazdu
Aby rozpocząć grę dopiero, gdy gracz wejdzie do pojazdu, a także skonfigurować zachowanie, gdy gracz opuści pojazd, wykonaj następujące instrukcje:
- Utwórz edytowalne odwołanie do urządzenia generatora pojazdów zawierające specyfikator
public
.@editable VehicleSpawner<public> : vehicle_spawner_atk_device = vehicle_spawner_atk_device{}
- Utwórz funkcję o nazwie
StartGameOnPlayerEntersVehicle()
zawierającą specyfikatoryprivate
isuspends
. Funkcja ta powinna odczekać, aż gracz wejdzie do pojazdu, zanim wywoła funkcjęStartGame()
, a także zaktualizować zmiennąMaybePlayer
o odwołanie do gracza z wejścia do pojazdu. Zaktualizuj metodęOnBegin()
tak, aby wywoływała tę funkcję zamiast funkcjiStartGame()
.OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() # Chcemy jedynie otrzymać powiadomienie, gdy gracz wejdzie do pojazdu po raz pierwszy, aby rozpocząć grę. # Funkcja StartGameOnPlayerEntersVehicle będzie oczekiwać na to zdarzenie, a następnie uruchomi pętlę rozgrywki. StartGameOnPlayerEntersVehicle() StartGameOnPlayerEntersVehicle<private>()<suspends> : void = VehiclePlayer := VehicleSpawner.AgentEntersVehicleEvent.Await() Logger.Print("Gracz wszedł do pojazdu") set MaybePlayer = option{player[VehiclePlayer]} StartGame()
- Skonfiguruj procedurę obsługi dla sytuacji, w której gracz opuszcza pojazd. Utwórz funkcję o nazwie
HandlePlayerExitsVehicle()
zawierającą specyfikatorprivate
.OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() # Po wejściu do pojazdu gracz może go w dowolnej chwili opuścić. # Chcemy wykrywać każde takie zdarzenie i umieszczać gracza z powrotem w pojeździe. VehicleSpawner.AgentExitsVehicleEvent.Subscribe(HandlePlayerExitsVehicle) # Chcemy jedynie otrzymać powiadomienie, gdy gracz wejdzie do pojazdu po raz pierwszy, aby rozpocząć grę. # Funkcja StartGameOnPlayerEntersVehicle będzie oczekiwać na to zdarzenie, a następnie uruchomi pętlę rozgrywki. StartGameOnPlayerEntersVehicle() HandlePlayerExitsVehicle<private>(VehiclePlayer : agent) : void = Logger.Print("Gracz opuścił pojazd. Ponowne przypisywanie gracza do pojazdu") VehicleSpawner.AssignDriver(VehiclePlayer)
Odbieranie dodatkowej pizzy
Aby odebrać graczowi dodatkowe pizze, gdy podniesie nowy przedmiot, tak aby gracz nie upuszczał pizzy na mapę, wykonaj następujące instrukcje:
- Dodaj edytowalne odwołanie do urządzenia usuwacza przedmiotów, które odpowiada za usuwanie pizzy z ekwipunku gracza.
@editable PizzaRemover<public> : item_remover_device = item_remover_device{}
- W funkcji
PickupDeliveryLoop()
usuń pizze z ekwipunku gracza, gdy tylko podniesie przedmiot.loop: if (PickupZone : base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() Sleep(0.0) PickupMarker.MoveMarker(PickupZone.GetTransform(), ?OverTime := 0.0) if (ValidPlayer := MaybePlayer?): PickupMarker.MapIndicator.ActivateObjectivePulse(ValidPlayer) <# 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) <# Usuwamy odebrane przez gracza pizze z jego ekwipunku, aby uniknąć ich kumulacji i konieczności upuszczenia ich na ziemię po przepełnieniu stosu. #> if (RemovingPlayer := MaybePlayer?): PizzaRemover.Remove(RemovingPlayer) # Po pierwszym odbiorze możemy włączyć strefę dostarczania. # Zaktualizuj poziom odbioru i wartość ScoreManager. if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Logger.Print("Nie znaleziono następnej strefy PickupZone do wybrania", ?Level := log_level.Error) return # Błąd pętli PickupDeliveryLoop