6.6 ロールオーバー

今回のタイトルになってるロールオーバーって?
よくブラウザで画像の上にマウスカーソルを乗せると画像が切り替わることがあるでしょ?
ロールオーバーってのはその機能のことだよ。
えっと、それってつまり button タグで作ったボタンの上にマウスカーソルを乗せたり、 クリックしたりすると画像が切り替わるアレのこと?
そうそう。
で、今回はクリッカブルマップのクリックできる領域の上にマウスカーソルが乗った時に、その部分の画像を変えようって話。
へぇ、クリッカブルマップってそういう機能もあるんだ。
まぁ button タグの時みたいに簡単にできるってわけじゃないんだけどね。
え、そうなの?
button タグで作るボタンの場合は、 レイヤが持ってる画像の位置(imageLeft)を変えることで、 通常の状態とボタンが押された状態とボタンの上にマウスカーソルがある状態を表す3種類の画像を切り替えてたよね。
§5.4 参照。
うん、そうだったね。
クリッカブルマップでマウスカーソルがクリックできる領域の上に乗った時に画像を切り替えるためには、 まずその時に表示する画像を単独で作っとくんだ。
例えば「Back」の部分だとこんな感じにね。

<「Back」の領域にマウスカーソルが乗った時に表示する画像(back_ro.png)>

通常時の画像とマウスカーソルが乗ってる時の画像を並べて作るんじゃないんだね。
クリッカブルマップの場合は通常時の画像は元々表示されてるから、わざわざ作る必要もないでしょ。
あ、そう言われればそうだね。
で、予めこの画像をレイヤに読み込んどくの。
このレイヤは普段は非表示なんだけど、「Back」の領域にマウスカーソルが乗った時に表示状態にすることで、 マウスカーソルが乗ったら画像が変わるように見せるんだ。

ロールオーバー用レイヤの表示切替

えっと、つまりこのレイヤの visible は普段は false になってるけど、 「Back」の領域にマウスカーソルが乗ったら true になるってことだよね?
ん、そうだよ。
でもそれってどうやるの?
領域アクションの onenteronleave を使うの。
※領域アクションについては §6.2 参照。
あ、領域アクション定義ファイルを使うんだ。
onenter にはマウスカーソルが領域内に入った時に実行される TJS スクリプトが指定できて、 onleave にはマウスカーソルが領域内から出て行った時に実行される TJS スクリプトが指定できるから…
onenter でレイヤの visibletrue にして、 onleavefalse にすればいいんだね?
そうそう。
えっと、具体的にはどうやったらいいの?
まず、右クリックサブルーチン(rclick.ks)の方でロールオーバー用のレイヤをこうやって作っとくの。

<「Back」のロールオーバー用レイヤの作成(rclick.ks 内に記述)>

[image layer=7 storage="back_ro" page=fore visible=false left=502 top=21]
※「Back」のロールオーバー用レイヤには 7 番のレイヤを使うことにします。

通常時はレイヤは非表示になるから visiblefalse で、 あと位置が変わらないから lefttop はレイヤを作る時に設定しとく、ってことかな?
ん、そういうこと。
で、領域アクション定義ファイルの「Back」の領域のアクションは、こう定義すれば OK。

<「Back」の領域(領域番号 1 番)のアクション定義(config_bg.ma 内に記述)>

1: storage="rclick.ks"; target="*back"; onenter="kag.fore.layers[7].visible = true"; onleave="kag.fore.layers[7].visible = false";

えと、「Back」のレイヤの番号は 7 番だから、 onenter の方は kag.fore.layers[7].visible = true でレイヤを表示状態にして、 onleave の方は kag.fore.layers[7].visible = false で非表示にしてる、ってことだよね?
そ。button タグよりはちょっと面倒かもしれないけど、そんなに難しくはないでしょ。
うん、確かにやってることは結構シンプルだもんね。
それじゃ、残りの3つも作っちゃおっか。
残りの3つって?
この3つだよ。

<残り3つのロールオーバー処理>

