6.3 コンフィグ機能の実装(その1)

前回でコンフィグ画面は表示できるようになったけど、 機能の方はほとんど仮の状態だったから、今回から作っていくことにするね。
結構色んな設定項目があるから作るの大変そうだよねぇ。
ん〜、でも大体はメニューから設定できる項目だから、そんなに複雑なスクリプトは書かなくても大丈夫だよ。
え、そうなの?
5章でシステムボタンを作った時も、 メッセージスキップとかオートモードみたいにメニューからも設定できる機能は簡単に作れたでしょ。
あ、そういえばメニューから設定できるのって kag.onSkipToNextStopMenuItemClick とか kag.onAutoModeMenuItemClick みたいに専用のメソッドがあったよね。
コンフィグの機能を作る時も大抵そういうメソッドがあるからね。
へぇ、そうなんだ。
じゃあまずはウィンドウモードの設定から作っていこっか。
「ウィンドウモード」と「フルスクリーンモード」のどっちかに設定できるんだよね。
ウィンドウモードに切り替える時には kag.onWindowedMenuItemClick メソッド、 フルスクリーンモードに切り替える時には kag.onFullScreenMenuItemClick メソッドを呼び出せば OK だよ。
ウィンドウモードの設定ってメニューにあるから専用のメソッドがあるんだね。
うん。だから「ウィンドウ」と「フルスクリーン」がクリックされた時は、 それぞれこうすればいいってコト。

<ウィンドウモードの「ウィンドウ」「フルスクリーン」がクリックされた時に実行されるスクリプト>

; ウィンドウモードの「ウィンドウ」をクリックした時に実行されるスクリプト
*window
[eval exp="kag.onWindowedMenuItemClick()"]
[s]

; ウィンドウモードの「フルスクリーン」をクリックした時に実行されるスクリプト
*fullscreen
[eval exp="kag.onFullScreenMenuItemClick()"]
[s]

なんかすごいカンタンにできちゃったね。
ウィンドウモードはこれで設定できるんだけど、コンフィグ画面的にはこれだけじゃダメなんだ。
えっ、なんで?
コンフィグ画面の「ウィンドウ」と「フルスクリーン」の横にはチェックボックスがついてるでしょ。
あ、そっか。選択された方のチェックボックスにチェックを付けなくちゃいけないんだ。
そういうこと。
でもどうやってチェックを付けるの?
前景レイヤを使うの。
前景レイヤを?
まず、チェックが付いてるチェックボックス用の画像を用意して…

<チェックが付いているチェックボックス用画像>

チェック画像

この画像をあらかじめ前景レイヤに読み込んどくんだ。
うん、それから?
で、「ウィンドウ」の方がクリックされたら、「ウィンドウ」の左のチェックボックスの所にこの画像を読み込んだ前景レイヤを表示するの。
あ、なるほど。
ってことは、「フルスクリーン」がクリックされたら「フルスクリーン」の左のチェックボックスにその前景レイヤを表示するんだね。
そ。こうすればチェックボックスにチェックが付いてるように見えるってワケ。
で、これがチェックボックスにチェックを入れる(ように見せる)サブルーチンだよ。

<「ウィンドウ」または「フルスクリーン」にチェックを入れるサブルーチン>

; ウィンドウモードのチェックボックスの表示を更新します
*update_windowmode
[layopt layer=0 page=fore left="&kag.fullScreened ? 290 : 90"]
[return]
※チェックが付いているチェックボックス用画像の表示には 0 番の前景レイヤを使うことにします。

layopt タグで前景レイヤの位置を設定してるのはわかるんだけど…
left 属性を指定してるトコがよくわかんないかな。
エンティティはわかるよね?
うん。属性の値を指定する時に "&変数名" って書くと、 その変数の中身の値が使われるんだよね。
そうそう。でも & の後ろには別に変数だけしか書けないわけじゃなくって、 TJS 式が書けるんだ。だからこんなふうに条件演算子を使った式も書けるの。
この場合、left 属性は kag.fullScreenedtrue なら 290false なら 90 になるんだ。
※条件演算子については §1.20 参照
kag.fullScreened っていうのは? フルスクリーンモードになってるかどうかってこと?
そだよ。
kag.fullScreened はウィンドウモードの時は false になってて、 フルスクリーンモードの時は true になってるの。
え〜っと、じゃあ、フルスクリーンモードの時は left290 にして、 ウィンドウモードの時は left90 にしてるってことになるのかな?
ん、そういうこと。
top は設定しなくていいの?
「ウィンドウ」のチェックボックスと「フルスクリーンモード」のチェックボックスは横に並んでるから、 top は最初に image タグで前景レイヤに画像を読み込む時に設定しとけば、 あとは変えなくてもいいでしょ。こんなふうに。

