I needed something similar when I was collaborating with a friend on a simple shmup. I was doing development and he was doing design. I exposed various game constants in a plain-text .ini file. He could edit them and modify the feel of the game without having to recompile the code.
I came to the same conclusion you did: I used ds_map
. Basically, on startup, my game would run scr_readIni.gml
, which set a bunch of variables. Here's an example:
globalvar options;
options = ds_map_create();
ds_map_add( options, "acceleration", "2.5,2.5" );
ds_map_add( options, "maxspeed", "4.0,4.0" );
ds_map_add( options, "subBeatFirePoints", "0.25,0.75" );
ds_map_add( options, "xPixelOffset", "-24,-24" );
ds_map_add( options, "yPixelOffset", "-24,+24" );
I scoped options
as a global variable so that the appropriate game objects had access to it. There's probably a more elegant method -- there is in most object-oriented languages -- but this was the approach I settled on.
After these variables were set, I'd check for the existence of my .ini file. If it existed, I'd overwrite the variables I had just set with the ones stored in the .ini file.
if( file_exists( global.configFilename )){
ini_open(global.configFilename);
// Read variables : OPTIONS
// (e.g. movement, allowed firing subbeats, etc.)
ds_map_replace( options, "acceleration", ini_read_string( "options", "acceleration", options[? "acceleration"]));
ds_map_replace( options, "maxspeed", ini_read_string( "options", "maxspeed", options[? "maxspeed"]));
ds_map_replace( options, "subBeatFirePoints", ini_read_string( "options", "subBeatFirePoints", options[? "subBeatFirePoints"]));
ds_map_replace( options, "xPixelOffset", ini_read_string( "options", "xPixelOffset", options[? "xPixelOffset"]));
ds_map_replace( options, "yPixelOffset", ini_read_string( "options", "yPixelOffset", options[? "yPixelOffset"]));
ini_close();
return true;
// If .ini file doesn't exist, just return (default settings set above)
} else {
return false;
}
Note that I ended up storing my arrays of reals as a string. When I needed to use them again, I split the string by commas and cast them to reals via a function:
// ds_list_to_reals( input ds_list )
//
// Goes through each item and casts it to a real
inDsList = argument[0];
var i;
for( i = 0; i < ds_list_size( inDsList ); i++ ){
ds_list_replace( inDsList, i, real( ds_list_find_value(inDsList, i) ) );
}
return inDsList;
If I had occasion to revisit this project, I'd probably try to update my code to match the approach taken by Dmi7ry in the other answer.
One last note: if you're interested in saving space, you could simply save the number you're seeding the random number generator with. Then, if you reseed the random number generator with the same number on the next startup, it'll generate the same sequence. Here's a snippet from the official docs:
ini_open("Save.ini")
ini_write_real("Levels", string(level), random_get_seed());
ini_close();
The methods to research are random_get_seed
and random_set_seed
.