バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

返信する
Arkroyal
記事: 80
登録日時: 2021年1月06日(水) 10:41

バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

投稿記事 by Arkroyal »

お世話になっております、皆様。

以前QTE関連の相談でプレイヤーの入力をリアルタイムに監視する代わりにボタンをクリックして入力を認識するように変更した結果フレームの改善に成功した者です。

数日前にとある方から気になる報告を受けまして、それは「私がバトル画面に追加したウィンドウがフレームに相当な負担をかけている」ということでした。

なので皆様に一度私のコードを見てくださればと思いこのように質問を申し上げることになりました。





q1.png
このようなものを作りました。コードは以下となります。


コード: 全て選択

(function() {

    var _Scene_Battle_create = Scene_Battle.prototype.create;
    Scene_Battle.prototype.create = function() {
        _Scene_Battle_create.call(this);
        this.createPlayerWindow();
        this.createTekiWindow();
    };

    Scene_Battle.prototype.createPlayerWindow = function() {
        this._PlayerWindow = new Player_Info();
        this.addWindow(this._PlayerWindow);
    };

    Scene_Battle.prototype.createTekiWindow = function() {
        this._TekiWindow = new Teki_Info();
        this.addWindow(this._TekiWindow);
    };
    
    var _Scene_Battle_update = Scene_Battle.prototype.update;
    Scene_Battle.prototype.update = function() {
        _Scene_Battle_update.call(this);
        this._PlayerWindow.setText();
        this._TekiWindow.setText();
    };
    
    //drawGauge省略
    
    	function Player_Info() {
	    this.initialize.apply(this, arguments);
	}
	
	Player_Info.prototype = Object.create(Window_Base.prototype);
	Player_Info.prototype.constructor = Player_Info;
	Player_Info.prototype.initialize = function() {
		var x = 1080;
		var y = 361;
		var width = 200;
		var height = 360;
		Window_Base.prototype.initialize.call(this, x, y, width, height);
	};

	Player_Info.prototype.setText = function(str) {
		this._text = str;
		this.refresh();
	};
	
	Player_Info.prototype.refresh = function() {
	this.contents.clear();
        this.changeTextColor(this.systemColor());
        this.drawText($gameActors.actor(1)._name,5,0);
        this.resetTextColor();
        this.changeTextColor(this.textColor(4));
        this.drawText("Lv",120,25);
        this.resetTextColor();
        this.drawText($gameActors.actor(1).level,145,25);
        this.drawActorHp($gameActors.actor(1),5,50,160);
        this.drawActorTp($gameActors.actor(1),5,85,160);
        this.changeTextColor(this.textColor(23));
        this.drawText("攻撃力",5,140);
        this.drawText("魔法力",5,170);
        this.drawText("敏捷性",5,200);
        this.drawText("運",5,230);
        this.resetTextColor();
        this.drawText($gameActors.actor(1).param(2),105,140);
        this.drawText($gameActors.actor(1).param(4),105,170);
        this.drawText($gameActors.actor(1).param(6),105,200);
        this.drawText($gameActors.actor(1).param(7),105,230);
	};
	
	// fontsize, backopacity, padding 省略


Teki_InfoはPlayer_Infoと同じ構造となります。

setTextを使ったのは、drawItemでは何故かウィンドウの中身がまともに出力できなかったのが理由です。

textcolorの負担が大きいとのことがありましたので主人公の名前やレベルなどはイメージに変更することを考えています。



問題なのはrefreshの処理でしょうか?それともtextcolorの無駄遣いでしょうか?

この未熟者が何を間違っているのかを教えてくださればと思う所存です。皆様のご指導をお待ちしております。何卒よろしくお願いいたします。
名無し蛙
記事: 352
登録日時: 2015年11月23日(月) 02:46

Re: バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

投稿記事 by 名無し蛙 »

どうもこんばんは
全容が分からない事には部分的な事しか指摘出来ませんけどコードを読んで引っ掛かるのはこの部分ですね。

コード: 全て選択

    var _Scene_Battle_update = Scene_Battle.prototype.update;
    Scene_Battle.prototype.update = function() {
        _Scene_Battle_update.call(this);
        this._PlayerWindow.setText();
        this._TekiWindow.setText();
    };
RGSS時代から言われてる事なんですけど
描画系メソッドを毎フレーム呼び出すコーディングは原則非推奨です。
コアスクリプトでもその点、変化が生じた時に必要最小限しか使用しないように気を付けています。
最低限、エネミーやアクターの状態に変化が生じた時だけ
リフレッシュするように無意味な更新処理は控えた方が良いです。
Arkroyal
記事: 80
登録日時: 2021年1月06日(水) 10:41

Re: バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

投稿記事 by Arkroyal »

名無し蛙 さんが書きました:どうもこんばんは
全容が分からない事には部分的な事しか指摘出来ませんけどコードを読んで引っ掛かるのはこの部分ですね。

コード: 全て選択

    var _Scene_Battle_update = Scene_Battle.prototype.update;
    Scene_Battle.prototype.update = function() {
        _Scene_Battle_update.call(this);
        this._PlayerWindow.setText();
        this._TekiWindow.setText();
    };
RGSS時代から言われてる事なんですけど
描画系メソッドを毎フレーム呼び出すコーディングは原則非推奨です。
コアスクリプトでもその点、変化が生じた時に必要最小限しか使用しないように気を付けています。
最低限、エネミーやアクターの状態に変化が生じた時だけ
リフレッシュするように無意味な更新処理は控えた方が良いです。



ご指導ありがとうございます!

指摘してくださった部分ですが、Scene_Battle.prototype.refreshStatusやBattleManager.refreshStatusなどを調べたところ「どうやって変化を感知するのか」がさっぱりわかりませんでした……。よろしければこの部分についてもっと詳しく教えてくだされば大変助かります。

私に思いついた方法と言えば、変化前のHPなどを変数に入れておいてそれらに変化があったらrefreshを呼ぶくらいですが、このような方法で解決するのも一つの手でしょうか?
名無し蛙
記事: 352
登録日時: 2015年11月23日(月) 02:46

Re: バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

投稿記事 by 名無し蛙 »

Arkroyal さんが書きました:私に思いついた方法と言えば、変化前のHPなどを変数に入れておいてそれらに変化があったらrefreshを呼ぶくらいですが、このような方法で解決するのも一つの手でしょうか?
それも一つの方法ですね。
Sprite_Timerなんかでもupdate内で状態変化をチェックして適宜redrawしています。

他にもScene_Battleに関連づけるのではなく
Window_BattleStatusに関連付けてrefreshを同期させる方法もあります。
まぁ、Teki_Infoと不揃いになるので今回は使用しなくても良いと思いますけど。

コード: 全て選択

const _Window_BattleStatus_initialize = Window_BattleStatus.prototype.initialize;
Window_BattleStatus.prototype.initialize = function() {
    _Window_BattleStatus_initialize.apply(this, arguments);
    this._playerInfoWindow = new PlayerInfo();
    this.addChild(this._playerInfoWindow);
    this.refresh();
};

const _Window_BattleStatus_refresh = Window_BattleStatus.prototype.refresh;
Window_BattleStatus.prototype.refresh = function() {
    _Window_BattleStatus_refresh.aplly(this, arguments);
    if ( this._playerInfoWindow ) this._playerInfoWindow.setText();
};
ステータスウィンドウは体力、元素力だけでなく
バフ/デバフの影響で攻魔敏運も変動する事を想定しているんですかね?
とりあえず名前とレベルは変わらないと思うのでこれはinialize時に描画。
他、戦闘中に変わる部分に関してはbitmap.clear()を使わず
clearRect(x, y, width, height)を使って部分的に変更して描画回数を減らしても良いかもしれません。

まぁ、ここまで削らなくても毎フレーム描画処理をやめれば及第点だと思いますね。
これで重くなるようなら他の部分に問題があります。
Arkroyal さんが書きました:指摘してくださった部分ですが、Scene_Battle.prototype.refreshStatusやBattleManager.refreshStatusなどを調べたところ「どうやって変化を感知するのか」がさっぱりわかりませんでした……。よろしければこの部分についてもっと詳しく教えてくだされば大変助かります
うーんかなり面倒臭いですね。
変化を感知というか変化が発生し得る箇所で呼んでるだけだと思います。
rpg_managers.jsの2442,2456,2515,2544行目ですか。ついでにrpg_scenes.jsの2464。
行動終了後やターン終了処理後にとりあえず呼び出してるんですけど
厳密にはコアスクリプトも一部、過剰に呼び出してる部分もあって完璧ではないんですよね。

例えば昔から言われてる問題部分だとrpg_managers.jsの2456行目。
バトルメンバーの人数だけthis.refreshStatus();を繰り返しているけど
一回のリフレッシュで全メンバー分更新するので人数分繰り返すのはどう考えてもリソースの無駄なんです。
まぁ、値の変化するタイミングを知り尽くして適宜リフレッシュする、
というのは実際難しいのでそこまでこだわらなくても良いと思います。
Arkroyal
記事: 80
登録日時: 2021年1月06日(水) 10:41

Re: バトル画面に新しくステータスウィンドウを作るのは危険でしょうか?

投稿記事 by Arkroyal »

ステータスウィンドウは体力、元素力だけでなく
バフ/デバフの影響で攻魔敏運も変動する事を想定しているんですかね?
とりあえず名前とレベルは変わらないと思うのでこれはinialize時に描画。
他、戦闘中に変わる部分に関してはbitmap.clear()を使わず
clearRect(x, y, width, height)を使って部分的に変更して描画回数を減らしても良いかもしれません。

まぁ、ここまで削らなくても毎フレーム描画処理をやめれば及第点だと思いますね。
これで重くなるようなら他の部分に問題があります。
はい、その通りです。変わらない部分はInitializeへ置くこと。畏まりました!

clearrectはウィンドウにおいて指定した部分のみ更新を行う方法なんでしょうか?こういうのもあったんですね。フレームごとに更新される項目(または領域)を減らすことでダメだったら自動更新の方をいじるべきでしょうか……。


うーんかなり面倒臭いですね。
変化を感知というか変化が発生し得る箇所で呼んでるだけだと思います。
rpg_managers.jsの2442,2456,2515,2544行目ですか。ついでにrpg_scenes.jsの2464。
行動終了後やターン終了処理後にとりあえず呼び出してるんですけど
厳密にはコアスクリプトも一部、過剰に呼び出してる部分もあって完璧ではないんですよね。
なるほど……turnendやinvokeactionなどの時に行われたのはその理由だったんですね!勉強になりました!
最後に編集したユーザー Arkroyal [ 2021年9月01日(水) 02:44 ], 累計 1 回
返信する

“MV:質問”に戻る