ゲーム中にウィンドウサイズを変更したい

返信する
七転八倒斎
記事: 12
登録日時: 2022年5月03日(火) 01:21

ゲーム中にウィンドウサイズを変更したい

投稿記事 by 七転八倒斎 »

プラグインを作成し、

コード: 全て選択

	Window_Message.prototype.windowWidth = function() {
		return Graphics.boxWidth - 調整したい分のピクセル;
	};
でウィンドウの幅を変更できたのですが、ゲーム中に任意のタイミングで変更するようにしたい場合、どうすればいいかわからないです…

単純にif文で囲ってゲーム内スイッチがONの時に分岐できるかなと思ったのですが

コード: 全て選択

if ($gameSwitches.value(1)) {
	Window_Message.prototype.windowWidth = function() {
		return Graphics.boxWidth - 調整したい分のピクセル;
	};
};
全く動作してくれませんでした。

どなたかご教授頂けましたら幸いです…!
-----

七転八倒しながらなんか作ってます。
アバター
Plasma Dark
記事: 731
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: ゲーム中にウィンドウサイズを変更したい

投稿記事 by Plasma Dark »

プラグインに書かれた処理は、まず一通りゲーム起動時にのみ実行されます。

コード: 全て選択

クラスA.prototype.メソッドA = function() {
  処理
};
こう書いた場合、クラスAのメソッドAに、関数を代入します。
代入自体をスイッチによって分岐しようとしても、ゲーム起動時にのみ実行されるため、何も起きません。
(スイッチはゲーム起動直後には全てOFFの扱いになっています)

ゲーム中の処理を分岐したい場合、関数の中身に分岐処理を書く必要があります。

コード: 全て選択

クラスA.prototype.メソッドA = function() {
  if (条件) {
    処理
  } else {
    処理
  }
};
さて、これだけではメッセージウィンドウ幅を動的に変えることはできません。
なぜなら、 Window_Message.prototype.windowWidth はマップシーンに入った際にウィンドウを作るためにしか使われていないからです。
一度メニューを開いて戻ればウィンドウ幅は変わります。

これをなんとかしようとする場合、やり方は色々考えられますが、updatePlacementの先頭に
widthとwindowWidthの返す結果が異なる場合のみ
ウィンドウのx,widthを調整してcreateContentsを呼び出す処理を足してあげるのがシンプルだと思います。
七転八倒斎
記事: 12
登録日時: 2022年5月03日(火) 01:21

Re: ゲーム中にウィンドウサイズを変更したい

投稿記事 by 七転八倒斎 »

返信ありがとうございます!
javascriptの知識がほぼ無いので見様見真似で試した結果がアレでした…
updatePlacementの先頭にwidthとwindowWidthの返す結果が異なる場合のみウィンドウのx,widthを調整してcreateContentsを呼び出す
とりあえずupdatePlacement(rpg_windows.js内でたくさんあったのでこれかなというものを抜き出して)の先頭にif文追加してcreateContentsを呼び出す(合ってるか自信は無い)ような事を書いてみたのですが、ウィンドウのx,widthを調整するという部分をどうすれば良いのかさっぱりでした…

if文でwidthとwindowWidthを参照しているという事は、どこかでwidthかwindowWidthの値を変更しなきゃならない感じでしょうか?

コード: 全て選択


Window_Message.prototype.updatePlacement = function() {
    if(!(width === windowWidth)){
        【x,widthを調整する?】
        this.createContents();
    }
    this._positionType = $gameMessage.positionType();
    this.y = this._positionType * (Graphics.boxHeight - this.height) / 2;
    this._goldWindow.y = this.y > 0 ? 0 : Graphics.boxHeight - this._goldWindow.height;
};

どうかご教授頂けますと幸いです…!
-----

七転八倒しながらなんか作ってます。
アバター
Plasma Dark
記事: 731
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: ゲーム中にウィンドウサイズを変更したい

投稿記事 by Plasma Dark »

問題をひとつずつ解決していきましょう。
windowWidth の処理書き換えについては、特定のスイッチがONだった場合にウィンドウ幅を細くするという前提で書いてみます。

コード: 全て選択

const _windowWidth = Window_Message.prototype.windowWidth;
Window_Message.prototype.windowWidth = function () {
  return $gameSwitches.value(スイッチID) ? 細くなった後の幅 : _windowWidth.call(this);
};
_windowWidth に元々の処理を退避しておいて、スイッチがONの場合のみ細くなった後の値を、
OFFの場合に元々の処理で返していた値を返すようにしています。
前にも述べた通り、これだけではスイッチをONにしてもメニューを開くなどして別シーンに遷移しなければ
メッセージウィンドウ幅は変わりません。

