Looking for a good tutorial explaning saving games.

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
So I customised my test game to hold a per-game score and an endings achieved list that both show on the status scree.
E.G. this -
TestStatusScreen.png

Each game you play your score goes up when you do certain things as you would expect, 0 to 100%, and I want this to be shown against save games, on the Save/Load screen. I can put text on these no problem, but assume I would need to store and data I want to put here to the save file. Is this correct?
E.G. put variables against each saved game here -
SaveLoadsScreen.png
I also have a 'endings achieved' list that is visible across games. This is held as a .csv file that the ending numbers are added to when a given ending is reached (there are seven in total).
And would like to also indicate the endings achieved to date on the saved file.

I've figured out most things from ether looking at the help file or searching for Ruby commands, but can't seem to find anything that talks about this. So I assume it's ether something that is difficult or can't be done, or I'm missing something so blindingly simple here that it isn't worth mentioning!

Any help would be appreciated.
 

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
What you need is a script that could allow you to do all that stuff except for the csv file because I don't know if Ruby can read it already. I guess that's not the case.
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
I've already got the score (just a game variable) and made the scripts for loading and saving the endings using a CSV file, it wasn't difficult.

I only need some more help/information on how the save game system works to write the extra data to the saved game. Unless I'm just not looking at this correctly! I'l need to have another look at what this does.

#--------------------------------------------------------------------------
# * Called from GameOver script to Update the endings achieved .CSV file
#--------------------------------------------------------------------------
def updateEndingsAchieved
# Read in endings file
file = File.open("Data/endings_data.csv", "r")
file_data = file.read
file.close
# Update and save the file contents if the current ending isn't present
if not file_data[$game_variables[3].to_s]
store_data = file_data + $game_variables[3].to_s + ","
file = File.open("Data/endings_data.csv", "w")
file.write(store_data)
file.close
end
return
end

#--------------------------------------------------------------------------
# * Called from Scene-Menu to Update the endings achieved list on a bitmap
#--------------------------------------------------------------------------
def update_Endings_List
# Read in endings file
file = File.open("Data/endings_data.csv", "r")
file_data = file.read
# Draw the endings list
textYPos = 20
if file_data["1"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 1:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "The Stooge." ,0)
textYPos += 40
end
if file_data["2"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 2:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "Betrayal and Punishment." ,0)
textYPos += 45
end
if file_data["3"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 3:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "Betrayal and Escape." ,0)
textYPos += 45
end
if file_data["4"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 4:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "A Solution of Sorts." ,0)
textYPos += 45
end
if file_data["5"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 5:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "A Hero of Sorts." ,0)
textYPos += 45
end
if file_data["6"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 6:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "An Eternal Ballance." ,0)
textYPos += 45
end
if file_data["7"]
@menusprite.bitmap.draw_text(410, textYPos, 200, 100, "Ending 7:" ,0)
@menusprite.bitmap.draw_text(415, textYPos+20, 200, 100, "Happy After Forever?" ,0)
textYPos += 45
end
return
end
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
Ok I looked at this again. Maybe I was explaining this wrong...
I now have the Score showing up for each saved file!
1656106119669.png

There is a method in Windows_saveFile called refresh to which I added text to this for 'SCORE and 'ENDINGS.'
I can add the saved score to this by using the '@game_variables[5].to_s)' value.
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
# Draw file number
self.contents.font.color = normal_color
name = "File#{@file_index + 1}"
self.contents.draw_text(4, 0, 600, 32, name)
@name_width = contents.text_size(name).width
# If save file exists
if @file_exist
bitmap = RPG::Cache.character(@characters[0][0], @characters[0][1])
self.contents.blt(100, -10, bitmap, Rect.new(0, 0, 100, 200))
self.contents.draw_text(220, 05, 200, 32, "ENDINGS: ")
self.contents.draw_text(220, 35, 200, 32, "SCORE: " + @game_variables[5].to_s)

