Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have an options Screen for things like Difficulty, Resolution, Full Screen, etc but I'm struggling to find the best way to store/obtain these variables at game time.

The way I've currently decided to do it is to create a 'Constants' class which contains all the GameOption enums. But how do I choose a default for all of these options, and how do I get the currently selected enum?

Especially with that of the resolution - I've decided to store the values but unsure how to get the default or currently stored value?

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;
}

}

any direction would be great, thanks :)

NB: I asked over at SO and they pointed me to this place. There is a comment there but I'd like to hear different ways of doing it / the most used ways. http://stackoverflow.com/questions/24725442/best-way-to-store-game-wide-variables

share|improve this question
1  
You asked in the right place; whoever sent you over here was mistaken. I answered the question anyway to help you out, but this isn't a game development specific question, this is a general programming question. –  jhocking Jul 13 at 19:16
    
I just read the SO thread; I like Scott Chamberlin's answer. –  jhocking Jul 13 at 19:28
    
@jhocking I pointed him this way in case there's any aspects which are particular to game development that might differ from an ordinary application. I also figured you guys might already have a canonical Q&A on this topic since it's so common. –  Chris Hayes Jul 14 at 16:25

3 Answers 3

up vote 23 down vote accepted

Hardcoded constants are fine for small projects, but eventually, as your software grows in size, you will wish you could change those settings without having to recompile everything. Not just that, but many times you will want to change settings while the game is running. You can't do that with hardcoded constants.

Once your project grows, you might want to take a look at CVARs. A CVAR is a "smart variable", so to speak, that you can modify during runtime via a console/terminal or UI and load and save its value from file. CVARs are usually implemented in terms of an object that wraps an underlaying value. The object can then keep track of the value and save/load it from file. You can also store the CVAR object into a map to then be able to access it by a name.

Following is a simple pseudo-code example of a CVAR type that wraps an int value, to illustrate the concept a bit further:

// 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; // default value to rest the variable
};

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

In the example above, I've assumed that the constructor of CVar always registers the variable with the global cvars map. This is quite useful, since it allows you to declare a variable like so:

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

And that variable is made available in the global map. Then, you can access it somewhere else via the map, by its name:

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

And when the game shuts down, you can iterate the map and save the variables marked as CVAR_PERSISTENT to a file, and reload them when the game restarts.

This is just a very rough sketch about the concept, if you would like to see how a real robust CVAR system is implemented, check out the one that was used on Doom 3.

share|improve this answer

Well first off an enum defines what the values can be, not what the values are. Thus you still need to declare another variable after you've declared the enum. For example:

public enum Sound
{
    ON,
    QUIET,
    OFF
}

public Sound soundValue;

In this example, you can now set soundValue to ON, QUIET, or OFF.


Then you still need to structure your code so that other parts of your code can access this "settings" object. I don't know if you need help with that part too, but common patterns to address this problem include singletons (those are frowned on these days) or service locators or dependency injection.

share|improve this answer

glampert solution is very complete, but I will add my personal experience.

I ran into this same problem, and my solution was to use an static Variables class.

The Variables class internally keeps a map from string to string (so far all my variables are only strings) and is accessed via getters and setters.

The point is that getting access to global variables can introduce all kind of subtle errors as totally unrelated parts of the code are suddenly interfering with each other.

In order to avoid this, I imposed the following semantics: using the set method throws an exception if a variable with that name already exists in the dictionary, and get deletes the variable from the dictionary before returning it.

Two additional methods provide what you would expect, setAndOverwrite and getAndKeep. The point of the semantic of the other methods is that you can easily spot errors of the kind "this method is supposed to initialize this variable, but other method did it before".

In order to initialize the dictionary, initial variables are stored in a json file, and then read when the game starts.

Sadly I haven't got too far away with my game yet so I cannot testify for the robustness of this approach. Still, maybe it can provide something interesting on top of CVARs.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.