GML [Solved] ds_maps: How to save/load the room with instances?

FoxyOfJungle

Kazan Games
I am making a customizable game where the player will have to build a mall.
How do I save all instances of 2 different objects and also save global variables such as score and others (All in the same ds_map)?
I need everything to be saved in a ds_map and then use ds_map_write ()

Save/Load Code:

Code:
/// @description Save Level
var _file = "gamedata.dat"


//Create root list
var _root_list = ds_list_create();


//For every instance, create a map
with (obj_par_building)
{
    var _map = ds_map_create();
    ds_list_add(_root_list,_map);
    ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
 
    var _obj = object_get_name(object_index);
    ds_map_add(_map, "obj", _obj);
    ds_map_add(_map, "x", x);
    ds_map_add(_map, "y", y);
}
 
//Wrap the root LIST up in MAP!
var _wrapper = ds_map_create();
ds_map_add_list(_wrapper, "ROOT", _root_list);

//Save all of this to a string
var _string = json_encode(_wrapper)
//var _string = ds_map_write(_wrapper);



//Save file (or upload to server)
file_delete(_file);
var _f = file_text_open_write(_file);
file_text_write_string(_f, _string);
file_text_close(_f);

Code:
/// @description Load Level
var _file = "gamedata.dat"

if (file_exists(_file))
{
    with (obj_par_building) instance_destroy();

    //Load file string contains (can be from server)
    var _s = file_to_string(_file);
 
    //Load wrapper ds_map
    //var _wrapper = ds_map_create();
    //ds_map_read(_wrapper,_s);
    var _wrapper = json_decode(_s);
 
 
 
    //Load list "root" that was added to map.
    var _list = ds_map_find_value(_wrapper,"ROOT");
 
 
    //Load instances
    for (var i=0; i < ds_list_size(_list); i+=1)
    {
        var _map = ds_list_find_value(_list, i);
 
        var _obj = ds_map_find_value(_map, "obj");
        with (instance_create_depth(0,0,0,asset_get_index(_obj)))
        {
            x = ds_map_find_value(_map, "x");
            y = ds_map_find_value(_map, "y");
        }
    }
 
    ds_map_destroy(_wrapper);
 
 
}

The code above can only save one object and does not save other global variables.


After saved:
Currently: (json_encode)




How I want: (ds_map_write)



I had made another similar code but it was very unstable.


As you can see, I saved it as json, but I just want to use data-structure (ds_map) and save everything in just one string, but it doesn't work. Can anyone help me to implement this code (save many objects and others global variables)?

(I have a lot of experience with GameMaker, since 2012, but this is my first time trying to save everything in a ds_map, I already read the manual but I still can't do it in a practical way. I already looked for several related topics but I can't find it!)
 
Last edited:

Yal

🐧 *penguin noises*
GMC Elder
For objects, it's pretty easy.

Code:
with(all){
   //You might wanna exclude controllers and other special objects with some if(object_index == invalidThing){continue} statements here
  somehow_save(x)
  somehow_save(y)
  somehow_save(object_get_name(object_index))
}
You need to save object names (and asset_get_index them when loading) since the indexes might change each time you compile.
 

FoxyOfJungle

Kazan Games
For objects, it's pretty easy.

Code:
with(all){
   //You might wanna exclude controllers and other special objects with some if(object_index == invalidThing){continue} statements here
  somehow_save(x)
  somehow_save(y)
  somehow_save(object_get_name(object_index))
}
You need to save object names (and asset_get_index them when loading) since the indexes might change each time you compile.
The way you suggested it doesn't seem to work for me, because different objects have different variables. I tried but it loaded weird...
Thanks for reply.
 
Last edited:

samspade

Member
Anyone can help? I'm still stuck with this :(
Yal's response is pretty much the best way. It can save things however you want. You just have to set it up. The goal is to store everything in a single map. If you wanted to save different objects different ways you would just loop through them differently - e.g. have one loop for one class or type of objects where you add their x and ys and another loop for a different type where you add their name, etc. however you want.

You could also use the user events. For example, you if you made it so user_event(10) was the save event then you could do this:

Code:
with (all) {
    event_user(10);
}
And that would run event_user(10) for any instance of an object that had one (and wouldn't run or error out if they didn't) and save that instance as you set up in their user event.

This asset is very helpful when working with json structure: https://marketplace.yoyogames.com/assets/8066/json-toolkit

Then you can just use the functions json_save and json_load to get the data in and out.


This video gives a basic idea of JSON structure if you're not familiar:

 

Yal