#end
# Draw play time
hour = @total_sec / 60 / 60
min = @total_sec / 60 % 60
sec = @total_sec % 60
time_string = sprintf("%02d:%02d:%02d", hour, min, sec)
self.contents.font.color = normal_color
self.contents.draw_text(4, 8, 600, 32, time_string, 2)
# Draw timestamp
self.contents.font.color = normal_color
time_string = @time_stamp.strftime("%Y/%m/%d %H:%M")
self.contents.draw_text(4, 40, 600, 32, time_string, 2)
end
end

What I want to do is show the endings achieved after the ENDINGS text.
But the endings is a string read from a .CSV file so I assume I would somehow need to add this to the save file at the time of saving in order to be able to read it back in to display here.

The objects to be saved a stored to the save file in the Scene_Save - ' def write_save_data(file)' method.
# Write each type of game object
Marshal.dump($game_system, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($game_self_switches, file)
Marshal.dump($game_screen, file)
Marshal.dump($game_actors, file)
Marshal.dump($game_party, file)
Marshal.dump($game_troop, file)
Marshal.dump($game_map, file)
Marshal.dump($game_player, file)
But I want to store the 'file_data' string read from the 'Data/endings_data.csv' file to this save file.
Is that possible, or is this just able to save the standard systems objects shown above?

Any help would be appreciated. Am I just mising something obvious here?
 

Attachments

  • 1656103821205.png
    1656103821205.png
    23.1 KB · Views: 3
Last edited:

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
I think I'm going to give up on this for the moment. I've tried several different things, but I clearly don't get enough about the save game process!

What I was thinking is shown in the following script snippets, but when loading in from the file it appears to expect Boolean values for 'switches' not the text string I thought I had saved!?

In def initialize ...
if @file_exist
file = File.open(@filename, "r")
@time_stamp = file.mtime
@characters = Marshal.load(file)
@frame_count = Marshal.load(file)
@game_system = Marshal.load(file)
@game_switches = Marshal.load(file)
@game_variables = Marshal.load(file)
@total_sec = @frame_count / Graphics.frame_rate
@endingsfile_data = Marshal.load(file)
file.close
end

In def refresh ...
if @file_exist
i =0
bitmap = RPG::Cache.character(@characters[0], @characters[1])
cw = bitmap.rect.width / 4
ch = bitmap.rect.height / 4
src_rect = Rect.new(0, 0, cw, ch)
x = 300 - @characters.size * 32 + i * 64 - cw / 2
self.contents.blt(x, 68 - ch, bitmap, src_rect)
self.contents.draw_text(220, 05, 200, 32, "ENDINGS: " + @endingsfile_data.to_s)
self.contents.draw_text(220, 35, 200, 32, "SCORE: " + @game_variables[5].to_s)
#end
#--------------------------------------------------------------------------
# * Write Save Data
# file : write file object (opened)
#--------------------------------------------------------------------------
def write_save_data(file)
# Get the endings string from the CSV file
endingsFile = File.open("Data/endings_data.csv", "r")
endingsfile_data = endingsFile.read
endingsFile.close

# Make character data for drawing save file
characters = []
for i in 0...$game_party.actors.size
actor = $game_party.actors
characters.push([actor.character_name, actor.character_hue])
end
# Write character data for drawing save file
Marshal.dump(characters, file)
# Wrire frame count for measuring play time
Marshal.dump(Graphics.frame_count, file)
# Increase save count by 1
$game_system.save_count += 1
# Save magic number
# (A random value will be written each time saving with editor)
$game_system.magic_number = $data_system.magic_number
# Write each type of game object
Marshal.dump($game_system, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($game_self_switches, file)
Marshal.dump($game_screen, file)
Marshal.dump($game_actors, file)
Marshal.dump($game_party, file)
Marshal.dump($game_troop, file)
Marshal.dump($game_map, file)
Marshal.dump($game_player, file)
Marshal.dump(endingsfile_data, file)
end

I'm obviously doing something very wrong here, didn't think it could be that simple!
If I reference an element in it comes out as printing 'false.'
Just a combination of being new with Ruby and not knowing the RPG maker system very well!
1656158046458.png
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
You do know what a ternary condition is, right? Just leaving you a clue here.
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
I know what a ternary expression is; a statment with possible true and false conditional values.
E.g.
schrodinger's cat == Alive ? "Yes" : "No"
Can have a value of 'yes' or 'No' :smile:
If that's what you mean?

Not seeing how this is going to help me get me a string value out of the stored endingsfile_data object stored in the savegame file though!
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
Let's forget what I've said before and do the following:

Ruby:
file = File.open("file.csv", "r")
string = file.read
n = string.scan("TRUE").size # or "true"
n.to_s # if you ever print it on the console or the popup window or some in game window.
 
Last edited:

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
OK, so by using $game_temp.message_text = $endingsfile_data in the game I can see the string I wan't to show on the file load screen.
E.g.
1656187950489.png
This shows that the text has been read in from the save file.
So what is the difference betwean what's been shown with
$game_temp.message_text = $endingsfile_data
(a global variable that hasen't been set yet when in the 'windows_savefile' class)
- and -
self.contents.draw_text(220, 05, 200, 32, "ENDINGS: " + @endingsfile_data.to_s)
(an instance variable that is read in on all the methods in the 'windows_savefile' class)


From the output below it looks like it is seeing @endingsfile_data in the draw_text method of the 'windows_savefile' class as a Game_SelfSwitchies type and the to_s part is just printing the type name not the contents. So I need this to print the contents of endingsfile_data, which is ''1,2,4,6,5,7,3,'
I.e. this:
1656186370475.png
Thanks for looking.

I can get around this in thw actual game I'm making by just showing a number instead of a list of items. And this is only in a test system. It's just a bit annoying becouse I shur this is close!
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
It seems $endings_filedata is a string and @endings_filedata is a file or a Ruby Object representing it. Otherwise you would just get a string in both cases.
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
Yeh I know, but the only way that global string can be populated with that number string is if the data was read in from the saved game file through the WINDOWS_SAVEFILE class.

So at some point the @endingsfile_data instance object is being converted to the $endingsfile_data global string.

But I can't use the $endingsfile_data global string in the save game title box command as it hasn't been defined at that point.
E.g. self.contents.draw_text(220, 05, 200, 32, "ENDINGS: " + $endingsfile_data)
The above line would just give a null value error.
Using the global variable wouldn't work anyway because then the text for all of the saved game would be the same. I'm just showing this a an example.

What I also don't get is that the 'self.contents.draw_text(220, 35, 200, 32, "SCORE: " + @game_variables[5].to_s)' command works. So the @game_variables object must be comming out in a usable form!?

I'm sure there is an easy way to fix this but the XP help files are... sparce to say the leat.
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
Huh? You can assign the value to that variable if you enter the scene and read the CSV because it's an archive independent from the save games, right? You just need to read the file before you even read the Ruby saved game files. Since it's just a comma separated values file it should always return the string after you read it with string.read

That's why I now think you are just a little confused but once you clear your mind, you will laugh at how easy it was to retrieve that value at any moment.
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
No, why I'm trying to do this is I want to keep a record of what endings were compleatred at the time the save game file was saved. The variable I've got here isn't linked to the two processes that save the current endings when a current game is saved, or to the current endings text list on the status screen. As you say those values are taked directly from the CSV file. The global endings-list variable taken from the save file is never needed or made directly from the CSV file. All variables for this are local to their methods.

The value I'm talking about here is saved to the 'normal' game save file that is used to save all the other game stats when you make a save game, the value I showed above in the popup is from the global variable read in from the 'normal' game save file, not the CSV file - two separate things compleatly.

The idea behind this is that the options screen was going to have an option to revert the endings back to the place when a saved game was taken if the user wanted to.
Again this is a test system that I'm using to test out mechanics not something that has to compleatly make sence as a game, as such!

I do have these two verions of the endings list now (the current one that can be read from the CSV file, and the one made at the time of a previously saved game) so I actualy can make this menu option, I just can't seem to show the text for these on the individual save/load game files..


So:
1) The CSV file holds the current endings achieved.

2) LoadSave files hold saved games with the score and the endings achieved at the time that save game was made.

3) You load a game and are given the option to overwrite the current endings list (in the CSV file) with the one that was stored in the game save file.