<ウィンドウモードのチェックボックス用画像(前景レイヤ 0)の位置設定>

あ、確かにそうだね。
ってワケで、結局「ウィンドウ」と「フルスクリーン」がクリックされた時に実行されるスクリプトはこうなるよ。

<ウィンドウモードの「ウィンドウ」「フルスクリーン」がクリックされた時に実行されるスクリプト(完成版)>

; ウィンドウモードの「ウィンドウ」をクリックした時に実行されるスクリプト
*window
[eval exp="kag.onWindowedMenuItemClick()"]
[call target=*update_windowmode]
[s]

; ウィンドウモードの「フルスクリーン」をクリックした時に実行されるスクリプト
*fullscreen
[eval exp="kag.onFullScreenMenuItemClick()"]
[call target=*update_windowmode]
[s]

ウィンドウモードを設定するメソッドを呼び出した後に call タグでさっきのチェックボックスを更新するサブルーチンを呼び出すんだね。
そう。
あ、ちょっと思ったんだけど、left の値ってこんな感じに直接指定してもいいんじゃない?

; ウィンドウモードの「ウィンドウ」をクリックした時に実行されるスクリプト
*window
[eval exp="kag.onWindowedMenuItemClick()"]
[layopt layer=1 page=fore top=90]
[s]

; ウィンドウモードの「フルスクリーン」をクリックした時に実行されるスクリプト
*fullscreen
[eval exp="kag.onFullScreenMenuItemClick()"]
[layopt layer=1 page=fore top=290]
[s]

うん、確かにこれでもちゃんと動くよ。
じゃあなんでわざわざサブルーチンにしてるの?
コンフィグ画面を初期化する時にも使うだからだよ。
それってどういうこと?
前回作ったスクリプトを実行した時に表示されたコンフィグ画面には、 ウィンドウモードに両方ともチェックがついてなかったでしょ?
あ、そういえばそうだね。
でもコンフィグ画面を表示した時にウィンドウモードにチェックが付いてなかったらマズイでしょ。
うん、普通はコンフィグ画面を表示した時のウィンドウモードの方にチェックが付いてるよね。
だから、コンフィグ画面を表示する時に現在のウィンドウモードにチェックを入れる必要があるわけ。
で、現在のウィンドウモードを知るためには kag.fullScreened をチェックする必要があるから…
さっきのチェックを入れるサブルーチンを呼び出して現在のウィンドウモードにチェックを入れる、ってこと?
そういうこと。
あとサブルーチンにしとくと、チェックボックスの表示位置を変えたくなった時に、 サブルーチンの中の layopt タグだけ修正すればいいしね。
あ、そっか。直接設定してたら、 初期化のスクリプトと *window*fullscreen の所の layopt タグを全部修正しないといけなくなるんだね。
だからサブルーチンを使ったってワケ。
なるほどね〜。
じゃ次はフォントの設定の部分を作っていくね。
あれ? 次ってメッセージ表示速度の設定じゃないの?
メッセージ表示速度とオートモードと BGM 音量と SE 音量は設定のやり方が共通してるから、後でまとめて作ろうと思って。
あ、そうなんだ。
フォントの設定部分を作るのにまず必要なのはメッセージレイヤだね。
それってフォント名を表示するのに使うんだよね?
そうそう。
今回はフォント名を表示するのに 1 番のメッセージレイヤを使うことにして、 コンフィグ画面を初期化する時にこんな感じで初期化しとくね。

<フォント名表示用レイヤの初期化スクリプト>

[current layer=message1 page=fore]
[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]

えっと、これってつまりこういうメッセージレイヤを作るってことだよね?

