GML [GM8] Changed sprites not saved

Hey guys! :)

I have a small question about changed sprites and saving.

to make it short:

1. i let the user choose a picture file from a chosen filepath.
2. i change an objects sprite to the opened image.
3. i save the game using the built in save and load function (actually dont need more by now),
4. object has no sprite.

i tried using an ini, but i couldnt really help myself. can i somehow let game maker save that chosen image to the working directory or game directory and then simply load it the enxt time i open the game, or so?
oh P.S: i tried replacing the sprite, but that is not an option, because i have multiple same objects, which can all have a user-inserted image as sprite.

any help appreciated!

Thanks a lot in advance!
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
3. i save the game using the built in save and load function (actually dont need more by now),
As the manual states, game_save\game_load will not save/load changed game resources (and data structures), so you would have to come up with an additional system on top of that.
 
Here is my simple save and load system. You may use it depending your needs. I basicly put the execution codes of those scripts onto the Game Start/Room Start Events and the Closing button/state.
 

Attachments

Here is my simple save and load system. You may use it depending your needs. I basicly put the execution codes of those scripts onto the Game Start/Room Start Events and the Closing button/state.
you posted the same pic twice, was that on purpose? :p
thanks for your reply! I tried ini files too, but i'd rather copy the image the user chose to the game folder.... is that possible in GM8?

Thanks so far! :)
 
As the manual states, game_save\game_load will not save/load changed game resources (and data structures), so you would have to come up with an additional system on top of that.
Oh yea, my bad. thanks!
I tried to program my own storage system, but i feel like ini files is noth the right thing for it... i'd rather save them in the game directory too.
 
So you want to restore an image to load it back. You can simply create an array and save that sprite_index and the image_index, then load them when you need.

Or maybe you can create a variable like that;

//Create Event
ChosenImageNumber = 0; //save that variable in an ini file when saving the game

//Step Event
do an ini read and check the ChosenImageNumber's value.
for example:

if ini read... -don't exactly know the code- = 1 { draw_sprite(x,y,sprIndex1); }
if ini read... = 2 { draw_sprite(x,y,sprIndex2); }
if ini read... = 3 { draw_sprite(x,y,sprIndex3); }
...
 
thanks for the ideas, but I'm really having trouble with ini files...
could you please give me a really specific script example of how to do it? cause it does not work for me.

what i did:
1. let the user open a picture.
2. store it in a variable and save that one to an ini file. (real didnt work. sprites will be put out as real, right? tried string and had problems too.)
3. in the create even of the object which shall have the sprite everytime i start the game: ini open & read the file. like sprite_index = ini_read....

it doesnt work. when i open the game, the object appears to be gone. or probably it doesnt have the sprite, cause it wasnt saved properly or so...
but to prevent this, i tried to give it a standard sprite in case it does not find the saved one...

i'm clueless..

EDIT:

since the ini will be saved in the game folder later, i even bounced out a standalone exe, but no ini file appeared..
 
Here is my save and load script that I've used in my Clicker game called Pixel Clicker that you can check on Android.

All these variables like "TotalPixels" are numbers.

If you can't do it, tell me I'm free and could write you some codes.

EDIT: I forgot that I have posted my codes twice. Sorry don't take it aggressive.
 

Attachments

Last edited:
When you load an image from disk to use as a sprite, that sprite exists in the game memory only and nowhere else.

When you close the game, the data for that sprite is gone. Even if you save the index of the sprite, that value is just an integer / real, and when you run the game again, it will have no relevant meaning, as the sprite data is no longer in memory.

What you need to do, as @Yal suggested above, is to save the sprite data that is in memory back to disk when the game ends, along with the filepath name.

Then when the game loads, you need to load that file into memory and assign that to the players sprite.

Actually, you could just save the file location of the sprite the player chose in the first place, if and only if the sprite data is in the game's working directory.

I recommend you manually save the sprite data to file yourself however, because GameMaker is "sandboxed". It does not have permissions to access files outside of the game folder, UNLESS the player has picked a file using the get_open_filename dialog.

GameMaker then acquires permissions to read that file even if it is not in the game folder, but only at that time.

I use sprite_save() to save the sprite to disk, then I save the name and who the sprite belongs to in an ini file that I can then read at the next game start and then load the file from disk.

