さて、じゃ早速前回の問題を修正していこっか。 | |
そーいえば、何で 200% で表示した時にはちゃんと画像が復元されたのに、 80% で表示すると画像が切れちゃったの? | |
実はね、見た目は問題なかったけど、200% の時もホントはちゃんと復元できてなかったんだよ。 | |
えっ、そーなの? | |
ん。ちなみにこの問題の原因はココにあるんだ。 |
「レイヤサイズの復元」ってトコ? | |
そ。 | |
何でコレが問題なの? | |
んー、それは KAGLayer クラスの restore メソッドを見ながら説明した方がわかりやすいかな。 | |
KAGLayer クラスの restore メソッドって、 レイヤサイズを復元してるメソッドだよね? | |
そう。 ちなみに KAGLayer クラスの定義は system フォルダにある KAGLayer.tjs に書いてあって、restore メソッドはこんな感じになってるよ。 |
<KAGLayer クラスの restore メソッド(KAGLayer.tjs より抜粋)>
最初に setImageSize メソッドを呼び出してるでしょ。 | |
※setImageSize メソッドについては §7.3 参照。 | |
うん。 | |
ここでセーブデータに保存されてるレイヤの画像サイズを読み込んで復元してるの。 | |
setImageSize メソッドの引数の dic.imageWidth と dic.imageHeight ってゆーのがセーブデータに保存されてるレイヤの画像サイズってコト? | |
そうだよ。 restore メソッドの引数の dic っていう辞書配列は、 例えば表画面の 0 番の前景レイヤの状態を復元する時は foreFlags[0](=f.foreCharacterLayers[0]) になってて、 裏画面の 0 番の前景レイヤを復元する時は backFlags[0](=f.backCharacterLayers[0]) になってるんだ。 |
|
※foreFlags, backFlags 等については §9.11 参照。 | |
じゃあ表画面の 0 番の前景レイヤだったら setImageSize(foreFlags[0].imageWidth, foreFlags[0].imageHeight); で、 裏画面の 0 番の前景レイヤだったら setImageSize(backFlags[0].imageWidth, backFlags[0].imageHeight); になるってことだね。 | |
そういうこと。 で、例えば前回やったみたいに画像を 80% に縮小表示すると、 元々の画像( のことね)のサイズは 64×64 ピクセルだから… |
|
64×0.8 は、え〜っと… 51.2 だから、51.2×51.2 ピクセルになるってこと? | |
小数点以下は切り捨てられるから、51×51 ピクセルになるね。 | |
あそっか。画像サイズは整数なんだよね。 | |
セーブデータには縮小後のサイズが記録されてるから、それを読み込んで setImageSize メソッドを呼び出すと setImageSize(51, 51); になって、 レイヤの画像サイズは 51×51 ピクセルに設定されるわけね。 | |
うん、そうなるよね。 | |
でも restore メソッドが呼び出された時にはまだ画像は縮小されてないから、 ここでレイヤのサイズを小さくすると、こんなふうにレイヤの画像の一部が無くなっちゃうんだ。 |
<setImageSize メソッド実行後のレイヤの状態(80% 縮小時)>
あ、そーいえば前回 80% に縮小した後にセーブデータを読み込んだ時も、 こんなふうに画像の右下の部分が切れちゃってたよね。 | |
それは画像を縮小する前にレイヤのサイズを小さくしてたのが原因だったってワケだね。 ちなみに 200% に拡大する場合は setImageSize(128, 128); が実行されるから… |
<setImageSize メソッド実行後のレイヤの状態(200% 拡大時)>
こんなふうにレイヤのサイズが 128×128 ピクセルに設定されるの。 この場合は画像が切れたりしないし、レイヤが拡張された部分は透明色になってて見えないから、 一見ちゃんと復元されてるように見えてたってワケ。 でも実際にはレイヤのサイズがセーブした時とは違っちゃうんだよね。 |
|
なるほどねぇ… | |
じゃあ、この問題を解決しようと思ったらどうすればいいと思う? | |
えっ? えーっと…要するにレイヤの画像サイズが拡大とか縮小した後のサイズになっちゃうからいけないんだよね? |
|
そうだね。 | |
じゃあ setImageSize メソッドを呼び出さないようにすればいいんじゃない? | |
まぁそれはそうなんだけど、KAGLayer クラスの restore メソッドを勝手に書き換えちゃうと他の問題が起きるかもしれないから、 それはどうかと思うよ? | |
そっかぁ… じゃあどーすればいいんだろ…? |
|
さっき「レイヤの画像サイズが拡大とか縮小した後のサイズになっちゃうからいけない」って言ってたよね? | |
うん。 | |
それってつまり、レイヤの画像サイズが拡大とか縮小する前のサイズにならなければ OK ってことだよね。 | |
う〜ん、確かにそーだけど、setImageSize メソッドが呼び出されたらレイヤの画像サイズは変わっちゃうんだからどーしよーもないじゃない? | |
setImageSize メソッドが呼び出されてもレイヤの画像サイズが変わらないようにすれば大丈夫でしょ? | |
えっ、そんなコトできるの? | |
例えば、レイヤの画像サイズが 100×100 ピクセルの時に、 setImageSize(100, 100); を実行しても画像サイズは変わらないよね。 | |
あ、そっか。 setImageSize メソッドを呼び出す前の画像サイズを引数に指定すればいいんだね。 |
|
そ。つまり、KAGLayer クラスの restore メソッドが呼び出される前に、予め imageWidth と imageHeight の値を拡大/縮小する前の元々の画像サイズに設定しとけばいいってワケ。 | |
なるほどね…って言いたいトコだけど、 どうやって imageWidth と imageHeight の値を元々の画像サイズに設定するの? | |
セーブする時(厳密に言うとセーブ可能なラベルを通過する時だね)に loadParams の imageWidth 要素と imageHeight 要素(= dic.imageWidth と dic.imageHeight)の値が元々の画像の幅と高さになるように設定しとけばいいの。 | |
※loadParams については §9.11 参照。 | |
セーブする時に設定するの? | |
この引数 dic はセーブデータに書き込まれてる loadParams になってるから、セーブデータに元々の画像サイズを書き込んどけば、 setImageSize メソッドが呼び出されてもレイヤの画像サイズは変わらなくなるわけ。 | |
あ、そっか。なるほどね。 | |
じゃセーブデータに元々の画像のサイズを書き込もうと思ったら、 プラグインにどんなメソッドを追加すればいい? | |
んーと、セーブデータに書き込みたいわけだから、 onStore メソッドかな? | |
※onStore メソッドについては §4.11 参照。 | |
ん、そうそう。 onStore メソッドでこんな感じに書き込めば OK。 |
最初の foreFlags と backFlags のとこは onRestore メソッドとおんなじだから大丈夫だよね? | |
うん。 | |
じゃ for ブロックの中を見てくね。 まずここの if の条件で何をチェックしてるかはわかる? |
|
えっと、flags.loadParams が void じゃないかどうかをチェックしてるみたいだね。 その前に flags = foreFlags[i]; って書いてあるから、 例えば i が 0 だったら flags.loadParams は foreFlags[0].loadParams になるから、 表画面の 0 番の前景レイヤに画像を読み込んだ時に指定されてた属性ってことだよね。 |
|
ん、そだね。 | |
確か前回 loadParams はレイヤに画像が読み込まれてない時とか freeimage タグで画像を解放した時に void になるって言ってたから、 レイヤに画像が読み込まれてたら、if の条件が真になって、 if ブロックの中身が実行されるんだね。 | |
そうそう。 で、その if ブロックの中で元々の画像サイズを loadParams の imageWidth 要素と imageHeight 要素に書き込んでるわけね。 あと一応レイヤの表示サイズも width 要素と height 要素に書き込んでるよ。 |
|
foreInfo[i].originalWidth と foreInfo[i].originalHeight ってゆーのが画像の元々の幅と高さなの? | |
そうだよ。 | |
これって前はなかったよね? | |
ん、これは今回新しく作る辞書配列で、
画像を読み込む時に originalWidth 要素と
originalHeight 要素に画像の元々の幅と高さを代入しとくの。 代入する部分は別のメソッドに書かなくちゃいけないから、 とりあえず今はそれぞれ画像の元々の幅と高さが代入されてるって思っといて。 |
|
そーなんだ、りょーかい。 | |
ちなみに foreInfo と backInfo はどっちも ImageHandlerPlugin クラス(今作ってる画像読み込み機能拡張プラグインのことね)のメンバ変数で、 それぞれ表画面と裏画面の前景レイヤに読み込まれてる画像の元々の幅と高さを記録しとくための配列だよ。 | |
※メンバ変数については §2.2 参照。 | |
foreInfo[i] と backInfo[i] にそれぞれ表画面と裏画面の i 番の前景レイヤに読み込まれてる画像の元々のサイズが記録されるんだよね? | |
そうだよ。 | |
えっと、じゃあ for ブロックの中でやってることって、 表画面と裏画面のそれぞれの前景レイヤに画像が読み込まれてたら、 foreInfo と backInfo に元々の画像サイズを記録して、 読み込まれてなかったら何もしないってことかな? | |
そういうこと。 じゃ次は originalWidth 要素と originalHeight 要素に画像の元々の幅を書き込まなくちゃいけないわけだけど、 これってどのメソッドでやればいいと思う? |
|
さっき画像を読み込む時に書き込むって言ってたから、 image タグを実行する時に書き込むってコトだよね…? | |
だね。 …って言っても image タグの中身は変えられないから、その後ってことになるね。 |
|
ってことは… processImage メソッドってコト? | |
そ。 | |
じゃあまた processImage メソッド書き換えるんだ? | |
うん、また書き換えるの。こんなふうにね。 |
今回もどこが変わったかわかりやすいように、前の processImage メソッドから変わったとこにだけコメント書いてるよ。 | |
前は isCharacterLayer メソッドを呼び出して layer が前景レイヤかどうかチェックしてたけど、それが無くなって getLayerInfo っていうメソッドが呼び出されてるみたいだけど、これって新しいメソッドだよね? | |
ん、そだよ。 getLayerInfo メソッドは、引数に指定されてるレイヤに対応する、 元々の画像の幅と高さを記録するための辞書配列を返すメソッドなんだ。 |
|
えっと…それってつまりどーいうコト? | |
例えば layer が表画面の 0 番の前景レイヤへの参照になってたら、 foreInfo[0] を返すってことだよ。 | |
あ、そーゆーコトね。 | |
あと layer が前景レイヤ以外のレイヤへの参照になってたら void を返すようにしてるよ。 | |
getLayerInfo メソッドの戻り値が void だったら return してるから何にもしないってことだよね? | |
そ。getLayerInfo メソッドを呼び出すことで layer が前景レイヤかどうか判るから、isCharacterLayer メソッドは呼び出さなくてもよくなるワケ。 | |
なるほど、だから isCharacterLayer メソッドを呼び出してる部分が無くなってたんだね。 | |
んで後はここで info の originalWidth 要素と originalHeight 要素にそれぞれ layer の imageWidth と imageHeight の値(元々の画像の幅と高さ)を代入すれば OK。 | |
え〜っと、ここ って image タグが実行された後だし scaleImage メソッドとかで画像が拡大/縮小される前だから、 こうすれば info.originalWidth と info.originalHeight に画像の元々の幅と高さがちゃんと代入されるってことかな? | |
ん、その通りだよ。 じゃ次はさっき出てきた getLayerInfo メソッドを見ていこっか。 |
|
は〜い。 | |
これが getLayerInfo メソッドのスクリプトだよ。 |
isCharacterLayer メソッドと似てるから大体何やってるかはわかると思うんだけど、どうかな? | |
確かに find メソッドで前景レイヤかどうかを調べてるところとか似てるね。 isCharacterLayer メソッドは true か false を返してたけど、こっちは辞書配列を返してるんだね。 |
|
あと、foreInfo と backInfo はこんなふうに最初から配列になってるんだけど… |
<ImageHandlerPlugin クラスのメンバ変数宣言部>
配列の中身は空っぽだから、もしまだ配列の中身(元々の画像のサイズを記録する辞書配列のことね)が作られてなかったら、 こことかここで新しく辞書配列を作って返すんだ。 | |
配列の中身って最初から作っとかなくてだいじょーぶなの? | |
配列の中身が作られてないってことはレイヤに画像が読み込まれてないってことだから、 セーブデータに何も記録する必要ないでしょ。だから中身がなくても大丈夫なの。 | |
あ、そー言われればそーだね。 | |
さて、これであと2つメソッドを追加すればプラグイン完成だね。 | |
え、まだメソッド追加しなきゃいけないの? | |
foreInfo と backInfo で表画面と裏画面のレイヤの情報を管理する以上、onCopyLayer メソッドと onExchangeForeBack メソッドはちゃんと作らなくちゃね。 | |
※onCopyLayer メソッドについては §4.6、 onExchangeForeBack メソッドについては §4.7 参照。 | |
onCopyLayer メソッドと onExchangeForeBack
メソッド…ってどんなメソッドだったっけ? なんかトランジションとかの関係だったよーな気がするんだけど…? |
|
onCopyLayer メソッドは backlay タグとか
forelay タグを実行した時に呼び出されるね。 あとトランジションが終わった時にも呼び出されるよ。 |
|
あ、そーそー。onCopyLayer メソッドって確か表画面の内容が裏画面にコピーされたり、 裏画面の内容が表画面にコピーされたりすると呼び出されるんだったよね。 | |
そ。じゃ、今回のプラグインの場合は onCopyLayer メソッドが呼び出されたらどうすればいいと思う? | |
えーっと… backInfo に foreInfo の中身をコピーしたり、 foreInfo に backInfo の中身をコピーしたり…とか? | |
ん、そうだね。 | |
あ、それでいーんだ。 | |
んじゃ onCopyLayer メソッド作ってみて。 ちなみに onCopyLayer メソッドには toback っていう引数があって、 表画面の内容が裏画面にコピーされる時には true になってて、 裏画面の内容が表画面にコピーされる時には false になってるよ。 |
|
配列の中身をコピーするのって assign メソッドだったっけ? | |
※assign メソッドについては §1.14 参照。 | |
うん。 | |
じゃあ作ってみるね。 |
こんな感じかな? | |
ん、これで OK。 それじゃ次は onExchangeForeBack メソッドだね。 これは基本的にトランジションが終わった後に呼び出されるメソッドだよ。 Fore(表画面)と Back(裏画面)を Exchange(交換)するってことだから… |
|
あ、表画面と裏画面のレイヤが入れ替わった時に呼び出されるんだ。 | |
そう。じゃこれで onExchangeForeBack メソッドも作れるよね? | |
foreInfo と backInfo を入れ替えるだけでいいの? | |
ん、それだけでいいよ。 | |
そっか。じゃあ… |
こうなるよね。 | |
これも OK だね。 それじゃ今度こそ完成だから、前回うまくいかなかったスクリプトを実行してみよっか。 必要なスクリプトはここにまとめとくね。 |
|
※09/03/01 追記: eximage マクロと image タグを混在させるとエラー(例外)が発生するというご指摘を頂きましたので、 両者を混在させてもエラーが発生しないように改良した eximage2.ks を同梱しました。 |
|
はーい! それじゃあ実行してみるね。 |
あ、今度はちゃんと復元されてる! | |
ん、今回はうまくいったね! あと回転とか拡大/縮小と回転を同時にやるのとかも試してみてね。 |
|
はーい。 は〜、やっと完成できた〜。 |
|
今回のプラグインはちょっと作るの大変だったかな。 | |
すごいタイヘンだったよ〜。 スクリプトとかかなりややこしかったし。 |
|
まぁ確かにそうかもね。 あ、そうそう。 |
|
ん? なに? | |
この画像読み込み機能拡張プラグインなんだけどね、 いくつか制限があるから使う時には注意してね。 | |
えっ、制限って? | |
結構色々あるんだけどね、まとめるとこんな感じ。 |
<eximage マクロを使用して画像を拡大/縮小/回転した時の制限事項>
簡単に言うと、eximage マクロで画像を拡大・縮小・回転した時には、 クリッカブルマップとかアニメーションとか pimage タグとか ptext タグは使わないようにしてね、ってこと。 | |
あ、そーいうのって使えなくなっちゃうんだ。 | |
今回作ったプラグインで拡大とかしてるのはレイヤのメイン画像とマスク画像だけで、 領域画像とかアニメーション用の画像とか部分画像とかまでは処理してないからね。 | |
そっかぁ… | |
まぁやろうと思えばこの制限をなくせるかもしれないけど、 かなり大変だと思うからそこまではやらないことにするね。 | |
確かにタイヘンそーだよね… | |
ってワケで、これで画像読み込み機能拡張プラグインは完成ってことにするね。 | |
うん、わかった。 じゃあこれで第9章は終わりになるの? |
|
んー、そうしようかと思ったんだけど、 せっかく画像の拡大・縮小・回転ができるようになったから、 これをもうちょっと他の事にも利用しようかなーと思うんだ。 | |
え、他の事って? | |
move タグは知ってるよね? | |
うん、もちろん知ってるよ。 レイヤを動かしたり不透明度を変えたりするタグだよね。 |
|
今度はその move タグを拡張してみようかなーって思ったの。 | |
move タグを拡張するって… もしかして画像を動かしながら拡大とか縮小とか回転できるようにするってコト? |
|
ん、そのとーり。 | |
そりゃ確かにそれが出来れば便利になりそーだけど… なんかそれってすごい難しそーじゃない? |
|
んー、画像読み込み機能拡張プラグインよりはちょっと難しいかもね。 | |
今回のプラグインだけでも十分難しかったのに、 これ以上難しくなったらついてけなくなりそーなんだけど… | |
まぁ次はついてけなかったとしても大丈夫だから、とりあえず作るだけ作ってみよ? move タグが拡張できると色々使えそうでしょ? |
|
ん〜…まーそれなら作ってみてもいーかもね。 | |
んじゃ次回からは move タグを拡張して、 レイヤを動かしたり不透明度を変えながら拡大・縮小・回転ができるようにしていくね。 | |
は〜い! | |
それじゃ、また次回ね! |