<フォント名表示用レイヤの設定>
表示位置(146, 279)
サイズ180×40ピクセル
上下左右の余白なし(marginl, marginr, margint, marginb がすべて 0)
背景透明(opacity が 0)
フォントサイズ18ピクセル
文字の色(color が 0x000000)
文字の影なし

ん、そうだね。
で、フォント名の表示を更新するサブルーチンはこんな感じ。

<フォント名の表示を更新するサブルーチン>

*update_font
[er]
[style align=center autoreturn=false]
[nowait]
[emb exp="kag.chDefaultFace"]
[endnowait]
[return]

まず er タグでメッセージレイヤをクリアして、 それから style タグで文字をセンタリングして、自動改行しないように設定してるね。
er タグと style タグはフォント名を表示するための準備って感じだね。
で、その後 emb タグでフォント名を表示するんだけど、 フォント名は一瞬で表示したいから nowait タグと endnowait タグで emb タグを挟んでるわけね。
emb タグの exp 属性に指定されてる kag.chDefaultFace っていうのがフォント名なの?
そうだよ。kag.chDefaultFace にユーザが選んだフォント名が設定されてるから、 これを参照すれば今選択されてるフォント名が判るんだ。
んじゃ次はクリッカブルマップのフォントの所がクリックされた時に実行されるスクリプトね。

<クリッカブルマップのフォント名が表示されている部分をクリックした時に実行されるスクリプト>

*font
[eval exp="tf.previous_font_face = kag.chDefaultFace"]
[eval exp="kag.onChChangeFontMenuItem()"]
[if exp="kag.chDefaultFace == ''"]
[eval exp="kag.chDefaultFace = tf.previous_font_face"]
[eval exp="kag.setMessageLayerUserFont()"]
[endif]
[call target=*update_font]
[s]

なんか複雑だね…
まぁね。で、注目して欲しいのは2番目の eval タグの行。
exp 属性が kag.onChChangeFontMenuItem() になってるね。
これって名前からするとメニューの「文字表示」−「フォント」を選択した時に呼び出されるメソッドっぽいけど…?
ん、そのとーり。
onChChangeFontMenuItem メソッドはメニューの「フォント」を選択した時に呼び出されるメソッドで、 呼び出すとフォントの選択ダイアログボックスが表示されるんだ。
フォントの選択ダイアログボックスって、これのことだよね。

<フォントの選択ダイアログボックス>

そ。で、フォントを選んで OK ボタンを押すと、ユーザフォントが設定されるの。
この時に kag.chDefaultFace も選択されたフォント名に設定されるんだ。
だから後は call タグでフォント名の表示を更新するサブルーチンを呼び出せば OK。
え? じゃあ call タグの前にある if タグとかは?
えっと、これ実はバグ対策なんだよね。
バグ対策?
version 2.29-dev.20070113 以前の吉里吉里本体だと、 フォント選択ダイアログで元々設定されてたのと同じフォントを選んで OK ボタンを押すと kag.chDefaultFace とかが空文字列("")になっちゃうんだ。
へぇ、そうなんだ。
これは version 2.29-dev.20070416 で修正されてるから、これ以降の吉里吉里本体を使えば問題ないんだけど、 この講座では version 2.28 安定版を使うことにしてるから、対策が必要なの。
具体的にはどうやってるの?
まず最初の eval タグで tf.previous_font_face っていう一時変数にフォント選択ダイアログを表示する前のフォント名を保存しとくの。
確かに tf.previous_font_facekag.chDefaultFace の値を代入してるね。
で、フォント選択ダイアログボックスを閉じた後に、もし kag.chDefaultFace が空文字列になってたら、 フォントの設定をダイアログボックスを閉じる前の状態に戻してるんだ。
kag.chDefaultFacetf.previous_font_face の値を代入してるのは解るんだけど、 その次の kag.setMessageLayerUserFont っていうのは?
setMessageLayerUserFont メソッドは全部のメッセージレイヤに対してユーザが選択したフォントを設定するメソッドだよ。
ユーザが選択したフォントって font タグの face 属性に "user" を指定した時に使われるフォントのこと?
そう、それ。
ちなみに version 2.29-dev.20070416 以降の吉里吉里本体を使う場合はこれで OK だよ。

<クリッカブルマップのフォント名が表示されている部分をクリックした時に実行されるスクリプト(version 2.29-dev.20070416 以降の吉里吉里本体用)>

