Najlepszy sposób na przechowywanie zmiennych dla całej gry


23

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 Constantsklasę, która zawiera wszystkie GameOptionwyliczenia, 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.


1
Zapytałeś we właściwym miejscu; ktokolwiek cię tu przysłał, się mylił. W każdym razie odpowiedziałem na to pytanie, aby ci pomóc, ale nie jest to pytanie specyficzne dla rozwoju gry, jest to ogólne pytanie dotyczące programowania.
jhocking

Właśnie przeczytałem wątek SO; Podoba mi się odpowiedź Scotta Chamberlina.
jhocking

@ jhocking Wskazałem go w ten sposób na wypadek, gdyby były jakieś aspekty związane z tworzeniem gier, które mogą różnić się od zwykłej aplikacji. Pomyślałem też, że macie już kanoniczne pytania i odpowiedzi na ten temat, ponieważ jest to tak powszechne.
Chris Hayes

Styczne do rzeczywistego pytania o globale, proszę nie zakładać, że istnieje tam stały zestaw rozdzielczości.
Lars Viklund,

Odpowiedzi:


32

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 intwartość:

// just some flags to exemplify:
enum CVarFlags {
    CVAR_PERSISTENT, // saved to file once app exits
    CVAR_VOLATILE    // never saved to file
};

class CVar {
public:
    // the constructor registers this variable with the global list of CVars
    CVar(string name, int value, int defaultValue, int flags);

    int getValue();
    void setValue(int v);
    void reset(); // reset to the default value

    // etcetera...

private:
    int flags; // flags like: save-to-file, etc.
    int value; // the actual value
    int defaultValue; // the default value to reset the variable to
};

// global list of all CVars:
map<string, CVar> g_cvars;

Globalny dostęp:
W powyższym przykładzie założyłem, że konstruktor CVarzawsze rejestruje zmienną na cvarsmapie globalnej ; jest to bardzo przydatne, ponieważ pozwala zadeklarować zmienną taką:

CVar my_var = new CVar("my_var", 0, 42, CVAR_PERSISTENT);

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:

CVar v = g_cvars.find("my_var");

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 .


4

Po pierwsze, wyliczenie określa, jakie mogą być wartości , a nie jakie wartości . Dlatego nadal musisz zadeklarować inną zmienną po zadeklarowaniu wyliczenia. Na przykład:

public enum Sound
{
    ON,
    QUIET,
    OFF
}

public Sound soundValue;

W tym przykładzie możesz teraz ustawić soundValueON, 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.


1

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 setmetody zgłasza wyjątek, jeśli zmienna o takiej nazwie już istnieje w słowniku, i getusuwa zmienną ze słownika przed jej zwróceniem.

Dwie dodatkowe metody zapewniają to, czego można oczekiwać, setAndOverwriteoraz getAndKeep. 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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.