書き換えるべき updatePlacement の処理自体はあっていますが、どうしてそうすると解決するのかを簡単に説明します。
rpg_windows.js の関係する箇所を雰囲気で読みながら、プラグインで書く処理を想像してみてください。

Window_Message.prototype.initialize が、メッセージウィンドウを生成する際に呼び出される関数です。
ツクールMVのウィンドウ生成では、基本的にウィンドウ左上のX,Y座標、ウィンドウの幅、高さを設定し、
Window_Base.prototype.initialize に渡します。
ここで作られた値には、 Window_Message クラスのメソッドからは this.x, this.y, this.width, this.height でアクセスすることができます。
幅については、 this.windowWidth() で得た値を渡していることが読み取れるかと思います。

実はこれらの値が、ウィンドウの座標とサイズを表すものになっているため、幅を調整するのであればこのwidthを変更してあげる必要があります。
メッセージの開始時に Window_Message.prototype.updatePlacement が呼び出され、そこでウィンドウの表示位置を変える処理が行われているため、幅の調整もここでやってしまおう、というのが私の提案です。

this.windowWidth() で得た値と実際の幅であるところの this.width の値を比較して、違っているようなら this.width を更新してあげる、というわけです。
(this.windowWidth() で得られる値は、先程書き換えたので指定のスイッチがONになっていると元々の幅よりも小さい値になっているはずです)

コード: 全て選択

const _updatePlacement = Window_Message.prototype.updatePlacement;
Window_Message.prototype.updatePlacement = function () {
  if (this.windowWidth() !== this.width) {
    this.width = this.windowWidth();
  }
  _updatePlacement.call(this);
};
実はこれだけでもメッセージウィンドウの幅は変わりますが、挙動が微妙になるかと思います。
スイッチをONにしてからメッセージを表示しようとすると、幅は細くなるものの、ウィンドウの位置が左端に寄っています。
そこから更にメニューを開くなどしてから戻って、もう一度メッセージを表示すると、ウィンドウの位置が真ん中に寄ります。
これは、メッセージウィンドウの生成時にX座標を、生成時点の幅をもとにして中央寄せになるよう計算しているからです。
今回はどうしたいかわかりませんが、ひとまず中央寄せで統一するということにして処理を書くと以下のようになります。

コード: 全て選択

const _updatePlacement = Window_Message.prototype.updatePlacement;
Window_Message.prototype.updatePlacement = function () {
  if (this.windowWidth() !== this.width) {
    this.width = this.windowWidth();
    this.x = (Graphics.boxWidth - this.width) / 2;
  }
  _updatePlacement.call(this);
};
x, widthを調整するというのはこういうことです。
createContents についてはもう少し複雑な説明が必要なのと、必ずしも必要ではないので次の書き込みにいきます。
アバター
Plasma Dark
記事: 731
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: ゲーム中にウィンドウサイズを変更したい

投稿記事 by Plasma Dark »

スイッチがONの場合のみ、元々の幅より狭くする、といった処理の場合には、createContentsを呼び出さなくても問題にはなりにくいと思います。
逆の場合(スイッチがOFFの場合のみ元々の幅より狭くする)は問題になります。

コード: 全て選択

const _windowWidth = Window_Message.prototype.windowWidth;
Window_Message.prototype.windowWidth = function () {
  return $gameSwitches.value(スイッチID) ? _windowWidth.call(this) : 細くなった後の幅;
};
windowWidth の分岐処理を逆転し、スイッチがONの場合のみ元々の処理を呼び出すようにしました。
これでスイッチをONにし、横に長い文章を表示させようとしてみてください。
ウィンドウの途中で文章が途切れてしまうはずです。

これは、メッセージウィンドウの生成時に描画範囲の大きさも決めて生成しているからです。

Window_Base.prototype.createContents の中では、ウィンドウ内にコンテンツ(文字など)を描画する範囲を、幅と高さを指定して生成しています。
幅を指定するために呼び出されるのは Window_Base.prototype.contentsWidth です。

コード: 全て選択

Window_Base.prototype.contentsWidth = function() {
  return this.width - this.standardPadding() * 2;
};
先程、 updatePlacement で x, width を調整するコードを書いているので、調整後に描画範囲を再生成する(すなわち、createContentsを呼び出す)ことで解決します。

以上を踏まえてプラグインを書くと、こんな形になります。
七転八倒斎
記事: 12
登録日時: 2022年5月03日(火) 01:21

Re: ゲーム中にウィンドウサイズを変更したい

投稿記事 by 七転八倒斎 »

返信ありがとうございます!!
プラグインまで組んでいただけるとは…!

やはりjavascriptの知識がないと完全に把握するのは難しいですね…
ご説明ありがとうございます。これを機に勉強してみようと思います!
-----

七転八倒しながらなんか作ってます。
返信する

“MV:質問”に戻る