*font
[eval exp="kag.onChChangeFontMenuItem()"]
[call target=*update_font]
[s]

ずいぶんシンプルになったねぇ。
うん。でも version 2.29-dev.20070113 以前のバージョンの吉里吉里でもちゃんと動作するようにしようと思ったら、 さっきのスクリプトを使う必要があるんだけどね。
さっきのスクリプトって version 2.29-dev.20070416 以降の吉里吉里でも使えるの?
うん、もちろん使えるよ。
ただ、tf.previous_font_face っていう一時変数を使ってるから、 これと同じ名前の一時変数を他のスクリプトで使えなくなっちゃうんだけどね。
あ、そっか。
もし他のスクリプトで同じ名前の一時変数を使ってたら、フォントを設定した時に書き換えられちゃうもんね。
だから、tf.previous_font_face っていう一時変数を他のスクリプトで使わないように注意しなくちゃいけないわけだね。
まぁ多分これと同じ名前の一時変数を他のスクリプトで使うことはないとは思うけどね。
確かに font とかが変数名に入ってるから、あんまり他では使わなさそうな名前だよね。
ま、でも今回に限らず変数名の競合には注意しなくちゃいけないよね。
それじゃ、次は「アンチエイリアス」のチェックボックスね。
まずクリッカブルマップがクリックされた時に実行されるスクリプトはこれ。

<クリッカブルマップの「アンチエイリアス」をクリックした時に実行されるスクリプト>

*antialias
[eval exp="kag.onChAntialiasMenuItemClick()"]
[call target=*update_antialias]
[s]

kag.onChAntialiasMenuItemClick っていうメソッドは、 メニューの「文字表示」−「アンチエイリアス」を選択した時に呼び出されるメソッド?
そ。onChAntialiasMenuItemClick メソッドはアンチエイリアスの ON と OFF を切り替えるメソッドだよ。
アンチエイリアスの設定を切り替えた後に、call タグで「アンチエイリアス」のチェックボックスの表示を更新するサブルーチンを呼び出してるんだよね?
そう。このサブルーチンを呼び出して「アンチエイリアス」のチェックボックスの表示を更新するの。

<「アンチエイリアス」のチェックボックスの表示を更新するサブルーチン>

*update_antialias
[layopt layer=1 page=fore visible="&kag.chDefaultAntialiased"]
[return]
※チェック画像の表示には 1 番の前景レイヤを使うことにします。

「アンチエイリアス」のチェックボックスは更新する時に visible を変えてるだけみたいだね。
「アンチエイリアス」のチェックボックスにチェックを付ける専用の前景レイヤを使うからね。
あ、そうなんだ。
ウィンドウモード用(0 番)の前景レイヤは使えないでしょ。
そっか。0 番の前景レイヤは「ウィンドウ」のチェックボックスか「フルスクリーン」のチェックボックスのどっちかに表示してないといけないもんね。
だから「アンチエイリアス」のチェックボックス用の前景レイヤは、コンフィグ画面を初期化する時にこうやって位置も合わせとくの。

<「アンチエイリアス」のチェック画像表示用レイヤの設定>

[image layer=1 storage="checked" page=fore visible=false left=340 top=285]

「アンチエイリアス」のチェックボックス用には専用のレイヤを使うから、最初に位置を合わせとけば、 更新する時は表示/非表示を切り替えるだけでいいんだね。
そういうこと。
えっと、visible 属性のとこに指定されてる kag.chDefaultAntialiased っていうのは、アンチエイリアスが ON になってたら true で、 OFF になってたら false なんだよね?
ん、そだよ。
つまりアンチエイリアスが ON の時は visibletrue になるからチェック画像が表示されて、 OFF の時は visiblefalse になるからチェック画像は表示されないわけね。

<アンチエイリアスのチェックボックス用画像(前景レイヤ 1)の表示>

これでフォントの設定もできたことだし、今回はこれくらいにしとこっか。
そうだね。結構長くなっちゃったもんね。
残りのメッセージ表示速度・オートモード速度・BGM 音量・SE 音量の設定は同じように作れるから、 次回以降でまとめて作っちゃうことにするね。
うん、おっけー。
それじゃ、また次回ね!


前へ | TOP | 次へ