『RPGツクールMZ』のウィンドウ枠を調べてみた
『RPGツクールMZ』で変更されたもので、結構大きいのが Window 周りの処理。
なんか良く分かんなくなったので、ざっくり流れを追ってみた。
ちなみに前作『RPGツクールMV』のウィンドウ関連は以下のように、結構まじめに調べて記事にしてます。
- ウィンドウ表示関連を調べてみた
- ウィンドウの内容を描いてみた
- 情報表示ウィンドウを調べてみた
- 選択ウィンドウを作ってみる
- タイトルとメニューのウィンドウを調べてみた
- イベントコマンドのウィンドウを調べてみた
- 戦闘シーンのウィンドウを調べてみた
…のに結構変わっちゃったのよねー最初に言ったように。
ここに挙げたMVの記事を、MZの参考にはしない方がいいと思います。
基本的にはどこが変わったかとか書かずに、初見のような感じで調べていこうと思います。
変わりすぎて一々ここが変わったとか書いていると文が膨れ上がりそうなので。
『RPGツクールMZ』非公式JavaScriptリファレンス
適宜このリファレンスのページにクラスなどリンクしていこうと思います。
Window枠を調べた動機
さて、僕は今 TF_VectorWindow.js というプラグインを作ってまして、これがずーっと作ってるんだけど、全然完成しない。
永遠のベータ版となっております。
未完成版のまま使われるとか、コンピュータの世界では特に珍しくないんですが、ちゃんと完成しときたいじゃないですか。
で、何が完成してないかというと、ウィンドウサイズの指定方法がイマイチわかってなくて、最初の表示の時だけずれちゃうし、その後もイマイチ想定通りに表示できてないんですよね。
ということでレイアウトまわり、MVのときにはちゃんと調べてなかったんで、しっかり調べていこうと思います。
Windowの基礎知識
画面に表示するクラスとして、『RPGツクールMZ』は Window と Sprite 系列が主にあるんですが、この違いは。
-
Window
は枠がある! -
Sprite
は枠がない!
なのです。そして Window
の枠は Sprite
を使って描かれてるんですね。
要は Sprite
の方が軽量なので枠がいらないなら Sprite
使った方がいいというわけです。
そしてこの枠の仕組みがなかなかにややこしい。
なお、Window
と Sprite
は両方とも次のように親クラスを辿れば同じ PIXI.Container
を継承しているので、割と似たような機能を持ってます。
あとで TilingSprite
も出てくるのでついでに継承ツリーに書いておきました。
Windowの部品構成
さて、リファレンス Window を見てみましょう。
-
_pauseSignSprite
ポーズサイン -
_upArrowSprite
上向き矢印 -
_downArrowSprite
下向き矢印 -
_clientArea
クライアントエリア-
_contentsSprite
内容-
contents
(_contentsSprite.bitmap
)
-
-
_cursorSprite
コマンド選択カーソル-
_cursorSprite.children
( Sprite × 9 ) カーソル枠を構成する9スライスのパーツ
-
-
_contentsBackSprite
項目の背景-
contentsBack
(_contentsBackSprite.bitmap
)
-
-
-
_container
ウィンドウ-
_frameSprite
ウィンドウ枠-
_frameSprite.children
( Sprite × 8 ) ウィンドウ枠を構成する9スライスのパーツ
-
-
_backSprite
ウィンドウ背景-
_backSprite.children
( TilingSprite×1 ) 繰り返しパターン用
-
-
みたいなのが書いてあまりす。Window
ってこんなにたくさんのオブジェクト持ってるんですね…もうやる気がみるみる萎えてきます。
今回とりあえず、コマンドやメッセージ表示は考えず、_container
以下のウィンドウの入れ物だけ考えます。
-
_container
ウィンドウ-
_frameSprite
ウィンドウ枠-
_frameSprite.children
( Sprite × 8 ) ウィンドウ枠を構成する9スライスのパーツ
-
-
_backSprite
ウィンドウ背景-
_backSprite.children
( TilingSprite×1 ) 繰り返しパターン用
-
-
こ、このくらいならなんとか。
Window のコードを読む
最終的には、Window_Message を理解したい。
とはいえ千里の道も一歩から、Window
から地道にコード読んでいきますかー。
_container のコードを読む
Window
の下に _container
があって、これは PIXI.Containerクラスで、単純にフォルダみたいな役割です。
これ自体は大して仕事はしません。名前からしてコンテナですしね。
ウィンドウ枠をまとめて扱いたいときに使われます。
例えば addChildToBack()
メソッドは _container
の手前にオブジェクトを追加するメソッドで、要はウィンドウ枠(_container
)の上かつ内容(_clientArea
)の下になんか表示させたいときに使うもののようです。
_container
の座標は Window
の左上と揃ってます。つまり [x, y] = [0, 0]です。
例外的に openness
プロパティの値(0 〜 255) に応じてサイズが変わるようになってて、これでウィンドウの開閉をしてます。
で、openness
の値が 0 だと isClosed()
が true
に、255だと isOpen()
が true
になります。
あと関係あるのは、opacity
プロパティで、ウィンドウ枠全体の不透明度(0 〜 255)を設定してます。
[文章の表示]コマンドで[背景]-[透明]を選んだ時に0にする、みたいな使い方してます。
opacity
で内容(文字とか顔画像など)の方が透明にならないの、変な感じもしますが。
_frameSprite のコードを読む
_frameSprite
は _container
に含まれる Sprite
クラスで、ウィンドウの枠担当です。
ウィンドウは8個の Sprite
を子オブジェクトに持っていて、それで枠を作っています。
-
_frameSprite
ウィンドウ枠-
_frameSprite.children
( Sprite × 8 ) ウィンドウ枠を構成する9スライスのパーツ
-
Window
クラスは _windowskin
プロパティを持ってて、これは Bitmap クラスです。要は画像データですね。
この _windowskin
に入っている画像は "img/system/Window.png" です。
中央(背景)を合わせて9個の画像を使うこの方式をコンピュータGUI業界では「9スライス」っていうんですが、詳細は検索していただくとして、その素材は _windowskin
の右上にあります。
_frameSprite.children[ 0 ]
みたいな感じで使われ、0〜8の配列番号は画像の左下にように振られています。
…イマイチ法則は分かりませんが、多分自分が番号を直接 JavaScript で扱うことはないので気にしなくていいでしょう。
8 はウィンドウでは使われてなくて、選択カーソル(上の画像では真ん中から右下のあたりの部品)では使われてます。
ちなみに ウィンドウの 8 に当たる部分は、矢印カーソルとか入っているのが分かるでしょうか。
ウィンドウ枠の画像全体は96×96ピクセル、角(0,1,2,3)のサイズは24×24です。
この枠の描画準備をしているのが _refreshFrame()
メソッドで、具体的な描画はMZになって作られた _setRectPartsGeometry()
メソッドに丸投げしてます。
正方形を#に区切って角(0,1,2,3)はそのまま表示、横棒縦棒(4,5,6,7)はウィンドウサイズに応じて引き延ばすという処理を行います。
そのため棒の部分に描いた模様は引き伸ばされるので、基本的には無地で引き伸ばさない向きに(横棒なら縦)に変化をつけた画像を用意することになります。
_backSprite のコードを読む
_backSprite
は _container
に含まれる Sprite
クラスで、ウィンドウの背景担当です。
子オブジェクトに、TilingSprite を抱えてます。ここで用意されるTilingSprite
オブジェクトには専用のプロパティ名はなくて汎用名の children
を使って _backSprite.children[ 0 ]
という感じに呼ばれてます。
-
_backSprite
ウィンドウ背景-
_backSprite.children
( TilingSprite×1 ) 繰り返しパターン用
-
Sprite
とは違ってTilingSprite
の方は設定した画像が繰り返し表示されます。
この背景は _refreshBack()
メソッドで描画されています。
中身は少々ややこしいのですが、
margin
が Window
の外側から _backSprite
までの距離(規定値:4ピクセル)です。
CSS的にはウィンドウ全体の領域から枠が描かれるまでの距離のような感じがしますが、ツクールはそうじゃないのでHTMLコーディングに慣れてる方はご注意!
margin
はエディタで変更できず4ピクセル固定で、ウィンドウデザインの大きな制約となっています。
ただ所詮背景が長方形限定なので margin
を変えられても、たいしたバリエーションは出せなさそうですが。
最近だと画像を細切れにしてまでサイズをケチる必要はないので、少なくともメッセージウィンドウは画像一枚ドーンと用意するタイプも採用して欲しかったなと思います。
TF_VectorWindow.js は画像用意することすらケチってその場で描画してるんですけどね。あと、角の丸みは好きなだけつけることができます!
_frameSprite
でも登場した _windowskin
の左上領域 [0, 0, 96, 96] が _backSprite
に使われ、その下の領域 [0, 96, 96, 96] が _backSprite.children[ 0 ]
に使われます。
_backSprite
の画像の上に _backSprite.children[ 0 ]
の画像が重なって表示されます。
なんで2種類重ねるのかちょっと不思議に思うかもしれません。
_backSprite
は、ひとつの画像が引き伸ばされます。なのでこちらはグラデーションのように繰り返しではなく全体にフィットしてほしい画像を使います。
_backSprite.children[ 0 ]
は画像が繰り返しパターンで描かれるので、模様のように縦横比が変わって歪むと困るものを設定するのです。
凝ってますね!
children
に2枚画像を配置しているのではなく、コンテナである _backSprite
自身も画像を表示しているのがちょっと特殊な感じします。
イラスト付きクリアファイルに、イラスト付き透明下敷きを挟んでるみたいな感じでしょうか。
そのせいで少々拡大率の計算がややこしいことになっていますが…こうした方が綺麗に表示されるんでしょうか?謎です。
そして最後に setTone()
メソッドで、[データベース]-[システム1]-[ウィンドウカラー]で指定した色にウィンドウを調整します。
あと _backSprite
関連では不透明度を指定するbackOpacity
プロパティがあります。
これがめちゃめちゃ謎仕様なんですが backOpacity
の値は0〜255中の192固定なんですよ。
ツクール本体にウィンドウの不透明度を指定する項目もありません。
つまりどういうことかというと、自作のウィンドウを作って完全に不透明の画像を作っても不透明度192に変換され…つまり絶対透けちゃう、ってことです。
助けて怪人ゾナーっ!
追記: 『RPGツクールMZ』version 1.3.0 で [システム2]-[ウィンドウの不透明度] が追加され、192以外の不透明度が指定できるようになりました!192に固定なの『RPGツクールMV』の時からなので、やっともやっとの修正ですが修正されて良かったです。
まとめ
メッセージ表示の部分まで調べようと思ったんですが、ひとまずウィンドウ描くところまでで燃え尽きてしまいました。ぷしゅううう。
ウィンドウ周りの画像はサイズや透明度などの値が固定なものが多く、理想通りのウィンドウを作るのがかなり難しい作りになっています。
普通なら「標準のをちょっと変えるぐらいで満足しておくのが無難」という結論に至るわけですが、無難な結論に至らずにプラグインでウィンドウ自作しようとしているので、もーちょっと頑張って調べてみようと思います。
Discussion