6.14 セーブ画面を作る 〜初期化・終了処理編〜

今回はセーブ画面の仕上げってことで、初期化のスクリプトとセーブ画面を閉じるスクリプトを作ってくね。
はーい。
まず、これがセーブ画面の初期化のスクリプト。

<セーブ画面の初期化スクリプト>

*initialize
; 右クリックでセーブ画面を閉じられるように右クリックの設定を変更します
[rclick jump=true storage="save.ks" target=*close enabled=true]
; 現在の状態をメモリ上の栞に保存しておきます
[tempsave place=0]
; スナップショットをロックします
[locksnapshot]
; メッセージ履歴の出力・表示を無効にします
[history output=false enabled=false]

[iscript]
{
    // システムボタンを使っていて、メッセージレイヤが表示されている時は onMessageHiddenStateChanged を呼び出します
    if(typeof global.exsystembutton_object != "undefined" && kag.fore.messages[0].visible)
        exsystembutton_object.onMessageHiddenStateChanged(true);
    var i;
    var elm = %["visible" => false];
    // 全ての前景レイヤを非表示にします
    for(i=0;i<kag.numCharacterLayers;i++)
        kag.fore.layers[i].setOptions(elm);
    // 全てのメッセージレイヤを非表示にします
    for(i=0;i<kag.numMessageLayers;i++)
        kag.fore.messages[i].setOptions(elm);
    // セーブデータの情報が無い場合は新しく作成します
    if(typeof sf.saveinfo == "undefined")
    {
        sf.saveinfo = new Dictionary();
        sf.saveinfo.page = 1; // 現在選択されているページ
        sf.saveinfo.latest = void// 最新のセーブデータ(セーブデータが無い場合は void)
    }
    // 一時変数を作成します
    tf.saveload = new Dictionary();
}
[endscript]
; 最初にセーブ画面を表示する時は以下のメソッドを定義します
[if exp="typeof global.update_saveinfo == 'undefined'"]
[iscript]
// セーブデータ情報の表示を更新するメソッドを定義します
function update_saveinfo(thumbnail)
{
    // 略(§6.11参照)
}
// サムネイルの上にマウスカーソルが乗った時に呼び出されるメソッドを定義します
function thumbnail_onenter(thumbnail)
{
    // 略(§6.13参照)
}
// サムネイルの外にマウスカーソルが出て行った時に呼び出されるメソッドを定義します
function thumbnail_onleave()
{
    // 略(§6.13参照)
}
[endscript]
[endif]

; レイヤを必要な数(前景レイヤ×25,メッセージレイヤは13個追加)確保します
[laycount layers=25 messages="&kag.numMessageLayers + 13"]

*initialize_from_load
; 背景レイヤに画像(クリッカブルマップ)を読み込みます
[image layer=base storage="save_bg" page=fore]

; 前景レイヤの設定をします
; #0: 1番目のサムネイル用画像
[layopt layer=0 page=fore visible=false left=8 top=110]
; 中略(§6.9参照)

; メッセージレイヤの設定をします
; セーブデータの日時表示用メッセージレイヤ
[current layer="&'message' + (kag.numMessageLayers - 13)"]
[position left=8 top=200 width=120 height=24 frame="" opacity=0 marginl=0 marginr=0 margint=0 marginb=0 visible=true]
[deffont size=13 face="MS ゴシック" color=0x804040 shadow=false bold=false]
; 中略(§6.9参照)

; すべての表示を初期化します
[call target=*update_all]
; ユーザの操作を待ちます
[s]