(The part where the endings is stared to and loaded from the game save file is working, I just can't show this value on the load/save screen, alongside the score value.)

I hope this explained it a bit better.
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
Then it's weird to see that somewhere in between loading and saving the endings in the saved game, you turn it into a GameSelfSwitches object. Why as a switch? It can only be true or false as you know. It's confusing how you're planning to achieve it with a couple of game self switches...

I would have thought you'd keep it as a string or an array that you can later convert to a string using the join(",") method.

Ruby:
def updateEndingsAchieved
  # Read in endings file
  file = File.open("Data/endings_data.csv", "r")
  file_data = file.read
  file.close
  # Update and save the file contents if the current ending isn't present
  if not file_data[$game_variables[3].to_s]
    store_data = file_data + $game_variables[3].to_s + ","
    file = File.open("Data/endings_data.csv", "w")
    file.write(store_data)
    file.close
  end
  return
end

I suspect the problem lies right where you concatenate both the file_data and the $game_variables[3] variable without double checking if that variable has the right value. Otherwise you would be hiding vital information alias piece of code, namely the root cause of all of your headaches. Yet, that seems to be unlikely...
 
Last edited:

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
Yes that is the problem. I don't know why this is coming back out of the save file as a switch object. It's a string I'm putting into the save file, so why is it a switch object when I'm bringing it out in the def Initialize(file_index, filename) process only.
That's my issue. I don't know if I'm just doing something fundimentaly stupid here. Explanations of the Ruby Marshal. save and load command seem to be saying that you put a string in, and read a string out. So I have no idea why @endingsfile_data = Marshal.load(file) is bringing back a switch type (in this process).

I don't know if I've just done something fundimentaly wrong here or if I'm missing something obvious. If this were truly a switch (only holding true and false, as you say) then how is the string I displayed for $endingsfile_data coming out of the read_save_data(file) method!?
P.s. This value is defenetly not from the CSV file.
Your example is for a CSV file, I don't have an issue with that.

The issue I have is reading and writing the endingsfile_data variable with the built in scripts:
class Scene_Save --> def write_save_data(file) **The built-in method that saves game data.
class Scene_Load--> def read_save_data(file) **The built-in method that loads game data.
These two processed actualy appear to work as expected.
The '$endingsfile_data = Marshal.load(file)' command in Scene_Load--> def read_save_data(file) is bringing in the data correctly as a global ($) string. So this is working as I would expect here.
So saving my 'endingsfile_data' variable to and loading it from the game save file is ok.
It's just the Window_SaveFile class that is reading it as a switch type... why!?
class Window_SaveFile --> def Initialize(file_index, filename) --> def refresh
** This looks for existing saved game files to show on the Load/Save window for selection.

My CSV file is a compleate read herring here, it dosn't interact with this process apart from providing the initial string in the write_save_data(file) method.
#--------------------------------------------------------------------------
# * Write Save Data
# file : write file object (opened)
#--------------------------------------------------------------------------
def write_save_data(file)
# Get the endings string from the CSV file
endingsFile = File.open("Data/endings_data.csv", "r")
endingsfile_data = endingsFile.read
endingsFile.close
** This is the extent of the CSV files involvement in this save process, it makes the endingsfile_data string...

# Make character data for drawing save file
characters = []
for i in 0...$game_party.actors.size
actor = $game_party.actors
characters.push([actor.character_name, actor.character_hue])
end
# Write character data for drawing save file
Marshal.dump(characters, file)
# Wrire frame count for measuring play time
Marshal.dump(Graphics.frame_count, file)
# Increase save count by 1
$game_system.save_count += 1
# Save magic number
# (A random value will be written each time saving with editor)
$game_system.magic_number = $data_system.magic_number
# Write each type of game object
Marshal.dump($game_system, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($game_self_switches, file)
Marshal.dump($game_screen, file)
Marshal.dump($game_actors, file)
Marshal.dump($game_party, file)
Marshal.dump($game_troop, file)
Marshal.dump($game_map, file)
Marshal.dump($game_player, file)
**This is all standard stuff from the origonal games script.

Marshal.dump(endingsfile_data.to_s, file)
** Here I'm puting this string into the normal game save file.

end


I think I'm just going to give up on trying to display the endings string on the Load/Save games screen. As I just don't understand what's hapening there and the actual save/load game methods (scripts) are actually working as expected.


Thanks for looking at this kyonides,
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
501
Reaction score
208
First Language
English
Primarily Uses
RMXP
Are you TOTALLY sure you loaded all of the preexisting objects in the right order?

Now my suspicion gears towards the spot belonging to $game_self_switches because you might have been usurping its rightful place by expecting to get the endings string at least a line before you can actually find it in the game file. Plus this kind of situations might happen when you refuse to alias a method. :D
 

Zeriab

Huggins!
Veteran
Joined
Mar 20, 2012
Messages
1,342
Reaction score
1,549
First Language
English
Primarily Uses
Other
Window_Savefile doesn't load the entire file. It doesn't need to.
Check out the order in which you dump objects into the save file.
  1. Marshal.dump(characters, file)
  2. Marshal.dump(Graphics.frame_count, file)
  3. Marshal.dump($game_system, file)
  4. Marshal.dump($game_switches, file)
  5. Marshal.dump($game_variables, file)
  6. Marshal.dump($game_self_switches, file)
  7. Marshal.dump($game_screen, file)
  8. Marshal.dump($game_actors, file)
  9. Marshal.dump($game_party, file)
  10. Marshal.dump($game_troop, file)
  11. Marshal.dump($game_map, file)
  12. Marshal.dump($game_player, file)
  13. Marshal.dump(endingsfile_data, file)
Next look at the order in which you load objects from your save file
  1. @characters = Marshal.load(file)
  2. @frame_count = Marshal.load(file)
  3. @game_system = Marshal.load(file)
  4. @game_switches = Marshal.load(file)
  5. @game_variables = Marshal.load(file)
  6. @endingsfile_data = Marshal.load(file)
Look at what is put in as number 6? Yup, there's your self-switches

To keep things simple I would put the data as a Game_System variable and then use it to display the endings list. Could for example be @game_switches.endings

*hugs*
- Zeriab
 

Garryg

Veteran
Veteran
Joined
May 16, 2022
Messages
114
Reaction score
48
First Language
English
Primarily Uses
RMXP
Ah! Now I get it. I knew it must be something stupid (obvious), thanks to both of you. I understand and can fix it now. I just wasn't thinking in terms of the order things were saved in the file, which I obviously should have been.

1656248776459.png
I learned quite a bit about the RPG XP system by doing this in my test project, things I can use in my first actual game :smile:
 
Last edited:

Latest Threads

Latest Profile Posts

ScreenShot_8_19_2022_2_3_18.png
FINALLY got the mood system in the game during battle. Since the game is called Panic Attack, I figured you should have certain moods present including Panic. so the main 3 or Hype, Depressed, and Anxious. Panic is only when stunned.
Red_V2.png
Red's design is finally finished (his hair is blue on purpose, it's a joke!). Out of all of the compulsory party members, he spends the most time with you. Just like the character he's based on, he presents himself as a simple person who only wants to help others, but there's obviously more to him than meets the eye.
I drew the cover for my new book. I don 't like to entrust this work to someone else )

WM8Xp2VYvg8.jpg
So if I wanted to share little video clips of my game on here... without using youtube... what would be the most ideal way to do that? FWIW, I use Mega a lot to upload videos and just share the links with my friends.

Forum statistics

Threads
124,684
Messages
1,165,232
Members
163,503
Latest member
Tinoy_C
Top