Bear in mind that every sprite loaded this way gets placed on its own texture page, so eventually will impact performance if you have too many of them.
 
You can create a variable that holds the selected image's id -variable, or just a number- that you have given to that sprite and load that variable when you need with ini_read this variable
 
You can create a variable that holds the selected image's id -variable, or just a number- that you have given to that sprite and load that variable when you need with ini_read this variable
Yes that would work as long as the image was already part of the game when the executable was created.

If the user is selecting their own sprite to use from file on disk, simply saving and loading the index of that dynamically created sprite won't work.
 
Yes that would work as long as the image was already part of the game when the executable was created.

If the user is selecting their own sprite to use from file on disk, simply saving and loading the index of that dynamically created sprite won't work.
Yes! That's one important advice you gave me there! I didn't know that since im still a noob...
And by the way I'm using GMS now, not gm8. Finally.

Okay, so I will need to do this:

1. Make user load a sprite
2. Save that sprite?
3. Store the objects given picture in an ini file when saving
4. Open the ini file and assign the sprite when the game starts.

?

Could you give me a code example for this? I don't want you to write my code, but I need to see the "correct" code in order to understand it for the future.

Thanks so much you guys!!
 
Note:

- sprite_add() function returns an Index to the sprite.
- You must keep track of the index yourself

Load Sprite From Disk
Code:
var sprite_file_path = get_open_filename("*.*", "*.png")

if ( sprite_file_path == "" )
{
    return 0
}

// Store the file name for future saving
_weapon.sprite_file_name = filename_name(sprite_file_path)  // Extract the file name portion from the complete file path 

sprite_delete(_weapon.sprite); // Delete existing sprite to prevent memory leaks
       
// Here I use SPRITE_ADD function to load the sprite from disk
_weapon.sprite = sprite_add(sprite_file_path, 0, false, false, 0, 0);
   
sprite_set_offset(_weapon.sprite, sprite_get_width(_weapon.sprite) * 0.5, sprite_get_height(_weapon.sprite) * 0.5) ; // Center the sprite x and y offsets

// Here I set the actual sprite_index of the weapon object to the sprite I have loaded from disk.
_weapon.sprite_index = _weapon.sprite;
Save the weapon details to disk.
Code:
var ini_file_name = "weapon_0.ini"
       
ini_open(ini_file_name)
       
// Save weapon name
ini_write_string("weapon_info", "name", _weapon.weapon_name)
       
var section_name = "level_0";

// Save the name of the sprite to the ini file.             
ini_write_string(section_name, "sprite_file_name",  _weapon.sprite_file_name)
           
var sprite_file_path = _weapon.sprite_file_name;

// Save the sprite image to disk
// Note : The user may have selected an image from anywhere on their computer.
// This save function then saves the image to the game data folder, so it can be loaded next time.
// This is because GMS games are sandboxed, and may not have access to the original location.
sprite_save_strip(_weapon.sprite, sprite_file_path)
Game Start, load any customised weapon sprites:
Code:
// open the ini file
var ini_file_name = "weapon_0.ini"
       
ini_open(ini_file_name)
       
// Create a weapon instance to hold data of weapon
var new_weapon = instance_create(x, y, o_weapon);
                       
var section_name = "level_0";

// Load the file name (defaults to laser.png if none found) - laser.png is an Included File   
new_weapon.sprite_file_name = ini_read_string(section_name, "sprite_file_name", "laser.png")  
               
var sprite_file_path = new_weapon.sprite_file_name;

// Load the image file from disk using sprite add                
new_weapon.sprite = sprite_add(sprite_file_path, 0, false, false, 0, 0)  
       
sprite_set_offset(new_weapon.sprite,sprite_get_width(new_weapon.sprite) * 0.5, sprite_get_height(new_weapon.sprite) * 0.5) 

// Assign the sprite to the weapon        
new_weapon.sprite_index = new_weapon.sprite;
 
Note:

- sprite_add() function returns an Index to the sprite.
- You must keep track of the index yourself

Load Sprite From Disk
Code:
var sprite_file_path = get_open_filename("*.*", "*.png")

if ( sprite_file_path == "" )
{
    return 0
}

// Store the file name for future saving
_weapon.sprite_file_name = filename_name(sprite_file_path)  // Extract the file name portion from the complete file path

