6.5 コンフィグ機能の実装(その3)

今回は BGM と SE の音量設定機能を作るわけだけど、もう大体の作り方はわかるよね。
「BGM音量」と「SE音量」のゲージのどこがクリックされたかを Layer クラスの cursorX プロパティで調べて、設定する値を計算すればいいんだよね?
ん、そうだね。
だから今回はこんな感じ。

<BGM と SE の音量設定法>

BGM と SE の音量はどっちも最小値が 0% で最大値が 100% だから、両方ともこの式で計算できるよ。
音量を計算する式の方がメッセージ表示速度とかを計算する式より簡単なんだね。
それじゃ「BGM音量」のゲージがクリックされた時に実行されるスクリプトを作ってみて。
えっ? えっと、BGM の音量を設定するんだから、 bgmopt タグを実行すればいいのかな?
ん、そうだね。
あ、でも bgmopt タグって volume っていう属性と gvolume っていう属性があったよね?
どっちを設定したらいいの?
volume 属性で設定した値はセーブデータに保存されて、 セーブデータを読み込むとそのセーブデータに保存されてる値に設定されるんだ。
gvolume 属性で設定した値の方はシステムセーブデータに保存されて、 起動した時に設定されるの。
え〜っと、じゃあコンフィグの場合はセーブデータごとの設定じゃないから、 gvolume 属性を設定すればいいってことになるのかな?
ん、そういうこと。
あと lw はメッセージ表示速度とかの時と同じで 146 と 360 だから。
わかった。じゃあスクリプトを書いてみるね。

<「BGM音量」のゲージがクリックされた時に実行されるスクリプト>

*bgmvolume
[bgmopt gvolume="&(kag.fore.base.cursorX - 146) * 100 \ 359"]
[call target=*update_bgmvolume]
[s]

ん〜、音量を設定した後でインジケータの表示を更新しなくちゃいけないから、こんな感じでいいのかな?
うん、OK だよ。
じゃ、ついでにインジケータの表示を更新するスクリプトも作ってみて。
インジケータ画像用のレイヤはコンフィグ画面を初期化する時にこう初期化しとくことにするね。

<「BGM音量」のインジケータ画像表示用レイヤの設定>

[image layer=5 storage="indicator_bgm" page=fore visible=true top=384]
※BGM音量インジケータ画像の表示には 5 番の前景レイヤを使うことにします。

<BGM音量用インジケータ画像 indicator_bgm.png

インジケータ画像(▲)

えっと、BGM 音量の値ってどうやって調べたらいいかわかんないんだけど…?
あ、そうだったね。
BGM 音量の値は kag.bgm.buf1.volume2 っていうプロパティを参照すれば取得できるよ。
なんかややこしいねぇ。
詳しい説明は省略するけど、bgm っていうのが BGM の再生や設定とかを管理してるオブジェクトで、 buf1 っていうのがサウンドバッファオブジェクトで、 volume2 は大域音量を設定したり参照したりできるプロパティなんだ。
う〜ん…なんかさらにややこしいんだけど…
まぁこれは別に詳しく知ってなくても大丈夫だから。
えと、じゃあ結局 layopt タグの left 属性を 137 + kag.bgm.buf1.volume2 * 359 \ 100 にすればいいってこと?
left の値の計算法は§6.4参照。
ううん、『\ 100』じゃなくて『\ 100000』になるんだ。
えっ、なんで?
volume2 プロパティは 0〜100000 の範囲で設定するようになってるから、 %で表す時には 1000 で割らなくちゃいけないんだ。
つまり、137 + kag.bgm.buf1.volume2 * 359 \ 100 \ 1000 になるわけね。
あ、だから 137 + kag.bgm.buf1.volume2 * 359 \ 100000 になるんだ。
じゃあ…

<「BGM音量」の現在値表示を更新するサブルーチン>

*update_bgmvolume
[layopt layer=5 page=fore left="&137 + kag.bgm.buf1.volume2 * 359 \ 100000"]
[return]

こんな感じになるのかな?
そうそう。
んじゃ次は SE の音量設定ね。
SE の方は seopt タグを使うんだよね?
ん〜、それでもいいんだけど SE の方はバッファが複数ある場合があるから、 今回は TJS スクリプトを使って設定することにするね。
それってどうやるの?
こうやるの。

<「SE音量」のゲージがクリックされた時に実行されるスクリプト>

