7.セーブ画面
1.セーブする情報を増やす
セーブ画面固有のクラスは、シーンクラス Scene_File と ウィンドウクラス Window_SaveFile があります。
セーブデータの書き込みは、Scene_File#write_save_dataで、
セーブデータの読み込みは、Scene_File#read_save_dataで行われています。
Marshal.dumpというのが書き込みで、Marshal.loadが読み込む処理です。
どちらのメソッドも File.open で作成したオブジェクト渡して処理しています。
このオブジェクトは、テキストファイルのようなもので、
Marshal なんちゃらで、内容を1つずつ追加しています。
読み込む場合も1つずつ順番に取り出すので、セーブとロードで同じ順番で処理します。
セーブ情報を増やしたい場合は、ここにMarshal なんちゃらを追加すればいいだけです。
しかし、今回は Game_System クラスにセーブ情報を含める方法を取りたいと思います。
こちらの方が改変箇所も少なくて後々楽なので。
こうしておくと、追加したいデータが複数あっても楽に追加できます。
セーブ画面で、パーティの情報やプレイ時間が表示されると思いますが、
これらは、セーブデータの最初の一部のみを読み込んで表示しています。
そのためアクターやエネミーの情報が多くなっても読み込みに時間が掛かりません。
デフォルトで読み込まれる情報は、イベント変数の情報までです。
(歩行グラ、プレイ時間、BGM、BGS、システム、メッセージ、スイッチ、EV変数)
詳しくはWindow_SaveFile#load_gamedataを確認してください。
このように、デフォルトでシステムの情報もロードされるので、
Game_System クラスに追加する方が都合がいいわけです。
先ほどの情報を参照する場合は、以下のようにします。
仮読み込みは、ウィンドウが作成されるときに Window_SaveFile で行われます。
セーブデータの書き込みは、Scene_File#write_save_dataで、
セーブデータの読み込みは、Scene_File#read_save_dataで行われています。
Marshal.dumpというのが書き込みで、Marshal.loadが読み込む処理です。
どちらのメソッドも File.open で作成したオブジェクト渡して処理しています。
このオブジェクトは、テキストファイルのようなもので、
Marshal なんちゃらで、内容を1つずつ追加しています。
読み込む場合も1つずつ順番に取り出すので、セーブとロードで同じ順番で処理します。
セーブ情報を増やしたい場合は、ここにMarshal なんちゃらを追加すればいいだけです。
しかし、今回は Game_System クラスにセーブ情報を含める方法を取りたいと思います。
こちらの方が改変箇所も少なくて後々楽なので。
class Game_System attr_accessor :save_data alias _original_initialize initialize def initialize _original_initialize @save_data = {} end endセーブ情報を保存しておく変数には、ハッシュを入れておきます。
こうしておくと、追加したいデータが複数あっても楽に追加できます。
$game_system.save_data[:data] = "Test"
セーブ画面で、パーティの情報やプレイ時間が表示されると思いますが、
これらは、セーブデータの最初の一部のみを読み込んで表示しています。
そのためアクターやエネミーの情報が多くなっても読み込みに時間が掛かりません。
デフォルトで読み込まれる情報は、イベント変数の情報までです。
(歩行グラ、プレイ時間、BGM、BGS、システム、メッセージ、スイッチ、EV変数)
詳しくはWindow_SaveFile#load_gamedataを確認してください。
このように、デフォルトでシステムの情報もロードされるので、
Game_System クラスに追加する方が都合がいいわけです。
先ほどの情報を参照する場合は、以下のようにします。
@game_system.save_data[:data]セーブデータの読み込みは、読み込むデータが決定されたときに Scene_File で行われ、
仮読み込みは、ウィンドウが作成されるときに Window_SaveFile で行われます。
2.ステータスの変更
ステータスの描画は、Window_SaveFile#refreshで行われています。
描画する内容を変更するには、この部分を改変すればいいわけですね。
今回は、セーブ回数とセーブした時刻と現在地名を追加したいと思います。
使用できるセーブデータの情報は、Window_SaveFile#load_gamedataで確認してください。
ここで、ステータスに表示するための情報を読み込んでいます。
まずは、セーブ回数からです。
Game_System クラスを見ると、save_count というプロパティが定義されています。
つまり、これを参照して描画してあげればいいわけですね。
Game_System オブジェクトは、@game_systemで参照できます。
#--------------------------------------------------------------------------
# ● セーブ回数の描画
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_save_count(x, y)
self.contents.font.color = system_color
self.contents.draw_text(x, y, @name_width, WLH, "セーブ")
self.contents.font.color = normal_color
self.contents.draw_text(x, y, @name_width, WLH, @game_system.save_count, 2)
end
次にセーブした日時を描画する処理を追加します。
最新のセーブファイルを調べるために @time_stamp変数にファイルの更新日時が保存されています。
この変数は、Time オブジェクトですので Time クラスのメソッドが使用できます。
詳しくはヘルプで調べてください。
#--------------------------------------------------------------------------
# ● セーブ日時の描画
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_save_time(x, y)
text = @time_stamp.strftime("%m'%d %H:%M:%S")
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 180, WLH, text, 2)
end
最後に現在地名です。
この情報はデフォルトでは保存されていないので、1.で追加した機能を使って保存します。
現在地名の取得については、こちらの説明をご覧ください。
現在地情報は、セーブ時に自動で取得して保存して欲しいので、
セーブ前にその処理を追加します。Scene_File#do_save ですね。
#--------------------------------------------------------------------------
# ○ セーブの実行
#--------------------------------------------------------------------------
alias _original_do_save do_save
def do_save
$game_system.save_data[:map] = $data_mapinfos[$game_map.map_id].name
_original_do_save
end
で、Window_SaveFile クラスに戻って描画処理を追加します。
#--------------------------------------------------------------------------
# ● セーブマップの描画
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_save_map(x, y)
self.contents.font.color = system_color
self.contents.draw_text(x, y, 60, WLH, "マップ")
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 200, WLH, @game_system.save_data[:map], 2)
end
以上の作業が終わったら、最後にこれらのメソッドを呼び出して実際に描画するように変更します。
#--------------------------------------------------------------------------
# ○ リフレッシュ
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = normal_color
name = Vocab::File + " #{@file_index + 1}"
self.contents.draw_text(4, 0, 200, WLH, name)
@name_width = contents.text_size(name).width
if @file_exist
draw_party_characters(152, 58)
draw_playtime(0, 34, contents.width - 4, 2)
draw_save_count(4, 32)
draw_save_time(328, 0)
draw_save_map(122, 0)
end
end
3.セーブの削除機能
Aボタンでファイルを削除する機能を追加したいと思います。
ファイルの削除は、File.delete(filename)メソッドで可能です。
セーブファイルを削除したときに効果音を演奏したいので、ちょっと定義しておきます。
サウンドの扱いについては、こちらを参考にしてください。
そこにAボタンが押された場合の処理を追加すれば良さそうですね。
消した後もステータスはそのままなので、ウィンドウのリフレッシュが必要そうです。
Window_SaveFile#refresh を見てみると、@file_existのファイルが存在しているかで
描画するか分岐しているようです。
つまり、@file_exist を false にして、refresh すればいいというわけですね。
確認のため、ウィンドウ作成時にファイルが存在しない場合のデフォルトの処理を見てみます。
Window_SaveFile#initialize から load_gamedata が呼び出されていますね。
ここで @file_exist が初期化されているようなので、ファイル削除後にこのメソッドを呼び出して初期化、
refresh で描画内容を更新という形を取りたいと思います。
ここでちょっと考えて欲しいのですが、Scene_File でこの処理を実装すると
@savefile_windows[@index] という記述が並ぶことになると思います。
ここで行っているのはウィンドウの操作なので、こういうことはファイルの削除も含めて、
ウィンドウ自身にやってもらったほうがよさそうですね。
ファイルを削除した場合は true を、ファイルが無ければ false を返すように定義します。
ファイルの削除は、File.delete(filename)メソッドで可能です。
セーブファイルを削除したときに効果音を演奏したいので、ちょっと定義しておきます。
サウンドの扱いについては、こちらを参考にしてください。
module Sound
# クラッシュ
@@crash = RPG::SE.new("Crash", 80)
def self.play_crash
@@crash.play
end
end
セーブファイルの選択は、Scene_File#update_savefile_selectionで行われているので、そこにAボタンが押された場合の処理を追加すれば良さそうですね。
class Scene_File
#--------------------------------------------------------------------------
# ○ セーブファイル選択の更新
#--------------------------------------------------------------------------
alias _original_update_savefile_selection update_savefile_selection
def update_savefile_selection
if Input.trigger?(Input::A)
if @savefile_windows[@index].file_exist
Sound.play_crash
File.delete(@savefile_windows[@index].filename)
else
Sound.play_buzzer
end
end
_original_update_savefile_selection
end
end
これで、セーブファイルを削除できるようになりましたが、消した後もステータスはそのままなので、ウィンドウのリフレッシュが必要そうです。
Window_SaveFile#refresh を見てみると、@file_existのファイルが存在しているかで
描画するか分岐しているようです。
つまり、@file_exist を false にして、refresh すればいいというわけですね。
確認のため、ウィンドウ作成時にファイルが存在しない場合のデフォルトの処理を見てみます。
Window_SaveFile#initialize から load_gamedata が呼び出されていますね。
ここで @file_exist が初期化されているようなので、ファイル削除後にこのメソッドを呼び出して初期化、
refresh で描画内容を更新という形を取りたいと思います。
ここでちょっと考えて欲しいのですが、Scene_File でこの処理を実装すると
@savefile_windows[@index] という記述が並ぶことになると思います。
ここで行っているのはウィンドウの操作なので、こういうことはファイルの削除も含めて、
ウィンドウ自身にやってもらったほうがよさそうですね。
ファイルを削除した場合は true を、ファイルが無ければ false を返すように定義します。
class Window_SaveFile
#--------------------------------------------------------------------------
# ● セーブファイルの削除
#--------------------------------------------------------------------------
def delete
return false unless @file_exist
File.delete(@filename)
load_gamedata
refresh
return true
end
end
最後に、このメソッドを呼び出すように変えてあげると完成です。
class Scene_File
#--------------------------------------------------------------------------
# ○ セーブファイル選択の更新
#--------------------------------------------------------------------------
alias _original_update_savefile_selection update_savefile_selection
def update_savefile_selection
if Input.trigger?(Input::A)
if @savefile_windows[@index].delete
Sound.play_crash
else
Sound.play_buzzer
end
end
_original_update_savefile_selection
end
end
4.セーブフォルダの変更
セーブファイルは、実行ファイルと同じフォルダに作成されるので、
セーブが増えるとちょっとゴチャゴチャしてきます。
そこで、セーブファイルを1つのファイルにまとめたいと思います。
セーブファイルは、Save1.rvdata のようなファイル名で保存されるので、
そのための処理があるはずです。まず、それを探します。
Save で全検索すると、2箇所引っかかります。
コンティニューの判定とファイル名の作成ですので、
この2箇所を変更すれば良さそうです。
※ Dir.glob メソッドは、半角英数字以外に対応していないので注意してください。
無い場合は作成する処理を追加します。
今度は、ゲームフォルダではなくマイドキュメントにセーブデータを保存したいと思います。
まず、マイドキュメントのパスを取得したいですが、標準の機能ではできませんので、
「ディレクトリ操作」のスクリプトを入手してください。
これで、マイドキュメントのパスをDirEx.pusrで取得できるようになります。
セーブフォルダは、"マイドキュメント/My Games/ゲームタイトル"としたいと思います。
標準機能の Dir.mkdir では、一度に複数のフォルダを作成できないので、
My Games の存在を調べて、TKG Sample の存在を調べるというように処理を分ける必要があります。
セーブが増えるとちょっとゴチャゴチャしてきます。
そこで、セーブファイルを1つのファイルにまとめたいと思います。
セーブファイルは、Save1.rvdata のようなファイル名で保存されるので、
そのための処理があるはずです。まず、それを探します。
Save で全検索すると、2箇所引っかかります。
コンティニューの判定とファイル名の作成ですので、
この2箇所を変更すれば良さそうです。
※ Dir.glob メソッドは、半角英数字以外に対応していないので注意してください。
class Scene_Title #-------------------------------------------------------------------------- # ○ コンティニュー有効判定 #-------------------------------------------------------------------------- def check_continue @continue_enabled = (Dir.glob("Save/Save*.rvdata").size > 0) end end class Scene_File #-------------------------------------------------------------------------- # ○ ファイル名の作成 # file_index : セーブファイルのインデックス (0〜3) #-------------------------------------------------------------------------- def make_filename(file_index) return "Save/Save#{file_index + 1}.rvdata" end endこれだけだと、フォルダが無いときにエラーになるので、
無い場合は作成する処理を追加します。
class Scene_File
#--------------------------------------------------------------------------
# ○ セーブの実行
#--------------------------------------------------------------------------
alias _ori_do_save do_save
def do_save
Dir.mkdir("Save") unless FileTest.directory?("Save")
_ori_do_save
end
end
今度は、ゲームフォルダではなくマイドキュメントにセーブデータを保存したいと思います。
まず、マイドキュメントのパスを取得したいですが、標準の機能ではできませんので、
「ディレクトリ操作」のスクリプトを入手してください。
これで、マイドキュメントのパスをDirEx.pusrで取得できるようになります。
セーブフォルダは、"マイドキュメント/My Games/ゲームタイトル"としたいと思います。
class Scene_File DIR_SAVE = DirEx.pusr + "/My Games/TKG Sample" end変更箇所は先ほどの3箇所なので簡単ですね。
class Scene_Title #-------------------------------------------------------------------------- # ○ コンティニュー有効判定 #-------------------------------------------------------------------------- def check_continue @continue_enabled = (Dir.glob("#{Scene_File::DIR_SAVE}/Save*.rvdata").size > 0) end end class Scene_File #-------------------------------------------------------------------------- # ○ ファイル名の作成 # file_index : セーブファイルのインデックス (0〜3) #-------------------------------------------------------------------------- def make_filename(file_index) return "#{Scene_File::DIR_SAVE}/Save#{file_index + 1}.rvdata" end #-------------------------------------------------------------------------- # ○ セーブの実行 #-------------------------------------------------------------------------- alias _ori_do_save do_save def do_save unless FileTest.directory?(Scene_File::DIR_SAVE) DirEx.mkdir(Scene_File::DIR_SAVE) end _ori_do_save end end今回は、フォルダの階層を作るので DirEx.mkdir を使用します。
標準機能の Dir.mkdir では、一度に複数のフォルダを作成できないので、
My Games の存在を調べて、TKG Sample の存在を調べるというように処理を分ける必要があります。
5.オリジナル
1.ウィンドウの位置の設定
2.タイトルウィンドウを実装
3.コマンドウィンドウを実装
4.ステータスウィンドウを実装
5.セーブデータの追加
[おまけ] セーブファイル削除機能
1.ウィンドウ位置の設定
まず、必要なウィンドウを作成・配置したいと思います。
Scene_File#start でタイトル、コマンド、ステータスの3種類のウィンドウを作成します。
これに伴い Scene_File#terminate も変更します。
2.タイトルウィンドウを実装
タイトルウィンドウは、表示しておくだけので Window_Base で作成します。
コマンドウィンドウで項目名が切れないようにウィンドウのサイズを調整しています。
調整のため縦幅を大きくしたので、デフォルトの文字サイズでは小さい気がします。
そこで、タイトルを描画する前に文字サイズを変更しておきます。
文字は、描画範囲をウィンドウ内容と同じサイズにすると中央にきます。
@saving は、Scene_File#initialize で設定されています。
true ならセーブ、false ならロードなので、その値で分岐して、タイトルの文字を描画します。
3.コマンドウィンドウを実装
Window_SaveCommand クラスを定義します。
Window_Command セクションをコピペしてください。
クラス名を Window_SaveCommand に変更し、
公開インスタンス変数は不要なので削除します。
initialize メソッドの引数も不要なので削除します。
まず、ウィンドウのサイズから書き換えます。
ウィンドウの縦幅はサイズが決まっているので、最初の3行が不要です。
サイズの設定は super で行います。項目は縦並びなので spacing は省略します。
次に項目名の設定です。縦幅 344 だと項目数はピッタリ13項目で納まります。
Array のこのような使い方はヘルプには載っていませんが雰囲気でわかってもらえると思います。
sprintf メソッドの使い方はこちらをご覧ください。
ここで注意する点は、@item_max を設定する位置です。
これは必ず super より後に処理します。
super が呼び出されると @item_max は 1 に変更されるからです。
そして、ウィンドウは縦幅が 56 で作成されます。
そのため @item_max を設定し直した後に create_contents を実行して
ウィンドウ内容を再生成する必要があります。
@column_max はデフォルトで 1 なので、設定は不要です。削除します。
また、refresh メソッドと draw_text メソッドの定義の変更は不要です。
コマンドクラスの定義が完了したので、シーンクラスの設定を行います。
まず start メソッドの @index は、このコマンドウィンドウのインデックスのことなので、
この部分を変更します。
ただし、この @index は処理の要なので消したままにしておくことはできません。
@index の部分を @command_window.index に置換する必要がありますが、
それだとちょっと面倒です。せっかくなので元の処理はなるべくそのまま使いたいです。
そこで update メソッドに @index = @command_window.index を追加して、
元の処理をそのまま使用できるようにします。
ウィンドウの更新部分も忘れずに変更しておきます。
4.ステータスウィンドウを実装
まずは、以下の3つのメソッドを変更します。
Scene_File#create_savefile_windows
Scene_File#dispose_savefile_windows
Scene_File#update_savefile_windows
create_savefile_windows の @item_max は、使用しないので削除します。
dispose_savefile_windows に変更点はありません。
メソッド名がこれだけ違って気持ち悪いので定義しています。
alias を使用して複製してもいいのですが、変更点が出たときのために定義文を書いておきます。
update_savefile_windows の else の処理は不要ですね。
表示されるウィンドウは1つだけなので、selected プロパティを使用せずに
visible プロパティの値でどのウィンドウが選択されているのかを判別します。
すべてのステータスウィンドウは、非表示の状態で作成するので
最初に選択されている項目のウィンドウをここで可視状態に変更します。
ステータスウィンドウは Window_SaveFile クラスを改変して作成します。
ウィンドウは非表示の状態で初期化します。
このままだと画面を開いたときに13ページも描画されて重くなってしまうので
ウィンドウが可視状態になったときに描画を行うようにします。
リフレッシュしたら描画済みフラグをONにして、次回からは再描画しないようにします。
リフレッシュの処理を変更します。
描画する項目は、ファイル番号、タイムスタンプ、マップ画像、マップ名、
パーティ、プレイ時間、所持金、の7項目です。
@name_width はカーソルの幅ですので、不要です。
Window_Base のメソッドをコピペしながら実装します。
特に難しいところもないと思います。
いつも通りの文字色変えて文字描画しての繰り返しです。
ウィンドウを切り替えるための処理が必要なので Scene_File#update を変更します。
選択しているセーブデータが変更されたときに、
表示しているステータスウィンドウを変更しなければいけないので
コマンドウィンドウが更新される前に last_index に選択項目を保存しておきます。
コマンドウィンドウが更新されてから、現在の項目と比較して変更されていないかを確認します。
変更されていれば、それぞれのステータスウィンドウの可視状態を変更します。
@index への代入は、update_savefile_selection の前に行います。
1秒間に60回も処理されるところなので、そこまで順番を気にしなくてもいいんですけどね。
5.セーブデータの追加
最後に必要な情報がセーブされるように変更を加えます。
マップ名を取得するためのデータの読み込み処理の詳細はこちら。
追加情報を保存するための準備ですが、(1) のものと違う方法を使います。
今回は変更前のセーブデータでも読み込めるようになっています。
拡張セーブデータは、save_data[:aaa] のように取得しますが、これできるのはハッシュの場合だけです。
しかし、(1) の方法だと変更前のセーブデータに @save_data は作成されておらず、
save_data プロパティの値は nil ということになります。これだとエラーが出てしまいます。
今回のようにプロパティ内で初期化すれば、セーブデータに情報がなくとも nil が返ることはなくなります。
セーブデータをファイルに保存する前に追加情報を更新しておきます。
セーブは、Scene_File#do_save で実行されるので、新しく必要な情報を3つ追加します。
スクリプトファイル
>> 講座内のコードをまとめたもの
>> [おまけ] セーブファイル削除機能
2.タイトルウィンドウを実装
3.コマンドウィンドウを実装
4.ステータスウィンドウを実装
5.セーブデータの追加
[おまけ] セーブファイル削除機能
Scene_File#start でタイトル、コマンド、ステータスの3種類のウィンドウを作成します。
これに伴い Scene_File#terminate も変更します。
コマンドウィンドウで項目名が切れないようにウィンドウのサイズを調整しています。
調整のため縦幅を大きくしたので、デフォルトの文字サイズでは小さい気がします。
そこで、タイトルを描画する前に文字サイズを変更しておきます。
文字は、描画範囲をウィンドウ内容と同じサイズにすると中央にきます。
@saving は、Scene_File#initialize で設定されています。
true ならセーブ、false ならロードなので、その値で分岐して、タイトルの文字を描画します。
Window_Command セクションをコピペしてください。
クラス名を Window_SaveCommand に変更し、
公開インスタンス変数は不要なので削除します。
initialize メソッドの引数も不要なので削除します。
まず、ウィンドウのサイズから書き換えます。
ウィンドウの縦幅はサイズが決まっているので、最初の3行が不要です。
サイズの設定は super で行います。項目は縦並びなので spacing は省略します。
次に項目名の設定です。縦幅 344 だと項目数はピッタリ13項目で納まります。
Array のこのような使い方はヘルプには載っていませんが雰囲気でわかってもらえると思います。
sprintf メソッドの使い方はこちらをご覧ください。
ここで注意する点は、@item_max を設定する位置です。
これは必ず super より後に処理します。
super が呼び出されると @item_max は 1 に変更されるからです。
そして、ウィンドウは縦幅が 56 で作成されます。
そのため @item_max を設定し直した後に create_contents を実行して
ウィンドウ内容を再生成する必要があります。
@column_max はデフォルトで 1 なので、設定は不要です。削除します。
また、refresh メソッドと draw_text メソッドの定義の変更は不要です。
コマンドクラスの定義が完了したので、シーンクラスの設定を行います。
まず start メソッドの @index は、このコマンドウィンドウのインデックスのことなので、
この部分を変更します。
ただし、この @index は処理の要なので消したままにしておくことはできません。
@index の部分を @command_window.index に置換する必要がありますが、
それだとちょっと面倒です。せっかくなので元の処理はなるべくそのまま使いたいです。
そこで update メソッドに @index = @command_window.index を追加して、
元の処理をそのまま使用できるようにします。
ウィンドウの更新部分も忘れずに変更しておきます。
Scene_File#create_savefile_windows
Scene_File#dispose_savefile_windows
Scene_File#update_savefile_windows
create_savefile_windows の @item_max は、使用しないので削除します。
dispose_savefile_windows に変更点はありません。
メソッド名がこれだけ違って気持ち悪いので定義しています。
alias を使用して複製してもいいのですが、変更点が出たときのために定義文を書いておきます。
update_savefile_windows の else の処理は不要ですね。
表示されるウィンドウは1つだけなので、selected プロパティを使用せずに
visible プロパティの値でどのウィンドウが選択されているのかを判別します。
すべてのステータスウィンドウは、非表示の状態で作成するので
最初に選択されている項目のウィンドウをここで可視状態に変更します。
ステータスウィンドウは Window_SaveFile クラスを改変して作成します。
ウィンドウは非表示の状態で初期化します。
このままだと画面を開いたときに13ページも描画されて重くなってしまうので
ウィンドウが可視状態になったときに描画を行うようにします。
リフレッシュしたら描画済みフラグをONにして、次回からは再描画しないようにします。
リフレッシュの処理を変更します。
描画する項目は、ファイル番号、タイムスタンプ、マップ画像、マップ名、
パーティ、プレイ時間、所持金、の7項目です。
@name_width はカーソルの幅ですので、不要です。
Window_Base のメソッドをコピペしながら実装します。
特に難しいところもないと思います。
いつも通りの文字色変えて文字描画しての繰り返しです。
ウィンドウを切り替えるための処理が必要なので Scene_File#update を変更します。
選択しているセーブデータが変更されたときに、
表示しているステータスウィンドウを変更しなければいけないので
コマンドウィンドウが更新される前に last_index に選択項目を保存しておきます。
コマンドウィンドウが更新されてから、現在の項目と比較して変更されていないかを確認します。
変更されていれば、それぞれのステータスウィンドウの可視状態を変更します。
@index への代入は、update_savefile_selection の前に行います。
1秒間に60回も処理されるところなので、そこまで順番を気にしなくてもいいんですけどね。
マップ名を取得するためのデータの読み込み処理の詳細はこちら。
追加情報を保存するための準備ですが、(1) のものと違う方法を使います。
今回は変更前のセーブデータでも読み込めるようになっています。
拡張セーブデータは、save_data[:aaa] のように取得しますが、これできるのはハッシュの場合だけです。
しかし、(1) の方法だと変更前のセーブデータに @save_data は作成されておらず、
save_data プロパティの値は nil ということになります。これだとエラーが出てしまいます。
今回のようにプロパティ内で初期化すれば、セーブデータに情報がなくとも nil が返ることはなくなります。
セーブデータをファイルに保存する前に追加情報を更新しておきます。
セーブは、Scene_File#do_save で実行されるので、新しく必要な情報を3つ追加します。
>> [おまけ] セーブファイル削除機能