クリックできる領域には全部ロールオーバー処理を追加するってこと?
そういうこと。じゃあ最初はチェックボックスのロールオーバー処理からね。
マウスカーソルが乗った時に表示する画像はコレ。
ブラウザで見るとわかりにくいと思うけど、赤い部分は半透明になってるよ。

<チェックボックス用ロールオーバー画像(check_ro.png)>

で、チェックボックスのロールオーバー用レイヤはこう作っとくね。

<チェックボックスのロールオーバー用レイヤの作成(rclick.ks 内に記述)>

[image layer=8 storage="check_ro" page=fore visible=false]
※チェックボックスのロールオーバー用レイヤには 8 番のレイヤを使うことにします。

チェックボックスって4つあるけど、ロールオーバー用のレイヤは1つだけなんだね。
2つ以上のチェックボックスに同時にマウスカーソルが乗ることはないでしょ。
あ、そっか。
じゃあロールオーバー用レイヤを4つのチェックボックスで共有するんだね。
ん、そうだよ。
それじゃ、領域アクション定義ファイルは基本的にさっきと同じように作ればいいから、ちょっと作ってみて。
え〜っと…チェックボックス用ロールオーバー画像は4つのチェックボックスで共有するから、 この4つの領域アクションの onenteronleave は全部おんなじになる…んだよね?
onleave はレイヤを非表示にするだけだから4つとも同じだけど、 onenter の方はレイヤを表示状態にするだけじゃなくて、 レイヤの位置も設定しないといけないから、それぞれ違うよ。
あ、位置も設定しなきゃいけないんだ…
ってことは、setPos メソッドを使えばいいんだよね?
ん、そうだね。
ちなみにそれぞれのチェックボックスの位置はこうなってるから、この位置にレイヤを表示してね。

<各チェックボックスの位置>

onenter の方って setPos メソッドを呼び出して visible も設定しなくちゃいけないよね?
うん。
そういう時って、どんなふうに onenter を書いたらいいの?
領域アクションに指定してる文字列は TJS スクリプトとして解釈されるから、 2つ以上の文を書きたい時には onenter="layer.setPos(0, 0); layer.visible = true"; っていう感じに、 普通の TJS スクリプトを書く時みたいに ; で文を区切って書けば OK だよ。
あと順次演算子を使って onenter="layer.setPos(0, 0), layer.visible = true"; って書いてもいいよ。
※順次演算子については §5.9 参照。
あ、そうなんだ。
じゃあ…

<各チェックボックス領域(領域番号 2, 3, 4, 8 番)のアクション定義(config_bg.ma 内に記述)>

; ウィンドウ
2: storage="rclick.ks"; target="*window"; onenter="kag.fore.layers[8].setPos(90, 98), kag.fore.layers[8].visible = true"; onleave="kag.fore.layers[8].visible = false";

; フルスクリーン
3: storage="rclick.ks"; target="*fullscreen"; onenter="kag.fore.layers[8].setPos(290, 98), kag.fore.layers[8].visible = true"; onleave="kag.fore.layers[8].visible = false";

; ページ末まで一度に表示
4: storage="rclick.ks"; target="*pagebreak"; onenter="kag.fore.layers[8].setPos(290, 135), kag.fore.layers[8].visible = true"; onleave="kag.fore.layers[8].visible = false";

; アンチエイリアス
8: storage="rclick.ks"; target="*antialias"; onenter="kag.fore.layers[8].setPos(340, 285), kag.fore.layers[8].visible = true"; onleave="kag.fore.layers[8].visible = false";

こんな感じになるのかな?
ん、ちゃんとできてるよ。
よかった〜。
じゃ、その調子で次はフォント名を表示する部分のロールオーバー処理も作ってみて。
フォント名を表示する部分のロールオーバー画像ってどんな画像なの?
この画像を使うことにするね。
ちなみに表示位置は (146, 284) だよ。

<フォント名表示部用ロールオーバー画像(font_ro.png)>

じゃあ、こんな感じでロールオーバー用のレイヤを作ればいいよね。

<フォント名表示部のロールオーバー用レイヤの作成(rclick.ks 内に記述)>

[image layer=9 storage="font_ro" page=fore visible=false left=146 top=284]
※フォント名表示部のロールオーバー用レイヤには 9 番のレイヤを使うことにします。