🐧 *penguin noises*
GMC Elder
The way you suggested it doesn't seem to work for me, because different objects have different variables. I tried but it loaded weird...
Thanks for reply.
Just check the objects and save the variables you want depending on object type, then.
Code:
//Save
switch(object_index){
  case one_thing:
      save(foo)
      save(bar)
   break

   case another_thing:
     //no variables
  break
}

//Load
n = instance_create(read(),read(),read())
switch(n.object_index){
  case one_thing:
     foo = read()
     bar = read()
   break

   case another_thing:
     //no variables
  break
}
 

FoxyOfJungle

Kazan Games
Yal's response is pretty much the best way. It can save things however you want. You just have to set it up. The goal is to store everything in a single map. If you wanted to save different objects different ways you would just loop through them differently - e.g. have one loop for one class or type of objects where you add their x and ys and another loop for a different type where you add their name, etc. however you want.

You could also use the user events. For example, you if you made it so user_event(10) was the save event then you could do this:

Code:
with (all) {
    event_user(10);
}
And that would run event_user(10) for any instance of an object that had one (and wouldn't run or error out if they didn't) and save that instance as you set up in their user event.

This asset is very helpful when working with json structure: https://marketplace.yoyogames.com/assets/8066/json-toolkit

Then you can just use the functions json_save and json_load to get the data in and out.


This video gives a basic idea of JSON structure if you're not familiar:

Just check the objects and save the variables you want depending on object type, then.
Code:
//Save
switch(object_index){
  case one_thing:
      save(foo)
      save(bar)
   break

   case another_thing:
     //no variables
  break
}

//Load
n = instance_create(read(),read(),read())
switch(n.object_index){
  case one_thing:
     foo = read()
     bar = read()
   break

   case another_thing:
     //no variables
  break
}
Thank you very much Yal and samspade, you clarified my mind a lot and after a while thinking and analyzing I managed to make it work perfectly! :D:D:D:)
Sorry for the late reply, I was busy with other things.

Code:
/// @description Save Level
var _file = "gamedata.dat";

//Create root list
var _root_list = ds_list_create();

//Save specific objects variables and create a map for each one
with (all)
{
    //Search
    switch (object_index)
    {
        case obj_game_controller:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "variable", global.VARIABLE);
            break;
      
      
        case obj_build_0:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "x", x);
            ds_map_add(_map, "y", y);
            break;
          
        case obj_character_0:
            var _map = ds_map_create();
            ds_list_add(_root_list,_map);
            ds_list_mark_as_map(_root_list,ds_list_size(_root_list)-1);
            var _obj = object_get_name(object_index);
            ds_map_add(_map, "obj", _obj);
            ds_map_add(_map, "x", x);
            ds_map_add(_map, "y", y);
            break;
      
      
    }
}



//Wrap the root LIST up in MAP!
var _wrapper = ds_map_create();
ds_map_add_list(_wrapper, "ROOT", _root_list);

//Save all of this to a string
var _string = json_encode(_wrapper)
//var _string = ds_map_write(_wrapper);



//Save file (or upload to server)
file_delete(_file);
var _f = file_text_open_write(_file);
file_text_write_string(_f, _string);
file_text_close(_f);

Code:
/// @description Load Level
var _file = "gamedata.dat";


if (file_exists(_file))
{
    //Load file string contains (can be from server)
    var _s = file_to_string(_file);
  
    //Load wrapper ds_map
    //var _wrapper = ds_map_create();
    //ds_map_read(_wrapper,_s);
    var _wrapper = json_decode(_s);
  
    //Load list "root" that was added to map.
    var _list = ds_map_find_value(_wrapper,"ROOT");
  
  
    //Load instances
    with (obj_par_building) instance_destroy();
    with (obj_par_character) instance_destroy();
  
    for (var i=0; i < ds_list_size(_list); i+=1) //loop for all objects
    {
        var _map = ds_list_find_value(_list, i); //map of individual object
        var _obj = asset_get_index(ds_map_find_value(_map, "obj")); //object name that was saved
      
        switch (_obj)
        {
            case obj_game_controller:
                var val = ds_map_find_value(_map, "variable"); global.VARIABLE = val;
                break;
          
          
            case obj_build_0:
                with(instance_create_depth(0,0,0,_obj))
                {
                    var val = ds_map_find_value(_map, "x"); x = val;
                    var val = ds_map_find_value(_map, "y"); y = val;
                }
                break;
              
            case obj_character_0:
                with(instance_create_depth(0,0,0,_obj))
                {
                    var val = ds_map_find_value(_map, "x"); x = val;
                    var val = ds_map_find_value(_map, "y"); y = val;
                }
                break;
          
        }
    }
  
    ds_map_destroy(_wrapper);
}

Now I just have to remove the option to save as json. :)
And I have this present for u2:
One of my favorite songs :p
 
Last edited:
Top