sprite_delete(_weapon.sprite); // Delete existing sprite to prevent memory leaks
      
// Here I use SPRITE_ADD function to load the sprite from disk
_weapon.sprite = sprite_add(sprite_file_path, 0, false, false, 0, 0);
  
sprite_set_offset(_weapon.sprite, sprite_get_width(_weapon.sprite) * 0.5, sprite_get_height(_weapon.sprite) * 0.5) ; // Center the sprite x and y offsets

// Here I set the actual sprite_index of the weapon object to the sprite I have loaded from disk.
_weapon.sprite_index = _weapon.sprite;
Save the weapon details to disk.
Code:
var ini_file_name = "weapon_0.ini"
      
ini_open(ini_file_name)
      
// Save weapon name
ini_write_string("weapon_info", "name", _weapon.weapon_name)
      
var section_name = "level_0";

// Save the name of the sprite to the ini file.            
ini_write_string(section_name, "sprite_file_name",  _weapon.sprite_file_name)
          
var sprite_file_path = _weapon.sprite_file_name;

// Save the sprite image to disk
// Note : The user may have selected an image from anywhere on their computer.
// This save function then saves the image to the game data folder, so it can be loaded next time.
// This is because GMS games are sandboxed, and may not have access to the original location.
sprite_save_strip(_weapon.sprite, sprite_file_path)
Game Start, load any customised weapon sprites:
Code:
// open the ini file
var ini_file_name = "weapon_0.ini"
      
ini_open(ini_file_name)
      
// Create a weapon instance to hold data of weapon
var new_weapon = instance_create(x, y, o_weapon);
                      
var section_name = "level_0";

// Load the file name (defaults to laser.png if none found) - laser.png is an Included File  
new_weapon.sprite_file_name = ini_read_string(section_name, "sprite_file_name", "laser.png") 
              
var sprite_file_path = new_weapon.sprite_file_name;

// Load the image file from disk using sprite add               
new_weapon.sprite = sprite_add(sprite_file_path, 0, false, false, 0, 0) 
      
sprite_set_offset(new_weapon.sprite,sprite_get_width(new_weapon.sprite) * 0.5, sprite_get_height(new_weapon.sprite) * 0.5)

// Assign the sprite to the weapon       
new_weapon.sprite_index = new_weapon.sprite;
Hey there again...

I tried and tried to implement it in my game, but since I'm really just starting out, I didnt' get it to work right...
A lot of people say things like "well, then you're not ready to learn this by now bla bla bla...".
The point is: I need a practical example. I know you described it pretty precisely, but still I didn't get it to work properly...
My last question is: could we have aksype or teamviewer meeting maybe, where you show me how it works, or at least look into my project, so I can explain you everything meanwhile?
that's be great...

Thanks
 
Let's keep it to the forums for now.

Everything works, except saving it and loading it the next time :D
Could you post exactly what code you are using, and what results you are getting when it doesn't work right.

In the mean time, let's try to simplify it down to the bare minimum.

Create a new test object and setup the following:

Let User Choose a Sprite:
Put this in a Key Pressed Event, like "C" for Choose
Code:
var sprite_file_path = get_open_filename("*.*", "*.png")
if ( sprite_file_path == "" )
{
    return 0
}
// Load the custom sprite
sprite_index = sprite_add(sprite_file_path, 0, 0, 0, 0, 0)
Save the sprite:
Put this in a Key Pressed Event, like "S" for save
Code:
file_name = "image.png"
sprite_save(sprite_index, 0, file_name)

// Save the name of the sprite so you can load it next time
ini_open("images.ini")
ini_write_string("images", "image_name", file_name)
ini_close()
3) Load the sprite:
Put this in a Key Pressed Event, like "L" for load
Code:
ini_open("images.ini")
image_name = ini_read_string("images", "image_name", "default.png")
ini_close()

// Load the sprite from disk
sprite_index = sprite_add(image_name, 0, 0, 0, 0, 0);
See if you can get this working. Start the game, Choose a custom sprite, Save it, Quit Game.

Start Game, Press Load, it should load the custom sprite.

NOTE : This is just a test code to make sure you can get it working. Later, the final version would need to save unique names for the sprites and/or append a number to the filename to make it unique so different objects won't load the same sprite.
 
Top