ん、OK。じゃアクション定義の方も書いてみて。
は〜い。

<フォント名表示領域(領域番号 7 番)のアクション定義(config_bg.ma 内に記述)>

7: storage="rclick.ks"; target="*font"; onenter="kag.fore.layers[9].visible = true"; onleave="kag.fore.layers[9].visible = false";

フォント名を表示する部分のロールオーバー用レイヤは位置が変わらないから、visible の設定だけでいいよね。
だね。
それじゃ最後はゲージのロールオーバー処理ね。
まずロールオーバー用画像はこれ。

<ゲージ用ロールオーバー画像(gauge_ro.png)>

※画像自体の色が白なので背景色を変えています。

これも4つのゲージで共有するんだよね?
もちろん。
ゲージは縦に並んでるから、レイヤを作る時に left は指定できそうだけど?
うん、だからこんな感じに left を指定してレイヤを作ればいいよね。

<ゲージのロールオーバー用レイヤの作成(rclick.ks 内に記述)>

[image layer=10 storage="gauge_ro" page=fore left=146 visible=false]
※ゲージのロールオーバー用レイヤには 10 番のレイヤを使うことにします。

えっと、じゃあ領域アクションの onentervisibletop を設定すればいいってことになるよね?
ん、そのとーり。
ちなみにそれぞれのゲージの top の値はこうなってるよ。

<各ゲージの top の値>

じゃ領域アクションを書いてみて。
おっけー。

<各ゲージ領域(領域番号 5, 6, 9, 10 番)のアクション定義(config_bg.ma 内に記述)>

; メッセージ表示速度
5: storage="rclick.ks"; target="*msgspeed"; onenter="kag.fore.layers[10].top = 164, kag.fore.layers[10].visible = true"; onleave="kag.fore.layers[10].visible = false";

; オートモード速度
6: storage="rclick.ks"; target="*autospeed"; onenter="kag.fore.layers[10].top = 234, kag.fore.layers[10].visible = true"; onleave="kag.fore.layers[10].visible = false";

; BGM 音量
9: storage="rclick.ks"; target="*bgmvolume"; onenter="kag.fore.layers[10].top = 364, kag.fore.layers[10].visible = true"; onleave="kag.fore.layers[10].visible = false";

; SE 音量
10: storage="rclick.ks"; target="*sevolume"; onenter="kag.fore.layers[10].top = 434, kag.fore.layers[10].visible = true"; onleave="kag.fore.layers[10].visible = false";

できたよ〜。
ん、ちゃんと書けてるね。
それじゃ実行してみよっか。
うん!
必要なファイルはここに置いとくね。
じゃあ、実行してマウスカーソルを乗せてみるね。

<実行結果>

<チェックボックスの通常時の画像(左)とマウスカーソルを乗せた時の画像(右)>

<フォント名表示部の通常時の画像(左)とマウスカーソルを乗せた時の画像(右)>

<ゲージの通常時の画像(左)とマウスカーソルを乗せた時の画像(右)>

<「Back」の通常時の画像(左)とマウスカーソルを乗せた時の画像(右)>

クリックできる所はマウスカーソルを乗せるとちゃんと画像が変わってるね。
ん、これでロールオーバー処理は完成だね。
じゃあこれでコンフィグ画面は完成かな?
そうだね。
でも、このコンフィグ画面にはちょっと問題があるんだ。
え、問題って?
5章でメッセージウィンドウに付けるシステムボタンを作ったよね。
§5.10参照
うん、作ったね。
あれがコンフィグ画面と何か関係あるの?
実は、メッセージウィンドウに5章で作ったシステムボタンを付けた状態でコンフィグ画面を表示すると、 こんなふうになっちゃうんだ。

<システムボタンを付けた状態で表示したコンフィグ画面>