*sevolume
[iscript]
{
    var elm = %["gvolume" => (kag.fore.base.cursorX - 146) * 100 \ 359];
    for(var i=0;i<kag.numSEBuffers;i++)
        kag.se[i].setOptions(elm);
}
[endscript]
[call target=*update_sevolume]
[s]

kag.se[i]i 番目の効果音バッファを表してて、 setOptions メソッドが seopt タグの代わりになってるんだ。
じゃあ、setOptions メソッドの引数の辞書配列の gvolume っていう要素が seopt タグの gvolume 属性に対応してるってこと?
そう。ちなみに seopt タグを実行すると、属性値を要素に持つ辞書配列を引数にして setOptions メソッドが呼び出されるようになってるんだ。
layopt タグの時とおんなじだね。
※レイヤの setOptions メソッドについては §6.2 参照。
だから今回ももちろん seopt タグを使ってスクリプトを書いても OK だよ。
じゃ、次はインジケータの更新ね。

<「SE音量」のインジケータ画像表示用レイヤの設定>

[image layer=6 storage="indicator_se" page=fore visible=true top=454]
※SE音量インジケータ画像の表示には 6 番の前景レイヤを使うことにします。

<SE音量用インジケータ画像 indicator_se.png

インジケータ画像(▲)

SE の音量は kag.se[0].volume2 で参照できるから、 インジケータの表示を更新するスクリプトを作ってみて。
SE 音量の方も volume2 の値の範囲は 0 〜 100000 になってるの?
うん。だから BGM 音量の時と同じようにしてね。
わかった。じゃあやってみるね。

<「SE音量」の現在値表示を更新するサブルーチン>

*update_sevolume
[layopt layer=6 page=fore left="&137 + kag.se[0].volume2 * 359 \ 100000"]
[return]

SE の音量の範囲って BGM の音量の範囲と同じだから、こんなふうに kag.bgm.buf1.volume2kag.se[0].volume2 に書き換えればいいんだよね?
ん、そうそう。
これでコンフィグの機能は一通り作れたから、次は初期化のスクリプトを作ってくね。
初期化のスクリプトって、右クリックした時に実行されるスクリプトのこと?
そ。§6.2 で作った仮のスクリプトに、 ここまででやった初期化のスクリプトを追加するの。
チェックボックスとかインジケータ用のレイヤを作ったり、 表示を初期化したりするスクリプトを追加するんだよね?
それとレイヤの数や表示状態を変えたりもするね。
初期化処理を追加すると、コンフィグ画面のスクリプトはこんな感じになるよ。

<コンフィグ画面の初期化スクリプト(rclick.ks 内の *rclick ラベル)>

; ※予め右クリックするとこのラベル(*rclick)にジャンプするように設定しておきます。
*rclick
; 右クリックでコンフィグ画面を閉じられるように右クリックの設定を変更します
[rclick jump=true storage="rclick.ks" target=*back enabled=true]
; 現在の状態をメモリ上の栞に保存しておきます
[tempsave place=0]
[iscript]
{
    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);
}
[endscript]
; 背景レイヤにコンフィグ画面の画像(クリッカブルマップ)を読み込みます
[image layer=base storage="config_bg" page=fore]
; レイヤを必要な数(前景レイヤ×7,メッセージレイヤは1つ追加)確保します
[laycount layers=7 messages="&kag.numMessageLayers + 1"]

; 前景レイヤに画像を読み込みます
; #0: ウィンドウモード(ウィンドウ/フルスクリーン)に表示するチェック画像
[image layer=0 storage="checked" page=fore visible=true top=97]
; #1: 「アンチエイリアス」に表示するチェック画像
[image layer=1 storage="checked" page=fore visible=false left=340 top=285]
; #2: メッセージ表示速度用インジケータ画像
[image layer=2 storage="indicator_msg" page=fore visible=true top=184]
; #3: 「ページ末まで一度に表示」に表示するチェック画像
[image layer=3 storage="checked" page=fore visible=false left=290 top=135]
; #4: オートモード速度用インジケータ画像
[image layer=4 storage="indicator_auto" page=fore visible=true top=254]
; #5: BGM 音量用インジケータ画像
[image layer=5 storage="indicator_bgm" page=fore visible=true top=384]
; #6: SE 音量用インジケータ画像
[image layer=6 storage="indicator_se" page=fore visible=true top=454]

