Piszemy RPGo-Platformówkę (13) – Znajdź, zabij, posprzątaj

Czyli zajmiemy się systemem zadań…

Hej, dzisiaj bez zbędnych wstępów zabierzmy się do dzieła! (oczywiście tradycyjnie zapraszam do samodzielnego zapoznania się ze [zmianami] oraz [demem].

Fabularnie


Każda szanująca się gra RPG ma mniej lub bardziej rozwinięty system zadań. Samo zadanie zazwyczaj polega na wykonaniu jednej (lub większej ilości) prostych czynności, za które dostajemy nagrodę.

Przyjęło się, że zadania otrzymujemy od NPC (postaci niezależnych), ale wciąż się zdarza że takowe możemy po prostu zebrać z czegoś w rodzaju tablicy ogłoszeń.

Chyba nie muszę mówić, że dobrze zaprojektowane zadanie zapewnia pewne odczucie realności świata oraz pozwala na dogłębniejsze jego poznanie. Same zadania mogą składać się z wielu skomplikowanych kwestii dialogowych – świetnym przykładem takiego systemu jest seria gier Wiedźmin (kto nie grał niech się wstydzi ;P).

Tablica ogłoszeń – Wiedźmin 3

W tym wpisie nie chcę mówić o samym konstruowaniu zadań, my w tym projekcie zajmiemy się najbardziej oklepanym typem zadań, masowo wykorzystywanym w grach MMO. A więc…

Znajdź, zabij, posprzątaj…


Ten typ zadań to bardzo łatwo powtarzalna formuła, która uogólnia się do zapisu: „[Znajdź/Zabij/…] N [przedmiotów/potworów], otrzymasz za to X złota, Y doświadczenia, Z dodatkowych przedmiotów (np miecz)”. Każdy kto grał w MMO zna ten schemat dokładnie, podczas gry jedynie co się zmienia w takich zadaniach to ilość i nazwa interesującego nas obiektu.

A więc jak można podejść do zadań tego typu? Przede wszystkim należy zwrócić uwagę, że ogólny schemat jest powtarzalny, a jedynie co powinniśmy wyłapywać podczas gry to pojedyncze zdarzenia, które mogły być celem misji (np zbieranie przedmiotów).

Same zadania wyróżniają się jedynie typem obiektu i ich ilością, można by się było bawić w abstrakcję po klasie Zadanie dla każdego typu zadań (np zbieranie roślin, zabijanie zwierząt), tylko że nie ma takiej potrzeby. Demonstruje to kod poniżej:

Każde zadanie ma swoją nazwę oraz krótki opis. Oprócz tego przewidziana jest nagroda za jego ukończenie w postaci złota i/lub doświadczenia i/lub przedmiotów.

Za weryfikację ukończenia zadania służy metoda IsFinished, która jest wywoływana w momencie przyjścia zdarzenia. Jako parametry przyjmuje typ obiektu, który został np. zebrany oraz ilość tych obiektów (dopuszczamy w ten sposób do sytuacji gdy gracz zbierze kwiatków ze skrzyni jednocześnie). Oprócz tego umożliwia ona wcześniej ustalonej nagrody.

Zbieranie nagrody odbywa się wewnątrz metody IsReward, która zwraca nagrodę w momencie gdy zadanie zostało wykonane, w przeciwnym wypadku zwraca „nagrodę zerową”.

„Tablica Zadań” posiada listę aktualnie wykonywanych zadań. Zajmuje się ona dodawaniem zadań do listy zadań oraz ich wyświetleniem na ekranie (AddQuest).

Zdecydowanie ciekawszym elementem jest metoda Notify, która informuje tablicę o nowym zdarzeniu. Tutaj przeszukujemy listę aktualnie wykonywanych zadań i po kolei aktualizujemy zadania, poprzez ich sprawdzenie czy nie zostały wykonane – jeżeli tak, to pobieramy nagrodę oraz usuwamy zadanie z listy.

Warto też zauważyć, że gdybyśmy chcieli urozmaicić nasze zadania o bardziej skomplikowane funkcje, jak np. „przetrwaj X czasu”, to bez problemu możemy nadpisać metodę Notify i zmienić jej sposób działania (pozostając jednocześnie kompatybilnym z resztą kodu).

Uwaga! W powyższym listingu zaznaczyłem miejsce (linia 42) gdzie możemy dodać kod, który będzie służył do aktualizacji o postępie w zadaniu w GUI. Obecnie takowa informacja nie jest wyświetlana. Ten feature pozostawiam jako ćwiczenie do samodzielnego wykonania.

Teraz możecie powiedzieć: „dobra, dobra; wszystko fajnie, tylko skąd nadchodzi informacja o aktualizacji zadania?”. Pytanie jest z pozoru niewinnie proste, ale może spowodować mały mętlik w głowie.

Rozwiązanie jednak okazuje się dość proste: logujemy wszystkie zdarzenia, które możemy chcieć wykorzystać w zadaniach i je przekazujemy do tablicy zadań przez NotifyNewEvent. W swoim przypadku ograniczyłem się do rozpoznawania zbierania (dowolnych) przedmiotów:

I to tyle ;) W analogiczny sposób możemy dorobić wykrywanie zabijania potworów (to także zostawiam jako ćwiczenie).

W demie, które jest dostępne dla tej lekcji przygotowałem zadanie polegające na zebranie jednego ciasteczka (po czym otrzymuje się m.in. złoto), stworzyłem je z poziomu Unity poprzez dodanie do initialQuests zadania o nazwie „Mmm, Cookies!”, które polega na zebraniu 1 obiektu o type (tagu) „Cookie”, za co dostajemy złoto.

Podsumowanie


Jeżeli chodzi o prosty system zadań, to tyle co mogłem dla Was przygotować. Zdaję sobie sprawę, że można o nich opowiedzieć więcej, ale mówiąc szczerze to można zrobić o zadaniach w grach oddzielny poradnik (a to sobie na razie daruję). W każdej grze system zadań jest trochę inny, a ten który przedstawiłem na pewno stanowi dość popularną bazę pod zapotrzebowania większości gier, innymi słowy: eksperymentujcie (i pochwalcie się wynikami).

Oprócz tego (tradycyjnie) zapraszam do systemu komentarzy, gdzie możecie podzielić się swoją opinią, czy pytaniem. Nie zapomnijcie też śledzić bloga przez social-media (linki w panelu po prawej) oraz pochwalić się nim wśród znajomych (za co bardzo dziękuję).

W kolejnej części zajmiemy się drzewkiem umiejętności.

Code ON!