O ile wiem, większość gier ma jakiś „system stanu gry”, który przełącza się między różnymi stanami gry; mogą to być na przykład „Intro”, „MainMenu”, „CharacterSelect”, „Ładowanie” i „Gra”.
Z jednej strony sensowne jest rozdzielenie ich na system państwowy. W końcu są one rozbieżne i w przeciwnym razie musiałyby znajdować się w dużej instrukcji przełączania, która jest oczywiście niechlujna; i z pewnością są dobrze reprezentowani przez system państwowy. Ale jednocześnie patrzę na stan „Gry” i zastanawiam się, czy coś jest nie tak z tym podejściem do systemu stanów. Ponieważ to jest jak słoń w pokoju; jest OGROMNY i oczywisty, ale nikt nie kwestionuje podejścia systemu stanu gry.
Wydaje mi się głupie, że „Gra” jest ustawiona na tym samym poziomie, co „Menu główne”. Nie ma jednak sposobu na przełamanie stanu „Gry”.
Czy najlepszym rozwiązaniem jest system stanów gry? Czy istnieje jakaś inna, lepsza technika zarządzania, no cóż, „stanem gry”? Czy można wprowadzać stan, który rysuje film i nasłuchuje, a następnie stan ładowania zapętla się w menedżerze zasobów, a następnie stan gry, który robi praktycznie wszystko ? Czy to również nie wydaje ci się niezrównoważone? Czy coś brakuje?
źródło
Pewnie stan Gry byłby ogromny, ale nie ma powodu, aby sam stan Gry nie mógł zawierać automatu stanów do zarządzania swoimi danymi. Hierarchiczne maszyny stanów są przydatne.
źródło
Zawsze lubię myśleć o każdym „stanie” jak o „scenie”. Film otwierający jest sceną, tylko statyczną. Kredyty są sceną. Menu to scena. Jedyną różnicą między nimi jest poziom interaktywności i logiki gry.
źródło
Właściwie to też mam z tym problemy.
Powiedzmy, że masz grę.
Zamiast zmieniać grę w stan „Ładowanie”, „Menu główne” itp. - IMO lepiej pozwolić, aby gra miała kilka stanów:
„Ładowanie” - „wyświetlanie menu” - „wstrzymane” itp.
Gra nadal działa, ale gdy wyświetli się menu główne, będzie w trybie „pokaż menu”.
A gdy gra nie jest w żadnym konkretnym stanie, po prostu działa.
Przynajmniej dla mnie ma to sens. :)
źródło
Program online (w tradycyjnym znaczeniu online, tj. Ciągłe uruchamianie i reagowanie na dane wejściowe, a nie połączenie z Internetem) zazwyczaj składa się z 3 rzeczy:
Ogólnie rzecz biorąc, te 3 są powiązane i zmieniają się w tym samym czasie. Na przykład podczas wyświetlania ekranu powitalnego możesz zmapować wszystkie klawisze na polecenie „zamknij ekran”, a aktualizacja może powoli zanikać grafikę, a wynik po prostu pokazuje tę grafikę. Ale podczas gry wszystkie klawisze mogą być przypisane do różnych poleceń, a aktualizacja zmienia właściwości wielu obiektów w grze.
Kiedy patrzysz na to w ten sposób, sensowne jest oddzielenie Intro od tworzenia postaci i właściwej gry: każda z nich ma swój własny zestaw zasad wprowadzania, aktualizacji i wyjścia. Są prawie jak samodzielne programy, które dzielą się danymi i kodem biblioteki. Mając to na uwadze, zwykle ma sens tylko jeden stan Gry, ponieważ rozgrywka jest dość jednorodna.
Oczywiście, jeśli faktycznie masz oddzielne typy rozgrywki (np. Przykład RPG - Mapa świata, Mapa miasta, Cutscene, Walka), z różnymi wejściami, aktualizacjami i wynikami, nie ma powodu, dla którego nie miałbyś wielu stanów też zamiast tylko 1 stanu gry. Ale to zależy od twojej gry.
źródło
Patrzę na to z innej strony. „Menu”, „Najlepsze wyniki”, „kredyty” lub „co”, można uznać za kolejny poziom, a wtedy stan ten niekoniecznie jest lżejszy niż stan „gry” (stan gry zawiera po prostu więcej podmiotów, i różne, ale ostatecznie to tylko kolejny poziom, na którym byty wykazują bardziej przewidywalne zachowanie, a „mapy” są na ogół mniej skomplikowane).
Zmiana tego sposobu myślenia zdecydowanie wyciąga cię z syndromu „nudnego menu”.
źródło
W mojej grze mam:
Kierownik realizacji , który inicjuje aplikację (grę), ładuje zasoby, zwalnia zasoby przy wyjściu z aplikacji itp. Inicjuje silnik aplikacji, GameViewEngine, GameLogicEngine.
Game State Manager , który znajduje się w GameLogicEngine i jest odpowiedzialny za kontrolowanie rzeczy związanych z główną pętlą gry: wykrywanie kolizji, obliczanie fizyki, czytanie klawiatury, operacje matematyczne itp.
Początkowo miałem zazwyczaj tylko jednego Game State Managera, który był częścią mojej GameLogicEngine. Miałem jednak pewne trudności z kontrolowaniem inicjalizacji głównych podsystemów (GameLogic, ApplicationEngine, ...). Można było to zrobić, ale było bardziej niechlujne, imo.
Teraz wszystko wydaje mi się bardziej przejrzyste i jestem zadowolony z projektu.
źródło
Zmień nazwę stanu „Gra” na „Gameplay”. Wtedy twoja logika wydaje się lepsza; Zatrzymujesz grę, aby przejść do menu: wychodzisz ze stanu gry, aby przejść do stanu menu głównego.
Ponadto uważam, że rzeczy takie jak pauza, które wymagałyby, aby gra była w tym samym stanie, co po wstrzymaniu gry, nie powinny być osobnymi stanami. Być może państwa dzieci i gniazdowanie? Rozgrywka ma menu pauzy.
źródło
Myślę, że istnieje dobra metoda zwana stosem stanu gry. Nie widziałem żadnych artykułów ani artykułów na ten temat, ale głos rozprzestrzenia się trochę. Zasadniczo najwyższy stan gry na stosie jest nazywany pierwszy i robi wszystko, co chce, z wejściem / renderowaniem itp. Najwyższy stan gry jest jedynym, który może przesuwać lub popować stany.
W moim silniku stany gry są w rzeczywistości tylko listami podmiotów gry. Następnie mam podmioty, które działają jak menu. Moje stany menu albo wstrzymują grę (nie aktualizując następnego elementu na stosie), ale pozwalają innym stanom przesuwać swoje modele do renderera, dzięki czemu moje menu pauzy (które nie obejmuje całego ekranu) nadal renderowanie gry z tyłu.
Mam nadzieję, że daje to wyobrażenie o nieco innym systemie, który nie jest oparty na maszynie stanów.
źródło
To jest w porządku. A przynajmniej jest to poprawa w stosunku do „posiadania dużego brzydkiego przełącznika w zależności od stanu gry”.
Chciałbym zaznaczyć, że w większości gier będziesz już potrzebować pewnego rodzaju maszyny o skończonym stanie, aby poradzić sobie z prostą sztuczną inteligencją jednostek. Typowym przykładem są wrogowie w stanie Bezczynności, Ataku lub Umierania.
Jeśli masz wystarczająco abstrakcyjną maszynę stanów skończonych, możesz jej ponownie użyć zarówno dla obiektu gry, jak i swojej sztucznej inteligencji; nagle nie inwestujesz dużo wysiłku w stan Gry - zamiast tego ponownie używasz kodu, którego użyłeś.
Następuje bezwstydna samo-wtyczka: zaimplementowałem taką maszynę skończoną w mojej bibliotece gier Lua, MiddleClass (konkretnie dodatek o nazwie MindState). Oto, w jaki sposób robisz z tym grę .
źródło
Innym podejściem do tego jest zastosowanie koncepcji ze świata programowania funkcjonalnego zwanej Unią Dyskryminacyjną . Chociaż zwykle znajdują się one w językach FP, można je emulować za pomocą klas .
Zasadniczo Unia dyskryminowana to zawsze jeden z
n
przypadków, a przechowywane dane mogą się różnić w zależności od przypadku.Na przykład:
Oto nasz
GameState
typ może byćMenu
alboPlaying
. Jeśli takMenu
, to będzie zawieraćMenuState
obiekt. Jeśli takPlaying
, to będzie zawieraćSimulationState
obiekt.Aby zaktualizować, będziemy
match
na stanie i odpowiednio wywołać inną funkcję:I podobnie do renderowania:
Jedną z zalet tego podejścia jest to, że można łatwiej obsługiwać różne stany (takie jak zasoby) bez globalizacji lub przekazywania obiektów „usługowych”.
źródło