Załóżmy, że masz grę, w której istnieje wiele (wiele) bytów pełniących niektóre funkcje, z których nie wszystkie są stale potrzebne lub należy je rozpatrywać w każdej ramce. Konkretnym problemem, nad którym pracuję, w którym występuje ten problem, jest szczegółowa symulacja ciała, w tym jego organów.
W grze każde stworzenie ma własne ciało, które jest podzielone na mniejsze części (tułów, nogi itp.), A czasami te części zawierają narządy, które pełnią określoną funkcję w ciele. To, czy organ obecnie służy celowi, czy jest aktywny, nigdy nie jest jasne. W końcu zwierzę może mieć pusty żołądek, który w związku z tym nie musi niczego trawić. Sprawdzanie lub symulacja każdego obiektu w każdej klatce byłoby bardzo śmieszne i bardzo kosztowne, gdy tylko pojawi się wiele stworzeń na świecie. Zastanawiałem się więc nad sposobem inteligentnego rozróżnienia między obiektami, które wymagają aktualizacji, a tymi, które tego nie robią.
To, co wymyśliłem, wydaje się co najmniej dobrym rozwiązaniem. Tworzy prostą kolejkę / stos (istotne jest to, że każdy element jest usuwany natychmiast po jego odczytaniu; kolejność nie ma znaczenia) nazywana „stosem uwagi”, w którym znajdują się obiekty, które należy symulować. Przedmioty wymagające uwagi po prostu ułożyłyby się na stosie lub zostałyby tam umieszczone przez inne obiekty. Obiekty te prawdopodobnie zaimplementują prosty interfejs z funkcją simulate ().
W przypadku mojego poprzedniego przykładu trawienia oznaczałoby to:
Gracz wybiera z ekwipunku coś do jedzenia (zakładając, że to chleb) i wkłada go do ust swojej postaci, a usta umieszcza na stosie uwagi. W następnej klatce usta są pobierane ze stosu i wywoływana jest jego funkcja symulacji (). Ponieważ jest to usta, rozsądnie byłoby symulować tutaj żucie. Może to trwać kilka ramek, w których usta ustawiają się na stosie, dopóki nie zdecydują, że jedzenie jest gotowe do połknięcia. W tym przypadku usta wkładają przeżuty chleb do żołądka (wiem, że nie trafia tam bezpośrednio, ale przełyk jest pominięty dla uproszczenia), który jest następnie umieszczany na stosie uwagi. W następnej ramce rozpoczyna się symulacja procesu trawienia. I tak dalej dla pozostałych niezbędnych narządów.
Przewidywalnym problemem z tym są obiekty na biegu jałowym. Śpiące zwierzę jest tego dobrym przykładem. Można to zrobić zgodnie z wcześniejszym opisem, utrzymując śpiące zwierzę na stosie i za każdym razem sprawdzając, czy trzeba się obudzić, ale wydaje się to marnotrawstwem, ponieważ jest to jedyna rzecz, jaką się robi. Aby uczynić obiekty na biegu jałowym bardziej wydajnym, planowałem dodać rodzaj harmonogramu, który przechowuje zadania do wykonania w określonym czasie. Jeśli zwierzę pójdzie spać, wykona pracę według tego harmonogramu, który będzie zaplanowany na pewien czas po tym, jak zwierzę pójdzie spać. Zadanie to polegałoby na ponownym umieszczeniu śpiącego zwierzęcia na stosie uwagi. Teraz możesz powiedzieć, że śpiące zwierzę, które nie znajduje się na stosie uwagi, może przegapić atak czegoś, ponieważ jego sztuczna inteligencja nie jest symulowana,
Teraz, szczerze mówiąc, nie wiem, czy jest to blisko eleganckiego rozwiązania tego problemu z powodu braku doświadczenia. Czy jestem blisko czegoś użytecznego? Jak to zwykle się robi lub czy ktoś ma jakieś sugestie lub lepsze rozwiązania?
źródło
Brzmi jak problem z wejściami: masz ponad 100 klawiszy na klawiaturze, ale nie chcesz sprawdzać każdego klawisza w każdej ramce, więc co robisz?
Dwie odpowiedzi: ankiety lub komunikaty systemowe.
Sondowanie = w dowolnym momencie, gdy miałoby to znaczenie w grze, sprawdź stan klawiszy klawiatury (lub obiektów, w twoim przypadku). Resztę czasu ignoruj.
Wiadomości = każe klawisz klawiaturowy (obiekt) umieszcza coś w kolejce wiadomości po naciśnięciu lub zwolnieniu (gdy wymaga uwagi). Podczas każdej iteracji pętli gry przegląda kolejkę i rozwiązuje wszystkie wiadomości przed kontynuowaniem.
źródło
Cofnę się więc od wdrożenia i przejrzę pytanie z perspektywy projektowania. Czy masz solidny plan wyświetlania wszystkich szczegółów, które chcesz uwzględnić w tej symulacji?
Na przykład:
Zasadniczo ogólną zasadą jest, aby twoja symulacja nie była bardziej skomplikowana niż jej wyniki. Na koniec dnia, jeśli jedynymi animacjami dla owiec są pasanie się, spanie, ucieczka. Zatem tak naprawdę nie ma znaczenia, ile czynników decyduje o tym, który stan wybrać. Wszyscy gracze zobaczą owce śpiące w nocy, uciekające przed niebezpieczeństwem i jedzące w ciągu dnia.
Symulacja zachowania to mnóstwo zabawy, ale zawsze pamiętaj o wrażeniach użytkowników końcowych.
źródło
Miałem podobny problem z grą, nad którą pracowałem kilka lat temu - symulacja obiektów była złożona i nie można jej było szczegółowo wykonać na każdym obiekcie na świecie.
Rozwiązaniem było użycie koncepcji LOD do symulacji. Obiekty znajdujące się w polu widzenia gracza uruchomiłyby pełną symulację. Obiekty odległe od gracza okresowo przeprowadzały bardzo uproszczoną symulację. Gdy obiekty pojawiły się w polu widzenia gracza, przechodziły z kursu, okresowej aktualizacji symulacji do szczegółowych, regularnych aktualizacji.
źródło
Rozwiązanie z harmonogramem jest dobre. Należy pamiętać, że każdy podmiot powinien mieć listę wskaźników do swoich przyszłych działań, co daje możliwość unieważnienia przyszłych działań w razie potrzeby. To znaczy. śpiące zwierzę budzi się natychmiast po zaatakowaniu, więc musisz anulować jego budzenie w przyszłości.
źródło
Jest na to wzór projektowy. Myślę, że to się nazywa obiekty bazy danych?
Zasadniczo trzymasz jedną „szablonową” owcę, która może reprezentować wszystkie nie-specjalne owce w świecie gry, narysuj je w ten sam sposób, zachowując unikalne dane w obiekcie szablonu, powiedzmy jako tabelę lokalizacji owiec i / lub czasu - od ścinania. Następnie, gdy trzeba uczynić owcę wyjątkową, można utworzyć konkretną instancję do śledzenia tej unikalnej owcy.
To samo dotyczy animacji. Jeśli jest to bezczynna animacja lub zdarzenie wspólne dla każdej instancji, może ona znajdować się w instancji szablonu, gdzie bardziej szczegółowe animacje można zaplanować osobno.
Dawno temu napisałem grę dla konkursu programistycznego, której główna pętla właśnie nazywała się animate () na całej scenie. Wykorzystał wskaźniki funkcji do zastąpienia bezczynnych animacji innymi, stosownie do potrzeb, i zastosował tę technikę do obsługi odziedziczonej animacji (np. Obracając postać stojącą na obracającym się dysku).
Ma to podobny charakter do używania delegata do animacji.
źródło
Czy maszyna stanu działałaby? Zwierzę jest w stanie np. Spania, jedzenia, biegu itd. Do każdego stanu przypisuje się listę aktywnych narządów. Tak więc każdą klatkę, którą odwiedzasz, przełączaj stan, przeglądaj listę organów dla tego stanu i wykonuj aktualizację na każdym z narządów.
źródło