1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice
  2. NOTICE: We will be applying a Xenforo update on Tuesday 25th of February. This means that from approximately 10:00 to 14:00 BST the forums will be offline (or possibly longer). Sorry for the inconvenience! Official Announcement here.

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

Discussion in 'Programming' started by FoxyOfJungle, Feb 9, 2020.

  1. FoxyOfJungle

    FoxyOfJungle Member

    Joined:
    Jul 18, 2018
    Posts:
    46
    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)

    [​IMG]


    How I want: (ds_map_write)

    [​IMG]

    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: Feb 11, 2020
  2. Yal

    Yal GMC Memer GMC Elder

    Joined:
    Jun 20, 2016
    Posts:
    4,214
    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.
     
  3. FoxyOfJungle

    FoxyOfJungle Member

    Joined:
    Jul 18, 2018
    Posts:
    46
    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: Feb 11, 2020
  4. FoxyOfJungle

    FoxyOfJungle Member

    Joined:
    Jul 18, 2018
    Posts:
    46
    Anyone can help? I'm still stuck with this :(
     
  5. samspade

    samspade Member

    Joined:
    Feb 26, 2017
    Posts:
    2,236
    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:

     
    FoxyOfJungle likes this.
  6. Yal

    Yal GMC Memer GMC Elder

    Joined:
    Jun 20, 2016
    Posts:
    4,214
    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 and sinigrimi like this.
  7. FoxyOfJungle

    FoxyOfJungle Member

    Joined:
    Jul 18, 2018
    Posts:
    46
    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: Feb 15, 2020

Share This Page