; フォント名表示用のメッセージレイヤの設定をします
[current layer="&'message' + (kag.numMessageLayers - 1)"]
[position left=146 top=279 width=180 height=40 marginl=0 margint=0 marginr=0 marginb=0 frame="" opacity=0 visible=true]
[deffont size=18 color=0x000000 shadow=false]

; メッセージ履歴の出力・表示を無効にします
[history output=false enabled=false]

; 各項目の表示を初期化します
[call target=*update_windowmode]
[call target=*update_pagebreak]
[call target=*update_antialias]
[call target=*update_msgspeed]
[call target=*update_autospeed]
[call target=*update_bgmvolume]
[call target=*update_sevolume]
[call target=*update_font]

; ユーザの操作を待ちます
[s]

う〜ん、やっぱり結構長くなったねぇ。
まぁね。
じゃ今回追加したとこだけ見ていくね。
うん。
まずはlaycount タグで必要なレイヤを確保してる部分からね。
コンフィグ画面で使う前景レイヤは全部で7枚だから、layers 属性が 7 で、 メッセージレイヤは… messages 属性が kag.numMessageLayers + 1 ってことは、 メッセージレイヤを1枚増やす、ってことなのかな?
うん、そうだよ。
なんでメッセージレイヤは1枚増やしてるの?
tempload タグでコンフィグ画面表示前の状態を復元するわけだけど、 メッセージレイヤに表示されてた文章の内容までは復元できないんだ。
あ、そうなんだ。
普通のセーブデータでもメッセージレイヤの内容までは保存されないでしょ。
あ、そういえばそうだね。
だから、コンフィグ画面を表示する前のメッセージレイヤは使わずに、 新しいメッセージレイヤを1つ作ってコンフィグ画面用に使うようにしてるの。
なるほどね。それなら元々あったメッセージレイヤの内容が書き換えられることはないもんね。
んじゃ次は image タグで前景レイヤに画像を読み込む部分ね。
この部分は今までにやったのをまとめて書いてるって感じだよね。
ん、だからここで改めて説明することもないかな。
じゃあ次はフォント名を表示するレイヤの設定をやってる部分ね。
なんか最初っからややこしい書き方になってるんだけど…
current タグの layer 属性には、 新しく作ったメッセージレイヤを指定してるの。
例えば、コンフィグ画面を表示する前のメッセージレイヤの数が1枚だった場合を考えてみるとわかりやすいと思うよ。
えっと、それって元々 kag.numMessageLayers1 だった、ってことだよね?
そ。で、コンフィグ画面を初期化する時にメッセージレイヤが1枚増えるから、 current タグが実行される時には kag.numMessageLayers の値はどうなってる?
2、だよね。
じゃあ 'message' + (kag.numMessageLayers - 1) は?
ん〜と、kag.numMessageLayers - 11 になるから、 'message' + 1 ってことだよね。
これだと 1 が文字列とみなされるから、layer 属性は 'message1' になるってこと?
※文字列と数値の足し算については §1.6 参照。
だから新しく追加したメッセージレイヤが操作対象のメッセージレイヤになるってワケ。
なるほど、確かにそうなるね。
残りの部分は §6.3 でやったからわかるよね?
うん、だいじょぶだよ。
それじゃ、最後はコンフィグ画面の表示を初期化してる部分だね。
これって今までに作ってきた表示の更新サブルーチンを全部呼び出してるんだよね?
そう。だからここも特に説明するコトはないかな。
あとは、コンフィグ画面を閉じる部分だね。

<コンフィグ画面を閉じるスクリプト(「Back」をクリックした時/コンフィグ画面表示中に右クリックした時に実行されるスクリプト)>

*back
; コンフィグ画面表示前の状態を復元します(但し BGM は復元しません(現在の BGM の再生を継続します))
[tempload place=0 bgm=false]
; メッセージ履歴の出力・表示を有効にします
[history output=true enabled=true]
; メッセージ表示速度の設定を反映します
[delay speed=user cond="kag.chUserMode"]
; 右クリックで再びコンフィグ画面を表示できるようにします
[rclick call=true storage="rclick.ks" target=*rclick enabled=true]
[return]