前景レイヤとメッセージレイヤの初期化スクリプトとメソッドの定義は省略してるけど、 セーブ画面の初期化スクリプトはこんな感じだよ。
省略しててもかなり長いよねぇ。
まぁね。 でもコンフィグ画面の初期化のスクリプトと似てる部分が多いから、 一通り見ていくのはそんなに大変じゃないと思うよ。
そうなの?
うん。ま、その辺は実際に見ていけばわかると思うから。
じゃあいつも通り最初から見ていこー。
だね。
まず rclick タグと tempsave タグだけど、これはどっちもコンフィグ画面を作る時に使ったよね。
rclick タグは右クリックでセーブ画面を閉じるのに使ってて、 tempsave タグはセーブ画面を閉じる時に、セーブ画面を表示する前の状態に戻すのに使ってるんだよね。
そ。だから rclick タグの target 属性は「Close」をクリックした時の領域アクションの target と同じだよ。
あと、tempsave タグと tempload タグはこういう画面を作る時には欠かせないよね。
じゃ次は locksnapshot タグね。
locksnapshot タグってサムネイルを作るのに使うんだよね?
そうだよ。
locksnapshot タグを実行すると、その時の画面のスナップショットが撮られるんだ。
だから、セーブ画面を作る前に locksnapshot タグを実行しとくわけね。
セーブ画面を作った後に実行するとサムネイルがセーブ画面の画像になっちゃうから、 セーブ画面を作る前に実行するんだっけ?
ん、そういうこと。
その次の history タグはコンフィグ画面の時に出てきたよね。
§6.2 参照。
output 属性を false にすると、 メッセージレイヤに表示した文字がメッセージ履歴に書き込まれなくなって、 enabled 属性を false にすると、 メッセージ履歴が表示できなくなるんだよね。
そうそう。
次は iscript タグ 〜 endscript タグの間の TJS スクリプトだけど、 前半はコンフィグ画面の時と同じだからわかるよね?
§6.5§6.6 参照。
うん。メッセージレイヤを非表示にするとこまではわかるよ。
じゃその次のシステム変数と一時変数を作るスクリプトから見てくね。
まずシステム変数 sf.saveinfo の方だけど、これって何に使うんだったか覚えてる?
えっと、sf.saveinfo.page が今表示されてるページ番号になってるんだよね。
sf.saveinfo.page って何のためにシステム変数に記録しとくんだった?
セーブ画面を初期化する時に、前にセーブ画面を表示した時に選択されてたページを最初に表示するためだよね。
§6.8 参照。
ん、そうそう。
あともう一つのシステム変数が sf.saveinfo.latest で、 最新のセーブデータの番号を記録しとくんだよね。
そうだね。
じゃついでにスクリプトの方も説明してみて。
え〜っとね…まず typeof sf.saveinfo == "undefined" っていう条件の if ブロックがあるね。
これって確か sf.saveinfo っていうシステム変数が無い時に真になるんだったよね?
そうだよ。typeof 演算子はその変数が存在しない場合に "undefined" になるからね。
ちなみに sf.saveinfo が存在しない時ってどんな時だと思う?
え? う〜ん…最初に起動した時、とか?
そ。最初は sf は空の辞書配列になってるからね。
当然 sf.saveinfo っていう要素もないわけ。
じゃあその時は if ブロックの中身が実行されるから、 sf.saveinfo っていう辞書配列を作って、 sf.saveinfo.pagesf.saveinfo.latest に それぞれ 1void を代入するんだね。
最初にセーブ画面を表示する時は1ページ目を表示するのが普通だし、 あと最初はセーブデータが無いから最新のセーブデータも無いしね。
一時変数の方は何も条件がないみたいだけど?
一時変数はホントに一時的に使うだけだから、無条件に新しい辞書配列を作ってるの。
新しい辞書配列を作ると、前にセーブ画面を表示した時の tf.saveload の内容って全部消えちゃうんだっけ?
そうだよ。別に前にセーブデータを表示した時の情報を残しとく必要はないから、 セーブ画面を表示するたびに新しい辞書配列を作ってるんだ。
なるほどね。
あ、あと一時変数の方はここで tf.saveload.thumbnail とかの要素を作らないんだね。
一時変数の方はセーブデータに記録されるわけじゃないし、 tf.saveload.thumbnail とかは参照される前にちゃんと値がセットされるから、 ここで作っとかなくてもいいんだ。
ふぅん、そうなんだ。
じゃあ次はメソッドを定義してる部分ね。
セーブデータの情報を更新する update_saveinfo メソッドと、 サムネイルの上にマウスカーソルが乗った時に呼び出される thumbnail_onenter メソッドと、 あとサムネイルの外にマウスカーソルが出て行った時に呼び出される thumbnail_onleave メソッドだね。
この3つのメソッドはセーブ画面を作る時に定義するんだけど、 最初にセーブ画面を表示する時に一回作っとけば、次に表示する時には作りなおす必要がないんだ。
えっと、じゃあメソッドが定義されてるかどうかを if タグの条件でチェックしてるってこと?
そうだよ。
例えば update_saveinfo っていうメソッドが定義されてるかどうか知りたい時は、 typeof global.update_saveinfo の値を調べればいいんだ。 まだ定義されてなかったら "undefined" になって、 定義されてたら "Object" になるの。
じゃあ typeof global.update_saveinfo == "undefined" が真だったら、 まだメソッドが定義されてないから定義するってこと?
そういうこと。
あ、でも if タグのとこでチェックしてるのって update_saveinfo メソッドが定義されてるかどうかってことだけだよね?
他のメソッドはチェックしなくていいの?
update_saveinfo メソッドと thumbnail_onenter メソッドと thumbnail_onleave メソッドはまとめて定義してるから、 typeof global.update_saveinfo"undefined" じゃなかったら他の2つも "undefined" にはならないでしょ。
あ、そっか。update_saveinfo メソッドが定義されてたら他のメソッドも定義されてるからチェックしなくてもいいんだ。
これで TJS スクリプトの部分はわかった?
うん、おっけーだよ。
じゃ次にいくね。
って言ってもレイヤを初期化するとこ§6.9 でやったからわかるよね。
うん。
あ、でも laycount タグの次に *initialize_from_load っていうラベルがあるんだけど、 なんでこんなトコにラベルがあるの?
あー、このラベルは今は使わないんだけど、ロード画面を作る時に必要になるんだ。
それってどういうこと?
セーブ画面とロード画面にはそれぞれ「Load」と「Save」っていうクリックできる部分があるでしょ。
「Load」をクリックするとロード画面に切り替わって、 「Save」をクリックするとセーブ画面に切り替わるんだよね。
「Save」の方をクリックすると、この *initialize_from_load っていうラベルにジャンプするの。
えっと、じゃあこのラベルってロード画面からセーブ画面に切り替えるのに使うってコト?
そういうこと。
ってワケだから、このラベルの詳しい説明はロード画面を作る時に改めてすることにするね。
うん、りょーかい。
で、最後は全部の表示を更新するサブルーチンを呼び出して完了。
セーブ画面って初期化でやること多いよねぇ。
まぁレイヤの数も多いし変数も色々使うからね。
それじゃ、あと残ってるのはセーブ画面を閉じる処理と「Close」をクリックした時の処理かな。
「Load」をクリックした時の処理もまだなんじゃない?
んー、そうなんだけど、これってロード画面に切り替えるわけだから、 ロード画面ができないと作れないんだよね。
あ、そっか。
だから「Load」をクリックした時の処理はちょっと後回しにさせてもらうね。
ロード画面を作った後でちゃんとやるから。
うん、わかった。
じゃセーブ画面を閉じるスクリプトを見ていくね。

