Hey, I am trying to use the config parser for options in a simple game I am making. I just want to be able to change the key bindings and some basic graphics options. I want the game to change these options without restarting, so it loads and updates it constantly.
Things I need some help with:
Fullscreen doesn’t seem to be working when using render.getFullScreen to compare the variables.
Converting strings to key events. (for example getting the string AKEY -> converting to events.AKEY). Simply adding a string there doesn’t work.
Here is what I have so far for the graphics:
from bge import logic, render
import configparser
config = configparser.ConfigParser()
scene = logic.getCurrentScene()
def save():
config["graphics"] = {
"fullscreen":True,
"af":16
}
with open(logic.expandPath("//") + "save.cfg", "w") as cfgFile:
config.write(cfgFile)
def main():
config.read(logic.expandPath("//") + "save.cfg")
render.setAnisotropicFiltering(int(config.get("graphics", "af")))
if not render.getFullScreen() == config.get("graphics", "fullscreen"):
render.setFullScreen(config.get("graphics", "fullscreen"))
No matter what the value is, it just seems to set full screen to true…
This is not related to configureParser. It is a separate problem. I can’t help with that, but I think there were threads dealing with the option to switch to fullscreen mode.
To make sure the recognized configuration is as you expect, print them to console.
AKEY represents a human readable form of a numeric code. The BGE works with the numeric code while we are better in reading the string representation.
What you need is a translation/mapping from string constant to numeric code and back.
Remark: for security reasons, I suggest you do some pre-validation to prevent other Python code than the expected constant names (e.g. check that all strings end with “KEY”).
I use saveGlobalDict() and loadGlobalDict() to save and load game settings
(resolution, audio volume, mouse sensitivity, key bindings, etc…).
Then I have init.py in place to initiate the default values for anything I need in place.
After that script checks if there’s a saved global dictionary file available and try to load values from there.
If something fails, the default values are in place.
from bge import events
def str_to_ev(strKey):
""""
This function will return the bge.events.<key> define for strKey.
If invalid key passed, will return None
"""
# Make sure module has strKey
if hasattr(events, strKey):
# Return bge.event define for strKey
return getattr(events, strKey)
return None
# Convert string to event which is an int
ev = str_to_ev('AKEY')
# Prints out int representation of bge.events.AKEY which is 97
print(ev)
# To see the full list of module defines:
# print(dir(events))
# Or line-by-line:
# for d in dir(events): print(d)
I think this is a lot cleaner and robust
Although, internally, bge.events could have a dict that contains all the events. Furthermore, bge.events.<key> could all be objects that contain conversion methods instead of the conversion functions being defined top level, e.g. bge.events.AKEY.EventToString() instead of bge.events.EventToString().
@Monster: I use main() instead of a python script so I can edit the module in realtime. I also prefer the way it looks. I thought that the value being compared might have been altering the output of the fullscreen (True vs True from variable). Ah I had no idea that eval could be used for that. Brilliant!
@Mperonen: Using globalDict works, however say there is a fatal error that disables the game from running, it’s easier to find and solve the problem in a config file rather than a binary containing the globalDict. It does essentially the same thing, just in a more ordered form.
@Mahalin: Looks like a clean way to set up. I’ll probably end up changing it so if the key returns none, then it sets it to the default
That is why I have init.py in place. It defines the default values generated for the new saved globals file in case the one in use breaks the game. You can just delete the file and a new file will be generated.
User or developer can still edit the init.py file to fizzle with the values. Ofcourse there has to be other checks to make sure that values are in valid form when reading and writing the file.
The usage of a function is a good idea. Giving them a name that tells a reader what it is supposed to do is a brilliant idea ;). “Main” means … um … to be honest - it means nothing. That is the reason why I asked.
[“main” is commonly used as entry point in Python applications. Something that is not valid in the BGE as there can be any number of entry points with any name. There is nothing that prevents us from using descriptive names - except ourselves. ]