global config file access for a game?

Started by
2 comments, last by ollyb342 12 years, 6 months ago
Afternoon!

I've been writing a first person platformer recently using LWJGL (OpenGL) and Java, and I've hit a slight snag.

My current approach to all configurable game aspects is to have a static class with a load of variables inside, which can be accessed anywhere in the game using this syntax "constants.MAP_DEPTH" (or whatever).

This is fine, as it can be accessed globally with no speed loss or the jiggery pokery of having to pass a "config" object around all the time. But I've recently come to the conclusion that it'd be nice to have all of the configuration in an external file to promote modding/make life easier when I'm making small changes to the game (rather than recompiling>running constantly..)

How are config files usually approached in game development?

I considered having a static class with a static method which can read the config file and return the contents, but this would mean lots and lots of file reading in the game loop and it's just not really appropriate.

I'm sorry if this is a simple question, but I'm up to about 17 classes now and I'm a wee bit stumped!

Hope you can help.
Ollie.

P.S let me know if I've not worded something too well and I'll try and elaborate somewhat!
Advertisement
Don't read the file in the game loop, read it once when the game starts and save the values in the variables you already have.

Or did I misunderstand?
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])

Afternoon!

I've been writing a first person platformer recently using LWJGL (OpenGL) and Java, and I've hit a slight snag.

My current approach to all configurable game aspects is to have a static class with a load of variables inside, which can be accessed anywhere in the game using this syntax "constants.MAP_DEPTH" (or whatever).

This is fine, as it can be accessed globally with no speed loss or the jiggery pokery of having to pass a "config" object around all the time. But I've recently come to the conclusion that it'd be nice to have all of the configuration in an external file to promote modding/make life easier when I'm making small changes to the game (rather than recompiling>running constantly..)

How are config files usually approached in game development?

I considered having a static class with a static method which can read the config file and return the contents, but this would mean lots and lots of file reading in the game loop and it's just not really appropriate.

I'm sorry if this is a simple question, but I'm up to about 17 classes now and I'm a wee bit stumped!

Hope you can help.
Ollie.

P.S let me know if I've not worded something too well and I'll try and elaborate somewhat!


You can change the values of static variables at runtime so initializing your config class using a config file once when the program starts is perfectly doable. (Personally i wouldn't use globals but i'm sure you've heard most of the arguments against it allready).

The easiest way to handle this would probably be the Properties class Java provides for you.

You can create a Properties object as easy as:

Properties config = new Properties();
FileInputStream fs = null;
try {
fs = new FileInputStream("config.cfg");
config.load(fs);
fs.close();
} catch (IOException e) {
//error handling goes here
System.err.println(e);
} catch (InvalidArgumentException e) {
//more error handling
System.err.println(e);
} finally {
if (fs!=null) {
try {
fs.close();
} catch (IOException e) {
//....
}
}
}


The config file should look something like: (You can also use XML data if you use the loadFromXML method rather than the load method)


MAP_DEPTH = 55
MAP_WIDTH = 60
NAMEOF_SOMETHING = Hello
SOMETHING_WITH_A_MULTIPLE_WORD_VALUE = "Hello World"


values can be accessed using:

config.getProperty("MAP_WIDTH"); //you always get the value as a string, convert as needed

if you want a global properties object you can wrap it in a static class like this: (the usual arguments against global state applies and if you think about how you structure your code a bit you can probably limit direct access to the config class to one or two classes removing the need for a global wrapper class)


public class GlobalConfig {
private static Properties config = new Properties();
public loadFromFile(String file) {
FileInputStream fs = null;
try {
fs = new FileInputStream("config.cfg");
config.load(fs);
fs.close();
} catch (IOException e) {
//error handling goes here
System.err.println(e);
} catch (InvalidArgumentException e) {
//more error handling
System.err.println(e);
} finally {
if (fs!=null) {
try {
fs.close();
} catch (IOException e) {
//....
}
}
}
}
public static String getConfigValue(String key) {
return config.getProperty(key);
}
public static void setConfigValue(String key, String value) {
config.setProperty(key,value);
}
public static void saveToFile(String file) {
FileOutputStream fs = null;
try {
fs = new FileOutputStream(file);
config.store(fs,null);
fs.close();
} catch (IOException e) {
//error handling
System.err.println(e);
} finally {
if (fs!=null) {
try {
fs.close();
} catch (IOException e) {
//....
}
}
}
}
}

The GlobalConfig class can then be used like this from anywhere:


//at the start of the main function:
GlobalConfig.loadFromFile("config.cfg");

//at the end of the main function when the program closes or somewhere in the options menu code (Assuming it is possible to change the config from within the game ofcourse, if the config can't change at runtime you don't have to save it again)
GlobalConfig.saveToFile("config.cfg");

//at any place where you need to access a config value:
int MAP_DEPTH = Integer.parseInt(GlobalConfig.getConfigValue("MAP_DEPTH"));
long REALLY_BIG_NUMBER = Long.parseLong(GlobalConfig.getConfigValue("REALLY_BIG_NUMBER"));
String SOME_TEXT = GlobalConfig.getConfigValue("SOME_TEXT");
//your variables obviously don't need to have the same name as the config values name, its perfectly fine to do for example:

long mapVolume = Long.parseLong(GlobalConfig.getConfigValue("MAP_DEPTH")) * Long.parseLong(GlobalConfig.getConfigValue("MAP_WIDTH")) * Long.parseLong(GlobalConfig.getConfigValue("MAP_HEIGHT"));



The indentation in my code is messed up, i really hate the gamedev "editor" ...

Also: I havn't tested the code i wrote, so it might contain errors and might not even compile, but it should give you an idea of how the Properties class can be used atleast.(If you choose to go with it and run into problems just post again and i'm sure me or someone else will be able to provide more help)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
[font="Arial"] [/font]


[font="Arial"]SimonForsman,[/font]
Thanks a lot for that mighty answer! That's explained everything perfectly. I didn't even consider that members in a static class could be instantiated..!

[font="Arial"] Thanks for taking the time for such a comprehensive answer =)

And thanks for answering too Krez, although I actually need to be able to continually grab data out of the global-config-thing, so saving the data in vars before the game loop starts is a no go.

Cheers,
A very happy Ollie.

[/font]
[font="Arial"][/font]
[font="Arial"] [/font]

This topic is closed to new replies.

Advertisement