⚔️

『RPGツクールMZ』のウィンドウ枠を調べてみた

2021/04/25に公開

『RPGツクールMZ』関連記事 目次

『RPGツクールMZ』で変更されたもので、結構大きいのが Window 周りの処理。
なんか良く分かんなくなったので、ざっくり流れを追ってみた。

ちなみに前作『RPGツクールMV』のウィンドウ関連は以下のように、結構真面目に調べて記事にしてます。

…のに結構変わっちゃったのよねー最初に言ったように。
ここに挙げたMVの記事を、MZの参考にはしない方がいいと思います。

基本的にはどこが変わったかとか書かずに、初見のような感じで調べていこうと思います。
変わりすぎて一々ここが変わったとか書いていると文が膨れ上がりそうなので。

『RPGツクールMZ』非公式JavaScriptリファレンス
適宜このリファレンスのページにクラスなどリンクしていこうと思います。

Window枠を調べた動機

さて、僕は今 TF_VectorWindow.js というプラグインを作ってまして、これがずーっと作ってるんだけど、全然完成しない。
永遠のベータ版となっております。
未完成版のまま使われるとか、コンピュータの世界では特に珍しくないんですが、ちゃんと完成しときたいじゃないですか。
で、何が完成してないかというと、ウィンドウサイズの指定方法がイマイチわかってなくて、最初の表示の時だけずれちゃうし、その後もイマイチ想定通りに表示できてないんですよね。
ということでレイアウトまわり、MVのときにはちゃんと調べてなかったんで、しっかり調べていこうと思います。

Windowの基礎知識

画面に表示するクラスとして、『RPGツクールMZ』は WindowSprite 系列が主にあるんですが、この違いは。

  • Window は枠がある!
  • Sprite は枠がない!

なのです。そして Window の枠は Sprite を使って描かれてるんですね。
要は Sprite の方が軽量なので枠がいらないなら Sprite 使った方がいいというわけです。
そしてこの枠の仕組みがなかなかにややこしい。

なお、WindowSprite は両方とも次のように親クラスを辿れば同じ 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() メソッドで描画されています。
中身は少々ややこしいのですが、
marginWindow の外側から _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』のウィンドウ内容を調べてみた

Discussion