あっ、システムボタンが表示されちゃってる!
何でだかわかる?
えっ? え〜っと…なんでなの?
システムボタンのプラグインには、 onMessageHiddenStateChanged っていうメソッドがあったよね。
§5.9参照
メッセージウィンドウが非表示になった時にシステムボタンも非表示にしたりするためのメソッドだったよね。
コンフィグ画面を表示する時にもメッセージレイヤを非表示にしてるわけだけど、 その時には直接 setOptions メソッドを使ってたでしょ。
§6.5参照
うん、そだね。
これってユーザがメッセージレイヤを非表示にしたわけじゃないから、 コンフィグ画面を表示する時にはプラグインの onMessageHiddenStateChanged メソッドが呼び出されないんだ。
あ、そうなんだ。
だからシステムボタンが表示されちゃってたんだね…
ってワケで、ちょっと対処法を考えてみようと思ってね。
これって対処できるの?
ん〜、まぁ一番単純なやり方は、コンフィグ画面を表示する時にシステムボタンの onMessageHiddenStateChanged メソッドを引数を true にして呼び出して、 コンフィグ画面を閉じる時に引数を false にして呼び出すって方法かな。
あ、確かにそれならシステムボタンを非表示にできるね。
例えばコンフィグ画面を表示する時はこんな感じかな。

<コンフィグ画面を初期化する部分(改)(rclick.ks 内に記述)>

*rclick

; 右クリックでコンフィグ画面を閉じられるように右クリックの設定を変更します
[rclick jump=true storage="rclick.ks" target=*back enabled=true]

; 現在の状態をメモリ上の栞に保存しておきます
[tempsave place=0]

[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);
}
[endscript]

; 以下略

で、コンフィグ画面を閉じる時はこんな感じ。

<コンフィグ画面を閉じる部分(改)(rclick.ks 内に記述)>

*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]
[iscript]
// システムボタンを使っていて、コンフィグ画面を表示する前にメッセージレイヤが表示されていた時は onMessageHiddenStateChanged を呼び出します
if(typeof global.exsystembutton_object != "undefined" && kag.fore.messages[0].visible)
    exsystembutton_object.onMessageHiddenStateChanged(false);
[endscript]
[return]

なんか条件をチェックしてるみたいだけど、これって何をチェックしてるの?
システムボタンを使ってない時は onMessageHiddenStateChanged メソッドが呼び出せないから、 システムボタンが使われてるかどうか調べてるの。
それって typeof global.exsystembutton_object != "undefined" っていう部分だよね?
えっと、typeof って何だったっけ?
typeof 演算子は変数の型を調べる演算子だよ。
typeof global.exsystembutton_object"undefined" だったら、 その変数はまだ作られてないってことだから、つまりシステムボタンが使われてないってことになるの。
typeof 演算子については §1.6§4.5 参照。
あっ、そういえば typeof 演算子でそーゆーチェックができたよね。
あと、コンフィグ画面を表示する前に元々メッセージレイヤが非表示だった場合は onMessageHiddenStateChanged メソッドを呼び出す必要がないから、それも調べてるよ。
kag.fore.messages[0].visible の部分だね。
つまり、システムボタンが使われてて、さらにコンフィグ画面を表示する前にメッセージレイヤが表示されてたら onMessageHiddenStateChanged メソッドを呼び出すわけね。
これでシステムボタンがあってもちゃんとコンフィグ画面だけが表示されるね。
ん〜、ただこのスクリプトだとシステムボタンのオブジェクトが exsystembutton_object っていう名前じゃなくちゃいけないし、 0 番のメッセージレイヤと連動してないといけないって制約がついちゃうんだけどね。
あ、そっか。確かにそうだね。
でも他の名前にしたかったらスクリプトを書き換えればいいんじゃない?
まぁそうなんだけどね。
コンフィグ画面を表示する時にシステムボタンを非表示にする方法は他にもあると思うけど、 今回はこの方法だけ紹介しとくね。
うん、りょーかい。
それじゃ、今回はここまで。
コンフィグ画面も完成したし、第6章は今回で終わりになるの?
ん〜ん。まだまだ続けるよ。
えっ、そうなの?
じゃあこの先って何するの?
次回からはクリッカブルマップを使ってセーブ/ロード画面を作ろうと思うんだ。
あ〜、確かにそーいうのもクリッカブルマップを使って作れるよね。
ってワケで、次回からはセーブ/ロード画面を作っていくね。
それじゃ、また次回!


前へ | TOP | 次へ