Save/Load Code

Discussion in 'Programming' started by Ted Gress, May 25, 2019.

  1. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Hi

    I'm trying to save "sprite_index" to a map but I keep getting this message:

    Code:
    ############################################################################################
    FATAL ERROR in
    action number 1
    of Draw Event
    for object SaveCompleteObject:
    
    Variable <unknown_object>.sprite_index(25, -2147483648) not set before reading it.
     at gml_Script_scr_drac_castle_save (line 23) -               ds_map_add(instanceMap, "sprite_index", instance.sprite_index);
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Script_scr_drac_castle_save (line 23)
    called from - gml_Script_scr_castles_save (line 3) - scr_drac_castle_save();
    called from - gml_Script_scr_save_game (line 10) - scr_castles_save();
    called from - gml_Object_SaveCompleteObject_Draw_0 (line 8) - scr_save_game();
    
    The savefile code is:

    Code:
    if(file_exists("drac_castle.sav"))
    {
        file_delete("drac_castle.sav");
        
    }
    
    var saveFile = file_text_open_write("drac_castle.sav");
    
    
            if (!instance_exists(DraculasCastleObject))
            {
                show_debug_message("Draculas Castle Doesn't Exist");   
            }
            var instance = instance_find(DraculasCastleObject, all);
            
            //convert instance to a ds_map
            var instanceMap = ds_map_create();
            //var list1 = ds_map_create();
            //
                
            ds_map_add(instanceMap, "sprite_index", instance.sprite_index);
            ds_map_add(instanceMap, "image_speed", instance.image_speed);
            ds_map_add(instanceMap, "x", instance.x);
            ds_map_add(instanceMap, "y", instance.y);
            
            ds_map_add(instanceMap, "global-castle_hp", global.castle_hp);
            ds_map_add(instanceMap, "death_sound_flag", instance.death_sound_flag);
            ds_map_add(instanceMap, "global-non_usable", global.non_usable);
            ds_map_add(instanceMap, "castle_myTimer", instance.castle_myTimer);
            ds_map_add(instanceMap, "global-ghost_flag", global.ghost_flag);
            
            ds_map_add(instanceMap, "damage_audio_flag_1", instance.damage_audio_flag_1);
            ds_map_add(instanceMap, "damage_audio_flag_2", instance.damage_audio_flag_2);
            ds_map_add(instanceMap, "damage_audio_flag_3", instance.damage_audio_flag_3);
            ds_map_add(instanceMap, "damage_audio_flag_4", instance.damage_audio_flag_4);
            ds_map_add(instanceMap, "damage_audio_flag_5", instance.damage_audio_flag_5);
            ds_map_add(instanceMap, "damage_audio_flag_6", instance.damage_audio_flag_6);
            
            ds_map_add(instanceMap, "global-you_lose", global.you_lose);
            
            
            
    
            JSONInstance = json_encode(instanceMap);
            
            file_text_write_string(saveFile, JSONInstance);
            //seperate with pipe character
            file_text_write_string(saveFile, "|");
            
            ds_map_destroy(instanceMap);       
            
            
            
    
    ///close the file
    file_text_close(saveFile);
    
    
    
    
    
    
    
     
  2. Danei

    Danei Member

    Joined:
    Mar 23, 2018
    Posts:
    278
    I don't think you're supposed to use all as the 2nd argument in instance_find() like that. Try replacing it with 0 to find the first (and I assume only?) instance of DraculasCastleObject.
     
    SupernaturalCow likes this.
  3. SupernaturalCow

    SupernaturalCow Member

    Joined:
    Sep 11, 2016
    Posts:
    70
    What Danei said - and if you need to save more than one DraculasCastleObject, you'll want to use 'instance_number', and a for loop.

    E.g.
    Code:
    for (var i=0; i<instance_number(object); i++) {
        var _inst = instance_find(object, i);
    
        // DS MAP CODE
    }
    That's when you start nesting maps into lists. Effectively, all "saving a game" is in GameMaker, is reconstructing the GM instance tree in a JSON file. Or at least, it is for these purposes.
     
  4. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Yeah I know. I used all becauase for some reason instance_find(DraculasCastleObject, 0) is returning null.
     
  5. SupernaturalCow

    SupernaturalCow Member

    Joined:
    Sep 11, 2016
    Posts:
    70
    Then you should post a thread about that :p
     
  6. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    That is what I am posting about.
     
  7. Double7

    Double7 Member

    Joined:
    Jan 13, 2017
    Posts:
    12
    I know when I do stuff like this I usually do something dumb. I don't assume you would make the same mistakes but this is what I would check.
    1) Ensure the name of the object is exactly 'DraculasCastleObject'. (also, I'm not sure if instance_find will find child objects or not, so if this is a parent object I would try a child object directly and see if that works.
    2) Make sure the code actually sees the objects. Just print out the count using instance_count() to see if it should be finding those objects. I would just use this instead of instance_exists() to grab more info

    What exactly is "DraculasCastleObject"? is it a parent object?
    Also I am curious why you are doing this in the Draw event
     
  8. SupernaturalCow

    SupernaturalCow Member

    Joined:
    Sep 11, 2016
    Posts:
    70
    Uh, ok. So, what does 'null' mean? -1? -4? undefined? pointer_null? It says in the Docs that you can use 'all', and it substitutes the 'n' argument for 'instance_count-1'. Let's say you have 5 instances of that object. What this means is that you have an instance stored at index 4, and not 0. I'm not intimately familiar with the instance functions, but I'd hazard a guess that when you delete instances, the instance indexing moves to accommodate this change. If that's correct, then my next bet is that you're dealing with an inactive instance. Do you have instance_deactivate code anywhere?

    Regardless, this is likely going to be one of those times when contextual code is helpful. I don't know what returning 'null' means, but if you mean it returns '-4', it's returning the keyword 'noone', which means you don't have any instances there, and the problem is with your instance exist check. If it's just crashing, then we need to know more to help. Show us the code that returns null, like you said.
     
  9. Danei

    Danei Member

    Joined:
    Mar 23, 2018
    Posts:
    278

    I think this means that if you're using 'all' as the first argument, then the maximum value you ought to use as the second one is equivalent to instance_count -1, not that you can use 'all' as the second argument to make any substitutions.



     
  10. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Ok. First off, null is noone in just about most programming languag

    My code that is coming back as no one is the following. It is coming back at no one but I don 't understand how that can be possible considering the object is sitting right in front of me.

    Code:
    if(file_exists("drac_castle.sav"))
    {
        file_delete("drac_castle.sav");
      
    }
    
    var saveFile = file_text_open_write("drac_castle.sav");
    
    
            if (!instance_exists(DraculasCastleObject))
            {
                show_debug_message("Draculas Castle Doesn't Exist"); 
            }
            var instance = instance_find(DraculasCastleObject, 0); //returns no one even though there has to be an instantiation. Thhe can see the castle right in front of me
          
            //convert instance to a ds_map
            var instanceMap = ds_map_create();
            //var list1 = ds_map_create();
            //
              
            ds_map_add(instanceMap, "sprite_index", instance.sprite_index);
    es.

    //////

    I'm getting a related runtime error that is associated with the DraculasCastleObject. Its the
    followinjg:

    Code:
    ___________________________________________
    ############################################################################################
    FATAL ERROR in
    action number 1
    of Draw Event
    for object SaveCompleteObject:
    
    Variable <unknown_object>.sprite_index(25, -2147483648) not set before reading it.
    Variable <unknown_object>.sprite_index(25, -2147483648) not set before reading it.
     at gml_Script_scr_drac_castle_save (line 23) -               ds_map_add(instanceMap, "sprite_index", instance.sprite_index);
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Script_scr_drac_castle_save (line 23)
    called from - gml_Script_scr_castles_save (line 3) - scr_drac_castle_save();
    called from - gml_Script_scr_save_game (line 10) - scr_castles_save();
    called from - gml_Object_SaveCompleteObject_Draw_0 (line 8) - scr_save_game();
    
    FATAL ERROR in action number 1 of Draw Event for object SaveCompleteObject:
    
    
    
     
  11. samspade

    samspade Member

    Joined:
    Feb 26, 2017
    Posts:
    1,870
    I think you've diagnosed your own problem. You're trying to reference an instance that doesn't exist. I also think this is very similar to a question you asked before.

    https://forum.yoyogames.com/index.php?threads/not-set-before-reading-it.62660/#post-376505

    The error message says it doesn't exist, so it doesn't exist. Your code says it doesn't exist, so it doesn't exist. I would figure out why it doesn't exist. I would strongly recommend learning to use the debugger and stepping through your code to figure this out.
     
    EvanSki likes this.
  12. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    samspade: Not sure where to look in the debugger. I know how to use it, I'm just sure how to narrow down the error using it. I'll give it a try....

    Debugger says DraculasCastleObject exists

    Look below. That is the profile in the save screen that is throwing an error.The screen throws an error when it tries to run a save script - the sprite_index specifically
     
    Last edited: Jun 1, 2019
  13. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
  14. EvanSki

    EvanSki Dedicated link provider

    Joined:
    Apr 17, 2018
    Posts:
    438
    Make sure the object your trying to find is there in the same room

    Before runing the save load code
     
  15. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,033
    This doesn't tell you that DraculasCastleObject currently exists, it just tells you that DraculasCastleObject's Step event code has been run by something while the profiler is on. You should be checking the Instances tab, and only at the exact moment when the save is happening.
     
  16. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    How do I turn on instances? Doesn't say in the manual
     
  17. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,033
     
  18. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Yeah I have the All Instances window it just doesn't populate. I apologize ahead of time, I just can't find it in the manual.
     
  19. nacho_chicken

    nacho_chicken Member

    Joined:
    Jun 21, 2016
    Posts:
    302
    If the All Instances window isn't populating it's because there are no instances.

    EDIT: If you have Real-time Debugging enabled. Try enabling that.
     
  20. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    The object, DraculasCastleObject wasn't in the same rom as the save room. So I made a flag that gets set to do the save when you return from save room. It doesn't crash but it doesn't save either.. And yeah, I had to enable real-time debugging.
     
  21. nacho_chicken

    nacho_chicken Member

    Joined:
    Jun 21, 2016
    Posts:
    302
    Then DraculasCastleObject doesn't exist. For all intents and purposes, only objects in the current room are treated as "existing." Like EvanSki said:
     
  22. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Yeah I didn't know that only objects that are in the room are treated as existing. This is going to mnke writing save code a lot lot harder
     
  23. EvanSki

    EvanSki Dedicated link provider

    Joined:
    Apr 17, 2018
    Posts:
    438
    Theres tutorials shaun spalding made a really easy .ini save system
     
  24. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    I would but I've already got over 200 individual save files. And that woujld be a lot of work to recreate.

    [EDIT] Do you have a link for that sav routine? I think I"m g oing to cut my losses if this is easy to set up
     
    Last edited: Jun 4, 2019
  25. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    So, I watched his videos. Everything looks to be straightforward, except saving multiple instances of objects. I have an example here of my problem. I know how to save to file using a ds_map etc.. I just don't know how to partition the instances.The tutorial code I was looking at used | pipes as delimiters. That's fine for saving, but I don't know how to unwrap them.

    Code:
    Fading Gem
    
    var fading_gem_count = instance_number(FadingGemObject);
    
    if (file_exists("fading_gem.sav"))
    {
        file_delete("fading_gem.sav");
        
    }
    
    var saveFile = file_text_open_write("fading_gem.sav");
    
    
    
    for (var i = 0; i< fading_gem_count;i++)
    {
            var instance = instance_find(FadingGemObject, i);
            
            //convert instance to a ds_map
            var instanceMap = ds_map_create();
            
            ds_map_add(instanceMap, "fade_duration", instance.fade_duration);
            ds_map_add(instanceMap, "alpha_step", instance.alpha_step);
            ds_map_add(instanceMap, "movement_speed", instance.movement_speed);
            ds_map_add(instanceMap, "image_alpha", instance.image_alpha);
            ds_map_add(instanceMap, "alpha", instance.alpha);
            
            
                
            
            
            JSONInstance = json_encode(instanceMap);
            
            file_text_write_string(saveFile, JSONInstance);
            //seperate with pipe character
            file_text_write_string(saveFile, "|");
            
            ds_map_destroy(instanceMap);       
            
            
            
            
    
            
    }
    ///close the file
    file_text_close(saveFile);

    The Load FIle:
    Code:
    var gem_counter  = instance_number(FadingGemObject);
    
    
    var loadFile = file_text_open_read("fading_gem.sav");
    
    if (!file_text_eof(loadFile))
        {
            //masetrData one long string
            masterData = file_text_read_string(loadFile);
            
            var SentryArray  = scr_split(masterData, "|");
            var SentryCount = array_length_1d(SentryArray);
            
            if (SentryCount > 0)
            {
                //freach sentry
                for (var i = 0; i < SentryCount; i++)
                {
                    var SentryJSON = sentryArray[i];
                    //deserialize
                    var sentryMap = json_decode(SentryJSON);
        
    
                    for (var i = 0; i< spit_count;i++)
                    {
                            var instance = instance_find(FadingGemObject, i);
            
                            //convert instance to a ds_map
                            var instanceMap = ds_map_create();
            
                                inst = instance_create_depth(_x,_y, -1100, FadingGemObject);   
            
            
            
                            var _fade_duration = ds_map_find_value(instanceMap, "fade_duration")
                            var _alpha_step = ds_map_find_value(instanceMap, "alpha_step")
                            var _movement_speed = ds_map_find_value(instanceMap, "movement_speed")
                            var _image_alpha = ds_map_find_value(instanceMap, "image_alpha")
                            var _alpha = ds_map_find_value(instanceMap, "alpha")
                            
                            inst.fade_duration = _fade_duration;
                            inst.alpha_step = _alpha_step;
                            inst.movement_speed = _movement_speed;
                            inst.image_alpha = _image_alpha;
                            inst.alpha = _alpha;
            
            
                        
                
                            ds_map_destroy(instanceMap);       
                    }
                }
            }
        }
            
    
    
    ///close the file
    file_text_close(loadFile);
     
  26. EvanSki

    EvanSki Dedicated link provider

    Joined:
    Apr 17, 2018
    Posts:
    438
     
  27. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    So, I watched the video on JSON and Save/Load. My problem is that I need some kind of delimter to separate the instances in the map.I have code to save the instances but I don'ot have code to
    load them.


    Save

    Code:
    var fading_gem_count = instance_number(FadingGemObject);
    
    if (file_exists("fading_gem.sav"))
    {
        file_delete("fading_gem.sav");
        
    }
    
    var saveFile = file_text_open_write("fading_gem.sav");
    
    
    
    for (var i = 0; i< fading_gem_count;i++)
    {
            var instance = instance_find(FadingGemObject, i);
            
            //convert instance to a ds_map
            var instanceMap = ds_map_create();
            
            ds_map_add(instanceMap, "fade_duration", instance.fade_duration);
            ds_map_add(instanceMap, "alpha_step", instance.alpha_step);
            ds_map_add(instanceMap, "movement_speed", instance.movement_speed);
            ds_map_add(instanceMap, "image_alpha", instance.image_alpha);
            ds_map_add(instanceMap, "alpha", instance.alpha);
            
            
                
            
            
            JSONInstance = json_encode(instanceMap);
            
            file_text_write_string(saveFile, JSONInstance);
            //seperate with pipe character
            file_text_write_string(saveFile, "|");
            
            ds_map_destroy(instanceMap);       
            
            
            
            
    
            
    }
    ///close the file
    file_text_close(saveFile);
    Load

    Code:
    var gem_counter  = instance_number(FadingGemObject);
    
    
    var loadFile = file_text_open_read("fading_gem.sav");
    
    if (!file_text_eof(loadFile))
        {
            //masetrData one long string
            masterData = file_text_read_string(loadFile);
            
            var SentryArray  = scr_split(masterData, "|");
            var SentryCount = array_length_1d(SentryArray);
            
            if (SentryCount > 0)
            {
                //freach sentry
                for (var i = 0; i < SentryCount; i++)
                {
                    var SentryJSON = sentryArray[i];
                    //deserialize
                    var sentryMap = json_decode(SentryJSON);
        
    
                    for (var i = 0; i< spit_count;i++)
                    {
                            var instance = instance_find(FadingGemObject, i);
            
                            //convert instance to a ds_map
                            var instanceMap = ds_map_create();
            
                                inst = instance_create_depth(_x,_y, -1100, FadingGemObject);   
            
            
            
                            var _fade_duration = ds_map_find_value(instanceMap, "fade_duration")
                            var _alpha_step = ds_map_find_value(instanceMap, "alpha_step")
                            var _movement_speed = ds_map_find_value(instanceMap, "movement_speed")
                            var _image_alpha = ds_map_find_value(instanceMap, "image_alpha")
                            var _alpha = ds_map_find_value(instanceMap, "alpha")
                            
                            inst.fade_duration = _fade_duration;
                            inst.alpha_step = _alpha_step;
                            inst.movement_speed = _movement_speed;
                            inst.image_alpha = _image_alpha;
                            inst.alpha = _alpha;
            
            
                        
                
                            ds_map_destroy(instanceMap);       
                    }
                }
            }
        }
            
    
    
    ///close the file
    file_text_close(loadFile);
    This is the saving of the json string


    Code:
            JSONInstance = json_encode(instanceMap);
            
            file_text_write_string(saveFile, JSONInstance);
            //seperate with pipe character
            file_text_write_string(saveFile, "|");
            

    This is the loading of the jason string
    Code:
     //masetrData one long string
            masterData = file_text_read_string(loadFile);
            
            var SentryArray  = scr_split(masterData, "|");
            var SentryCount = array_length_1d(SentryArray);
            
            if (SentryCount > 0)
            {
                //freach sentry
                for (var i = 0; i < SentryCount; i++)
                {
                    var SentryJSON = sentryArray[i];
                    //deserialize
                    var sentryMap = json_decode(SentryJSON);
        
    
                    for (var i = 0; i< spit_count;i++)
                    {
                            var instance = instance_find(FadingGemObject, i);
            
                            //convert instance to a ds_map
                            var instanceMap = ds_map_create();
            
                                inst = instance_create_depth(_x,_y, -1100, FadingGemObject);   
            
            

     
  28. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    So the latest video by Shaun Spalding uses JSON like I do above. I'm all set except for how to use a delimiter to separate the instances of the objects. For example I have a Simple Brain object and I have 5 instances of it. I need to save the object variables for each individual instance. I'd like to use a pipe to separate them but I don't know how that works with JSON.I basically need a "split" script for JSON
     
  29. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    Why would you want to use a delimited string when you can just use a json structure? Keep in mind that ds_maps and ds_lists can be nested generating a nested json object or array respectively, much better than a string, and definitely easier to manage.

    Just add a ds_list to your save data with your instances in it saved as ds_maps (with every variable as key / value pair in the map)
     
  30. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Nevermind that for right now. I just found a major issue/logic error in my code. I want to save the current state of the game. To do that I was saving the variable instances variables. But there are a lot of variables and I was trying to save them all at once. Let me give you an example. There are eight bats you can choose from to have on the playing field. If I go to save the state of the game at any one time, there coujld be any oneo f those 8 bats on the play field as well as various enemies. But since there is no guarantee there is a bat on the field, there is no guarantee the bats variables are instantiated. So, I'm getting the following error for example (on a global variable):

    Code:
    global variable name 'wind_drop' index (100259) not set before reading it.
     at gml_Script_scr_wind_save (line 24) -               ds_map_add(instanceMap, "global-wind_drop", global.wind_drop);
    ######################################################################################
    ######
    --------------------------------------------------------------------------------------------
    I need a solution that doesn't involve me prototyping all the variables. The game easily has 100 instance variables that need to be saved.
     
  31. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    I am using a JSON String. I used the delimited string because that was what the tutorial I went through used.
    I'm not sure how to decode JSON into a string and maintain the hierarchy.
     
  32. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    I can see that you used a delimiter, but it's totally unnecessary when you have better and built in ways to do the same thing. When you decode (and encode) to json your hierarchy is automatically maintained (in the form of nested data structures) as long as you added your nested data structures using the appropriate functions (ds_map_add_map, ds_list_mark_as_map, ds_map_add_list, etc...).

    I don't remember Shaun's video about JSON suggesting using a delimiter, assuming we are talking about the same one.
     
  33. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    No. He didn't go beyond explaining how to save more than one instance of an object. But more importantly, did you see my other post? The JSON string isn't that big of an issue now that I can't even save to my ds_map
     
  34. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    You will never find the specific and exact code you need for everything you are trying to do, but we are here to help if you are stuck. I'm trying to tell you that the part you miss is related to generating a JSON using nested structures. In the specific: a root ds_map, containing a ds_list of instances (as ds_maps, you already have this part).
    Try reading about nesting data structures in the manual, and eventually come up with something or every question you have in this regard.

    That's another problem, if that's preventing you from testing the json part, solve that first. I'm just replying to the latest of your questions, I figured that since you were asking for something else the other problem was solved.
     
    Last edited: Jun 7, 2019
  35. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    It is preventing me from testing out the json part. I understand that you are just trying to help and I appreciate it. The latest problem kind of struck me and I can't work with a ds_map, ds_list, JSON, etc. without this problem with the variable scope. Any help you could provide would be greatly appreciated.
     
  36. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    As far as I can tell, you were trying to save instances belonging to another room (since you move to a different room to save) and you solved this by calling the save routine when coming back from the save room.

    Given the above, if the instances are not saved, there are a couple of things that come to mind that could cause this:

    - The code for saving is never run. Add a show_debug_message at the top to verify that
    - The code is run, but there are no instances at the time of the save. This could happen if the instance calling the save routine is created before any dracula castle (even in the same step, instances are not created simultaneously). Verify that by using the debugger or a show_debug_message at the top of the script checking the existence of an instance at least (you already did that at some point in a code you posted)
    - Everything runs fine, but there's a problem writing to file or generating the json string. Use a show_debug_message on the json string and check if it's empty or generated as expected.
     
  37. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673


    This is a big problem. Lets say I have four player characters, two castles, and five enemies. But they aren't all on the screen at the time. In reality its more like 8 pc s , 10 enemies, and two towers. If the variables for the sprites etc, have to be in the room to save, how in the world can I tell when they are in the room or not. Especially if they are global variables?
     
  38. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    I think you are very confused about variables, instances and their scope.

    The instances have to exist in the room you are saving them, their variables is just a consequence. By global variables I imagine you are referring to the instance name in the room editor, but if the instances are not there, it doesn’t really matter if the name is a global or not.

    Moreover, by existing I don’t mean visible. An instance can exist even if it’s outside of the screen or invisible. As soon as you change room though they get destroyed. So, if you change room before saving, all instances in the current room are destroyed (unless persistent).

    There are a lot of ways to solve a problem like this, a couple:

    1. save the instances BEFORE going to the save room.
    2. Prepare the json (or the ds_map) before going to the save room and store it in a global. Then, only in the save room, store it to file.
     
    Last edited: Jun 8, 2019
  39. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Ok. So global means global variable. As in: global.myCounter++
    Sorry visible was the wrong word. What I am saying is there are multiple objects that can be instantiated or not instantiated and I don't know how to save them in the main room before switching to say, the save room, when I don't know what objects are saved or what objects to save.

    I think you might not be understanding me. Here is the process. I have a scr_dracula_castle script. It gets called by the master save script, scr_save_game. I enter the main room. I go into the save room which sets a flag to save the game when in the main room. I return to the main room and the save flag begins the save script. The first script to execute has two types of floating brains, they both need to be saved. In this case, one of the floating brains is instantiated, but the other isn't - but could be.

    So let me summarize. I have a room with multiple objects that can be instantiated at various times. How do I write a script to handle that. In addition, I have global variables that cross rooms: may need to be accessed in the main room or both the main room and second room. How do I store that? Say I'm in my save script, I think what I should do is declare an instance of those globals in the create event for every time I use it in an Object. Is that right? I don't see how I can store a global in a ds_map without that variable being instantiated.
     
  40. Danei

    Danei Member

    Joined:
    Mar 23, 2018
    Posts:
    278
    Why not create an obj_saveable object, and make it the parent of every object whose instances will need to be saved. Then, using with, you can loop through each instance that exists, put its relevant variables into a ds_map, and then nest that ds_map inside the larger ds_map that you will ultimately encode into JSON.

    Hypothetical example using made-up variable names:

    Code:
    overarchingSaveMap = ds_map_create();
    var instanceSaveID = 0;
    
    with (obj_saveable){
      var instanceMap = ds_map_create(); //create a submap
      instanceMap[? "objIndex"] = object_index; //save the object index so we know what to create upon load.
    
    
      switch (object_index) {
      case obj_brain:
      
        instanceMap[? "x"] = x;
        instanceMap[? "y"] = y;
        instanceMap[? "hp"] = hp;
       //etc.
      break;
    
    case obj_bat:
     
    instanceMap[? "x"] = x;
        instanceMap[? "y"] = y;
        instanceMap[? "wingspan"] = wingspan;
       //etc.
      break;
    
    case obj_draculas_castle:
     
    instanceMap[? "x"] = x;
        instanceMap[? "y"] = y;
        instanceMap[? "interiorDecorStyle"] = interiorDecorStyle;
        //Obviously I'm just making up variables here, but you can choose which ones each type of object needs to save in a switch like this
      break;
      }
    
    ds_map_add_map(overarchingSaveMap, "instance"+string(instanceSaveID), instanceMap);
    instanceSaveID ++; //put the instance map into the larger map ensuring each one will have a unique key
    
    }
    
    then you will end up with a ds_map of ds_maps, and each of those submaps will contain whatever variables you want them to. You can then encode that as a JSON, and when you decode it upon load, you can iterate through the overarching map with ds_map_find_first() and ds_map_find_next() and run instance creation code every time you pull out a key that starts with "instance".

    As for global variables, you should initialize all of them, even if it's just as noone. That way you'll never try to save a variable that isn't defined. You can just stick them into the same overarching map that you put the instances into, or nest them all in their own submap too, whichever you find easier to work with.
     
    Amon likes this.
  41. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Hi Danei

    Can you tell me if this code is what you are talking about or if I have to change anything, etc...

    Code:
    overarchingSaveMap = ds_map_create();
    var instanceSaveID = 0;
    
    with (obj_saveable){
      var instanceMap = ds_map_create(); //create a submap
      instanceMap[? "objIndex"] = object_index; //save the object index so we know what to create upon load.
    
    
      switch (object_index) {
      case SentryBatObject:
     
     
          ds_map_add(instanceMap, "global-wind_drop", global.wind_drop);
            ds_map_add(instanceMap, "global-wind_drop_myTimer", global.wind_drop_myTimer);
            ds_map_add(instanceMap, "sprite_index", instance.sprite_index);
            ds_map_add(instanceMap, "image_speed", instance.image_speed);
            ds_map_add(instanceMap, "x", instance.x);
            ds_map_add(instanceMap, "y", instance.y);
            
            
            ds_map_add(instanceMap, "snap", instance.snap);
            ds_map_add(instanceMap, "flight", instance.flight);
            ds_map_add(instanceMap, "alarm[0]", instance.alarm[0]);
            ds_map_add(instanceMap, "hp", instance.hp);
        
            ds_map_add(instanceMap, "damage", instance.damage);
            
            ds_map_add(instanceMap, "killed_a_brain", instance.killed_a_brain);
            ds_map_add(instanceMap, "opponent", instance.opponent);
            ds_map_add(instanceMap, "under_attack", instance.under_attack);
            
            
            
            
            ds_map_add(instanceMap, "colliding_flag", instance.colliding_flag);
            ds_map_add(instanceMap, "global-wind_myTimer", global.wind_myTimer);
    
            ds_map_add(instanceMap, "wind_brain_refresh_myTimer", instance.wind_brain_refresh_myTimer);
    
            ds_map_add(instanceMap, "global-push_back_trigger", global.push_back_trigger);
            ds_map_add(instanceMap, "global-push_back_enemy", global.push_back_enemy);
            ds_map_add(instanceMap, "global-old_path", global.old_path);
    
    
            ds_map_add(instanceMap, "play_myTimer", instance.play_myTimer);
            ds_map_add(instanceMap, "played", instance.played);
    
            ds_map_add(instanceMap, "target_placement_x", instance.target_placement_x);
            ds_map_add(instanceMap, "target_placement_y", instance.target_placement_y);
            ds_map_add(instanceMap, "wind_counter", instance.wind_counter);
            
            ds_map_add(instanceMap, "new_bat", instance.new_bat);
        
        
            
    
    
            ds_map_add(instanceMap, "wind_counter", instance.wind_counter);
            
            
            ds_map_add(instanceMap, "brainx", instance.brainx);
            ds_map_add(instanceMap, "brainy", instance.brainy);
            ds_map_add(instanceMap, "sprite_myTimer", instance.sprite_myTimer);
            ds_map_add(instanceMap, "global-old_path", instance.old_path);
            
            ds_map_add(instanceMap, "path_speed", instance.path_speed);
            ds_map_add(instanceMap, "speed", instance.speed);
    break;
      }
    
    ds_map_add_map(overarchingSaveMap, "instance"+string(instanceSaveID), instanceMap);
    instanceSaveID ++; //put the instance map into the larger map ensuring each one will have a unique key
    
    }
    I made a parent object obj_saveable then added all the stuff I want to save as children. But I thought I would have to
    do an instance_exists() somewhere in the code to see if the instance exists in the room to save.


    -Ted
     
  42. Danei

    Danei Member

    Joined:
    Mar 23, 2018
    Posts:
    278
    The with (obj_saveable) should obviate any need to use instance_exists(), because it's only going to run in instances that exist.

    you don't need instance.x, instance.y, etc. the with puts you in the instance's scope. Which is also why you shouldn't be saving global variables inside the with, or putting them in the instance's sub-map at all. Either give all globals their own sub-map, or just put them in the larger map by themselves. I assume you'll be adding more cases to your switch statement as well?
     
  43. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Yes I’ll be adding more cases to the switch
    There are so many instances I’d like to do multiple Ds maps. How would they worked
     
  44. Danei

    Danei Member

    Joined:
    Mar 23, 2018
    Posts:
    278
    That code already does 1 ds_map per instance...Or do you mean multiple overarching maps to house different sets of instances?? If the latter, you'd do it the same way as the above, just with a different overarching map name, and a different set of object index cases inside the switch. I don't see how doing that would help you much, though. It's not like your ds_map is going to run out of room for instances.
     
  45. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    @Danei:

    How would I go about doing the load part? Also I still don't know how to handle globals?? Also like I was saying, for each case statement there is a TON of code and I'd like to split up that switch statement into multiple files so it is readable.

    Also, finally, could you tell me what is wrong with this code? It is creating a save file:

    { "instance0": { "objIndex": 19.000000 } }

    Code wise I have:

    Code:
    overarchingSaveMap = ds_map_create();
    
    var instanceSaveID = 0;
    
    with (obj_saveable){
      var instanceMap = ds_map_create(); //create a submap
      instanceMap[? "objIndex"] = object_index; //save the object index so we know what to create upon load.
    
    
      switch (object_index) {
      case SentryBatObject:
     
            ds_map_add(instanceMap, "target_placement_x", instance.target_placement_x);
            ds_map_add(instanceMap, "target_placement_y", instance.target_placement_y);
            ds_map_add(instanceMap, "wind_counter", instance.wind_counter);
            
            ds_map_add(instanceMap, "new_bat", instance.new_bat);
        
        
            
    
    
            ds_map_add(instanceMap, "wind_counter", instance.wind_counter);
            
            
            ds_map_add(instanceMap, "brainx", instance.brainx);
            ds_map_add(instanceMap, "brainy", instance.brainy);
            ds_map_add(instanceMap, "sprite_myTimer", instance.sprite_myTimer);
            ds_map_add(instanceMap, "global-old_path", instance.old_path);
            
            ds_map_add(instanceMap, "path_speed", instance.path_speed);
            ds_map_add(instanceMap, "speed", instance.speed);
    
        break;
      }
    /*
    case obj_bat:
     
    instanceMap[? "x"] = x;
        instanceMap[? "y"] = y;
        instanceMap[? "wingspan"] = wingspan;
       //etc.
      break;
    
    case obj_draculas_castle:
     
    instanceMap[? "x"] = x;
        instanceMap[? "y"] = y;
        instanceMap[? "interiorDecorStyle"] = interiorDecorStyle;
        //Obviously I'm just making up variables here, but you can choose which ones each type of object needs to save in a switch like this
      break;
      }
    */
    }
            ds_map_add_map(overarchingSaveMap, "instance"+string(instanceSaveID), instanceMap);
            instanceSaveID ++; //put the instance map into the larger map ensuring each one will have a unique key
    
    
    
            JSONInstance = json_encode(overarchingSaveMap);
            show_debug_message("WINDJSON" + JSONInstance);
            //JSONInstance2 = json_encode(list1);
            file_text_write_string(saveFile, JSONInstance);
            
            ds_map_destroy(instanceMap);       
            
    
    ///close the file
    file_text_close(saveFile);
    
    
    
     
    Last edited: Jun 10, 2019
  46. Ted Gress

    Ted Gress Member

    Joined:
    Sep 1, 2016
    Posts:
    673
    Hi. Its been a week. Is there anybody who can help me?
     
  47. Catan

    Catan Member

    Joined:
    Jun 20, 2016
    Posts:
    549
    What have you improved and / or solved during this week? What are you still having trouble with?
     
    rIKmAN likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice