Mam ekran opcji takich rzeczy jak trudność, rozdzielczość, tryb pełnoekranowy itp., Ale staram się znaleźć „najlepszy” sposób przechowywania / uzyskiwania tych zmiennych w czasie wykonywania.
Obecnie zaimplementowałem Constants
klasę, która zawiera wszystkie GameOption
wyliczenia, ale jak wybrać ustawienie domyślne dla wszystkich tych opcji? Ponadto, jak uzyskać aktualnie wybrany wyliczenie?
Jeśli chodzi o rozdzielczość, postanowiłem zapisać wartości, ale nie jestem pewien, jak uzyskać wartości domyślne lub aktualnie przechowywane. Każdy kierunek byłby świetny; dzięki! :)
namespace V1.test.RPG
{
public class GameOptions
{
public enum Difficulty { EASY, MEDIUM, HARD }
public enum Sound { ON, QUIET, OFF }
public enum Music { ON, QUIET, OFF }
public enum ResolutionWidth
{
SMALL = 1280,
MEDIUM = 1366,
LARGE = 1920,
WIDESCREEN = 2560
}
public enum ResolutionHeight
{
SMALL = 800,
MEDIUM = 768,
LARGE = 1080,
WIDESCREEN = 1080
}
public Boolean fullScreen = false;
}
}
NB: Zapytałem w SO i wskazali mi to miejsce. Jest tam komentarz, ale chciałbym usłyszeć różne sposoby zrobienia tego / najczęściej używane sposoby.
Odpowiedzi:
Planowanie rozwoju:
stałe zakodowane są odpowiednie dla małych projektów, ale w końcu, gdy twoje oprogramowanie powiększy się, będziesz chciał zmienić te ustawienia bez konieczności ponownej kompilacji. Wiele razy będziesz chciał zmienić ustawienia, gdy gra jest uruchomiona i nie możesz tego zrobić za pomocą stałych zakodowanych na stałe.
CVary:
Gdy Twój projekt się rozwinie, możesz rzucić okiem na CVAR . CVAR jest „inteligentną zmienną”, że tak powiem, którą można modyfikować w czasie wykonywania za pomocą konsoli, terminala lub interfejsu użytkownika. CVAR są zwykle implementowane jako obiekt, który otacza podstawową wartość. Obiekt może zatem śledzić wartość, a także zapisywać / ładować ją do / z pliku. Możesz przechowywać obiekty CVAR na mapie, aby uzyskać do nich dostęp za pomocą nazwy lub innego unikalnego identyfikatora.
Aby zilustrować tę koncepcję nieco dalej, następujący pseudo-kod jest prostym przykładem typu CVAR, który otacza
int
wartość:Globalny dostęp:
W powyższym przykładzie założyłem, że konstruktor
CVar
zawsze rejestruje zmienną nacvars
mapie globalnej ; jest to bardzo przydatne, ponieważ pozwala zadeklarować zmienną taką:Ta zmienna jest automatycznie udostępniana na mapie globalnej i możesz uzyskać do niej dostęp z dowolnego miejsca, indeksując mapę nazwą zmiennej:
Trwałość:
gdy gra się wyłącza, iteruj mapę i zapisz wszystkie zmienne oznaczone jako
CVAR_PERSISTENT
, do pliku. Następnym razem, gdy rozpocznie się gra, załaduj je ponownie.Orzecznictwo:
Aby uzyskać bardziej szczegółowy przykład solidnego systemu CVAR, sprawdź implementację opisaną w Doom 3 .
źródło
Po pierwsze, wyliczenie określa, jakie mogą być wartości , a nie jakie są wartości . Dlatego nadal musisz zadeklarować inną zmienną po zadeklarowaniu wyliczenia. Na przykład:
W tym przykładzie możesz teraz ustawić
soundValue
ON, QUIET lub OFF.Następnie musisz tak ustrukturyzować swój kod, aby inne części kodu miały dostęp do tego obiektu „ustawień”. Nie wiem, czy potrzebujesz pomocy w tej części, ale typowe wzorce rozwiązania tego problemu obejmują singletony (te są marszczone w tych dniach), lokalizatory usług lub zastrzyk zależności.
źródło
Rozwiązanie glampert jest bardzo kompletne, ale dodam swoje osobiste doświadczenia.
Natrafiłem na ten sam problem i moim rozwiązaniem było użycie statycznej klasy zmiennych.
Klasa Variables wewnętrznie przechowuje mapę od łańcucha do ciągu (do tej pory wszystkie moje zmienne są tylko łańcuchami) i jest dostępna za pośrednictwem metod pobierających i ustawiających.
Chodzi o to, że uzyskanie dostępu do zmiennych globalnych może wprowadzać wszelkiego rodzaju subtelne błędy, ponieważ całkowicie niepowiązane części kodu nagle zakłócają się nawzajem.
Aby tego uniknąć, narzuciłem następującą semantykę: użycie
set
metody zgłasza wyjątek, jeśli zmienna o takiej nazwie już istnieje w słowniku, iget
usuwa zmienną ze słownika przed jej zwróceniem.Dwie dodatkowe metody zapewniają to, czego można oczekiwać,
setAndOverwrite
orazgetAndKeep
. Istota semantyki innych metod polega na tym, że można łatwo wykryć błędy tego rodzaju: „ta metoda ma inicjować tę zmienną, ale inna metoda zrobiła to wcześniej”.Aby zainicjować słownik, zmienne początkowe są przechowywane w pliku json, a następnie odczytywane po uruchomieniu gry.
Niestety, moja gra nie była jeszcze zbyt daleko, więc nie mogę świadczyć o solidności tego podejścia. Może jednak może zapewnić coś interesującego oprócz CVAR.
źródło