<セーブ画面を閉じる時に実行するスクリプト>

*close
; セーブ画面表示前の状態を復元します(但し BGM は復元しません)
[tempload place=0 bgm=false]
; メッセージ履歴の出力・表示を有効にします
[history output=true enabled=true]
; スナップショットをアンロックします
[unlocksnapshot]
; 右クリックで再びコンフィグ画面を表示できるようにします
[rclick call=true storage="rclick.ks" target=*rclick enabled=true]
[iscript]
// システムボタンを使っていて、コンフィグ画面を表示する前にメッセージレイヤが表示されていた時は onMessageHiddenStateChanged を呼び出します
if(typeof global.exsystembutton_object != "undefined" && kag.fore.messages[0].visible)
    exsystembutton_object.onMessageHiddenStateChanged(false);
[endscript]
[return]

こっちもコンフィグ画面の時と似てるね。
そうだね。コンフィグ画面のスクリプトと違ってるのは delay タグが無いことと、 unlocksnapshot タグがあることだけだね。
§6.6 参照。
unlocksnapshot タグって locksnapshot タグを使った後に必ず書かなきゃいけないんだよね。
ん、サムネイルを使う必要がなくなったら unlocksnapshot タグを実行するようにしてね。
じゃないと次に locksnapshot タグを実行してもスナップショットが撮られなくなっちゃうから。
あ、そうなんだ。
さて、これでセーブ画面の機能は一通り作れたね。
まぁロード画面に切り替える機能はロード画面を作った後で実装することになるけどね。
じゃあ実行してみる?
そうだね。
必要なファイルはここに置いとくから実行してみて。
あ、それと今回は右クリックするとセーブ画面が表示されるようにしてるから。
りょ〜かい!

<実行結果>

表示されたセーブ画面

右クリックしたらちゃんとセーブ画面が表示されたね。
じゃ試しにセーブしてみて。
うん!

<実行結果(セーブ後)>

データをセーブした後のセーブ画面

うん、サムネイルとセーブデータの情報も表示されてるし、 「New」 もちゃんと表示されてるね。
ちゃんとセーブできてるみたいだね。
あとページ切り替えとか「Close」もうまく動くか試してみてね。
は〜い!
じゃ今回はここまで。
次回はロード画面を作ることにするね。
それじゃ、また次回!


前へ | TOP | 次へ