コンフィグ画面を閉じるスクリプトはあんまり変わってないね。
あ、delay タグが増えたのかな?
ん、delay タグ以外は前と同じだよ。
この delay タグって何のために追加したの?
メッセージ表示速度の設定を反映するためだよ。
それってどういうこと?
メッセージ表示速度を設定する時は kag.userChSpeed にメッセージ表示速度の値を代入したでしょ。
§6.4 参照。
うん、そうだったよね。
これだけだと実際の文字の表示には反映されないから、 delay タグを実行する必要があるんだ。
じゃあ delay タグを実行すると文字の表示速度が設定した値になるんだ?
うん。ただ、kag.chUserModefalse の時には delay タグは実行しないけどね。
あ、ホントだ。cond 属性が kag.chUserMode になってるね。
でもなんで kag.chUserModefalse の時には delay タグを実行しないの?
…っていうかそもそも kag.chUserMode って何なの?
kag.chUserMode は現在の文字の表示速度がユーザが選んだ値になってる時には true になって、そうじゃない時には false になるんだ。
だから、例えば delay タグの speed 属性を "user" 以外にして実行したりすると false になるわけね。
う〜ん、kag.chUserMode が何なのかは大体わかったけど、 kag.chUserModefalse の時に delay タグを実行しないのはなんでなの?
kag.chUserModefalse の時は、 例えば演出上の理由とかでスクリプト側で表示速度が設定されてるってコトだから…
うん?
わざわざスクリプトで表示速度を設定してるのに、 コンフィグ画面を表示しただけで表示速度をユーザが指定した値に変えられちゃったら困るでしょ?
あ、そっか。そーいう時に delay タグを実行すると、 コンフィグ画面を表示する前の表示速度に戻らなくなっちゃうんだね。
だから cond="kag.chUserMode" にしとくことで、 コンフィグ画面を表示する前にユーザが設定した文字表示速度になってた時だけ、 コンフィグ画面表示中にユーザが設定した値を反映するようにしてるってワケ。
なるほどね〜。
それじゃ、これでコンフィグ画面のスクリプトが一通りできたから、実行してみよっか。
は〜い!
と、その前に Config.tjs の中身をちょっと書き直しとかないとね。
え、なんで?
不必要なメニュー項目を表示しないようにするためだよ。
不必要なメニュー項目って?
『システム−自動的に読み進むウェイト』と『文字表示』と『画面』の項目だよ。
なんでこの3つの項目を表示しないようにするの?
まず『システム−自動的に読み進むウェイト』についてだけど、 今回はゲージをクリックすることでオートモードのウェイトを設定してるから、 元々メニュー項目にある『短い』とか『やや短い』とかの5つの項目で表せなくなってるでしょ?
あ、確かにそうだね。
だからこのメニュー項目は消しとくの。『文字表示』を消すのも大体同じ理由だね。
あと『画面』についてだけど、コンフィグ画面ではウィンドウモードはチェックボックスで表示してるよね。
うん、そだね。
もし『画面』のメニュー項目を表示したままにしといたら、 コンフィグ画面表示中にメニューからウィンドウモードを設定した時に、 コンフィグ画面のチェックボックスの表示を更新できなくなっちゃうでしょ。
あ、そっか。コンフィグ画面表示中にメニューの項目が選択されたかどうかは判らないもんね。
だからこういう表示したままにしとくとマズイ項目は予め削除しとくの。
それで Config.tjs を書き換えるんだね。
ってワケで、Config.tjs の autoModeWaitMenu.visiblecharacterMenu.visibledisplayMenu.visible はそれぞれ false に設定しといてね。

<Config.tjs の設定変更箇所その1>

// ◆ 「システム > 自動的に読み進むウェイト」
;autoModeWaitMenu.visible = false;

<Config.tjs の設定変更箇所その2>

// ◆ 「文字表示」
;characterMenu.visible = false;

<Config.tjs の設定変更箇所その3>

// ◆ 「画面」
;displayMenu.visible = false;

うん、設定できたよ。
それじゃ、必要なデータはここに置いとくから、ちょっと実行してみて。
りょーかい!

<実行結果>

表示されたコンフィグ画面

お〜、ちゃんとコンフィグ画面になってる〜!
うん、うまく表示できてるね。
じゃ、それぞれの設定がちゃんとできるかも試しといてね。
はーい!
…って、設定ができるかどうかの確認は今やらないの?
う〜ん…画像とか文章じゃ表現しにくい設定項目が多いからね…ちょっとその辺は割愛ってことで。
まぁそれはそうだけどねぇ…
きっとちゃんと動くと思うから、色々試してみてね。
ま、いっか。うん、わかった。
それじゃ、今回はここまで。
また次回ね!


前へ | TOP | 次へ