RPGツクールMVにおける外部ファイルの読み込みについて

返信する
タツノコ
記事: 20
登録日時: 2020年6月15日(月) 19:07
連絡する:

RPGツクールMVにおける外部ファイルの読み込みについて

投稿記事 by タツノコ »

初めまして
タツノコと申します。

RPGツクールMVのスクリプトにて
外部ファイル(CSVファイル)を読み込みしたいと思っております。

以下のロジックで記載したのですが、
ファイルから読み込めたはずの文字列が変数に入っておりませんでした。

【質問させていただきたいこと】
  test.csvから読み込んだ文字列を$testMessageに入れる手段

【前提】
  ・window_test_wind→Window_Selectableを継承したクラスです。
             loadCsvの関数が呼ばれていることは確認済みです。(掲示板が長くなるといけないので、ピンポイントで記載させていただきました。
  ・test.csvは「/db」フォルダにあります。

【気になったこと】
  ・Scene_XX.prototype.initializeで以下の「loadCsvFile」を呼び出した場合
   Scene_XX.prototype.create内で「$testMessage」を参照したところ、
   中身がnullになってませんでした。(読み込めてました)
  ・Scene_XX.prototype.initialize内で、で以下の「loadCsvFile」を呼び出し
   同じScene_XX.prototype.initialize内で「$testMessage」を参照したところ
   nullのままでした
【対象のソースコード】

コード: 全て選択

   var $testMessage = null;
   (function(){
    function loadCSVFile(name, src) {
        var xhr = new XMLHttpRequest();
        var url = 'db/' + src;
        xhr.open('GET', url);
        xhr.overrideMimeType('text/plain; charset=utf-8');
        xhr.onload = function() {
            if (xhr.status < 400) {
                window[name] = xhr.responseText;
            }
        };
        xhr.onerror = DataManager._mapLoader || function() {
            DataManager._errorUrl = DataManager._errorUrl || url;
        };
        window[name] = null;
        xhr.send();
    };
    
    window_test_wind.prototype.loadCsv(){
         loadCSVFile('$testMessage','test.csv');
         while($testMessage == null){}
         alert($testMessage);
    }
)
仕組みを理解してないままの質問になってしまい申し訳ございません。
もしかしたら既出の質問かもしれませんが
何卒よろしくお願いいたします。

以上です。
アバター
トリアコンタン
記事: 2311
登録日時: 2015年11月10日(火) 21:13
お住まい: きのこ王国
連絡する:

Re: RPGツクールMVにおける外部ファイルの読み込みについて

投稿記事 by トリアコンタン »

こんにちは!
すべての処理を見ていないので正確なことは言えませんが、
XMLHttpRequestは非同期処理なので、initializeで読み込み開始したファイルを同じメソッドで読み込み完了まで強引に待機するのは元々難しいと思います。

実装案

コード: 全て選択

var $testMessage = null;

(function() {
    'use strict';

    function loadCSVFile(name, src) {
        var xhr = new XMLHttpRequest();
        var url = 'db/' + src;
        xhr.open('GET', url);
        xhr.overrideMimeType('text/plain; charset=utf-8');
        xhr.onload = function() {
            if (xhr.status < 400) {
                window[name] = xhr.responseText;
            }
        };
        xhr.onerror = DataManager._mapLoader || function() {
            DataManager._errorUrl = DataManager._errorUrl || url;
        };
        window[name] = null;
        xhr.send();
    };

    function window_test_wind() {
        this.initialize.apply(this, arguments);
    }

    window_test_wind.prototype             = Object.create(Window_Selectable.prototype);
    window_test_wind.prototype.constructor = window_test_wind;

    window_test_wind.prototype.initialize = function(x, y, width, height){
        Window_Selectable.prototype.initialize.apply(this, arguments);
    };

    window_test_wind.prototype.loadCsv = function(){
        loadCSVFile('$testMessage','test.csv');
        // XMLHttpRequestによるファイル読み込みは非同期なので無理やり処理を止めることはできません。
        //while($testMessage == null){}
    };

    var _Scene_Map_initialize = Scene_Map.prototype.initialize;
    Scene_Map.prototype.initialize = function() {
        _Scene_Map_initialize.apply(this, arguments);
        this._testWin = new window_test_wind();
        this._testWin.loadCsv();
    };

    var _Scene_Map_isReady = Scene_Map.prototype.isReady;
    Scene_Map.prototype.isReady = function() {
        // このメソッドで読み込み完了まで待機します。
        return _Scene_Map_isReady.apply(this, arguments) && !!$testMessage;
    };

    var _Scene_Map_create = Scene_Map.prototype.create;
    Scene_Map.prototype.create = function() {
        _Scene_Map_create.apply(this, arguments);
        console.log($testMessage);
    };
})();
プラグイン関連のトラブルが発生した際の切り分けと報告の方法です。
http://qiita.com/triacontane/items/2e227e5b5ce9503a2c30

[Blog] : http://triacontane.blogspot.jp/
[Twitter]: https://twitter.com/triacontane/
[GitHub] : https://github.com/triacontane/
タツノコ
記事: 20
登録日時: 2020年6月15日(月) 19:07
連絡する:

Re: RPGツクールMVにおける外部ファイルの読み込みについて

投稿記事 by タツノコ »

トリアコンタン様
タツノコです。

ご回答ありがとうございます。
なるほど、そうだったんですね。
メソッドを跨がないで読み込むというのは難しいんですね。。。(非同期通信ということで、待機していたら
そのうちレスポンスが返ってくるのかなと思っておりました。)
そして、実装案もいただきありがとうございます!


尚、似たような質問になってしましますが、
Scene_XXXクラス(Scenen_系統のクラスを継承したクラス)内のメソッドおよび
Window_XXX(Window_系統のクラスを継承したクラス)内のメソッドでも
考え方は上記と同じという認識を持ちましたが、あっておりますでしょうか・・・?
(「Window_XXXクラス内のメソッドでファイル読み込みをしたい場合は、メソッドを跨がないと取れない。」という認識。)

連続で質問をしてしまい申し訳ございません。
何卒、よろしくお願いいたします。

以上です。
アバター
トリアコンタン
記事: 2311
登録日時: 2015年11月10日(火) 21:13
お住まい: きのこ王国
連絡する:

Re: RPGツクールMVにおける外部ファイルの読み込みについて

投稿記事 by トリアコンタン »

こんにちは!

メソッドを跨ぐかそうでないかがポイントではなく、ロード開始から時間が経過しているかどうかがポイントとなります。ただし、具体的に何秒かは分かりません。

そこで、『isReady』というメソッドが役に立ちます。
このメソッドは、シーン遷移時に毎フレーム呼ばれ、シーンを開始するために必要なロードがすべて完了しているかどうかをチェックします。
このメソッドがtrueを返すとシーン開始の準備が整ったとコアスクリプトが判断するので、実装案ではここに『!!$testMessage;』を追加しています。
プラグイン関連のトラブルが発生した際の切り分けと報告の方法です。
http://qiita.com/triacontane/items/2e227e5b5ce9503a2c30

[Blog] : http://triacontane.blogspot.jp/
[Twitter]: https://twitter.com/triacontane/
[GitHub] : https://github.com/triacontane/
タツノコ
記事: 20
登録日時: 2020年6月15日(月) 19:07
連絡する:

Re: RPGツクールMVにおける外部ファイルの読み込みについて

投稿記事 by タツノコ »

トリアコンタン様
お世話になっております。
タツノコです。

ポイントについて承知いたしました!
whileでnullチェックを回してても、nullから変わらずというところで
関数をまたぐことがポイントだと勘違いしておりました。(すみません!)

isReadyについてもご解説ありがとうございます!
iReadyをオーバライドし、元の関数(isReady)も呼び出しつつ、同じ条件に読み込みが完了(この場合$testMessageに値が入ること)した場合に処理続行し、
以降の処理を行うときに読み込みが終わっていないことを防ぐという点について理解いたしました!
(認識が間違えていたら申し訳ございません)

ご丁寧に解説いただき本当にありがとうございます!
返信する

“MV:質問”に戻る