//============================================================================= // ParallelPreload.js // ---------------------------------------------------------------------------- // Copyright (c) 2015 Triacontane // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // ---------------------------------------------------------------------------- // Version // 2.0.3 2017/12/21 最新のコアスクリプトで正常に画像が表示されない場合があるため利用を非推奨とします。 // 2.0.2 2017/06/18 本体v1.5.0で機能しなくなる問題に対応(by 奏ねこま様) // 2.0.1 2017/05/27 競合の可能性のある記述(Objectクラスへのプロパティ追加)をリファクタリング // 2.0.0 2016/08/05 本体v1.3.0対応(1.2.0では使えなくなります) // 素材のプリロード時に発生するエラー(対象が存在しない等)を抑制するよう仕様変更 // 1.1.2 2016/07/23 コードのリファクタリングとヘルプの修正 // 1.1.1 2016/04/29 ログ出力を無効化するパラメータを追加 // 1.1.0 2016/04/28 音声素材の並列プリロードに対応 // 他のプラグインの影響等で、特定のシーンでプリロードが止まってしまう問題を修正 // 1.0.1 2016/04/25 色相が0以外の画像がすべて0で表示されてしまう問題を修正 // 色相に関する制約の説明を追加 // ブラウザプレー時、戦闘アニメの表示速度が著しく低下する問題を修正 // バトルテストとイベントテストが実行できなくなる問題を修正 // 1.0.0 2016/04/23 初版 // ---------------------------------------------------------------------------- // [Blog] : http://triacontane.blogspot.jp/ // [Twitter]: https://twitter.com/triacontane/ // [GitHub] : https://github.com/triacontane/ //============================================================================= /*: @url https://triacontane.blogspot.com/ @plugindesc Parallel Preload Plugins @author Triacontane @license MIT License @help English Help Translator: munokura This is an unofficial English translation of the plugin help, created to support global RPG Maker users. Feedback is welcome to improve translation quality (see: https://github.com/munokura/triacontane-MV-plugins ). Original plugin by Triacontane. Please check the latest official version at: https://triacontane.blogspot.com ----- This plugin will remain available, but its use is not recommended due to some images not displaying properly in the latest core script. This plugin was created because the core script at one time did not have a preload function. However, since the release of the open-source version, the core script has implemented appropriate image loading and discarding functions, so this plugin has been deemed to have served its purpose. ------------------------------------------------------------------------- Image materials are loaded in parallel at game start. Designed to distribute and reduce load as much as possible. To list the materials to be loaded, please use the "Material List JSON Creation Program" created by fftfantt. (MIT License as of April 28, 2016) Create a JSON file containing a list of required materials from this program, named "MV_Project.json," and place it under "/data". When creating the file, be sure to uncheck "Add extension". ・How to Use https://github.com/fftfantt/RPGMakerMV/wiki/JSON_Maker_for_MV ・Mainframe https://raw.githubusercontent.com/fftfantt/RPGMakerMV/master/JSON_Maker_for_MV.zip When running from a browser, the plugin waits for one image to finish loading before beginning to load the next. Therefore, specifying a large number of images will take longer to complete loading, reducing the effectiveness of this plugin. When playing in Chrome, loading a large number of images will significantly slow down the game's performance. (This is a core issue that occurs after a certain period of play even without this plugin.) In this case, please install a workaround plugin as described below. (For mainframe version 1.2.0) http://fanblogs.jp/tabirpglab/archive/422/0 Only image data with a hue of 0 can be preloaded. If you absolutely must load images with a different hue, you will need to edit the relevant section of "MV_Project.json" directly as follows: Example: To preload "Bat.png" with a hue of "100", use the following syntax: "Bat" -> "Bat:100" Caution! Playing games using this plugin on a mobile network may result in significant data usage. Please warn users if necessary. Terms of Use: You may modify and redistribute this plugin without permission from the author, and there are no restrictions on its use (commercial, 18+, etc.). This plugin is now yours. @param 素材一覧データ @text Material list data @desc The name of the JSON file to be placed under "/data" @default MV_Project @param ロード間隔 @text Load Interval @desc The interval (in frames) between file loads. If you set it to 0, the game will start after loading everything. (Except when using a browser) @default 0 @param ログ出力 @text Log Output @desc Outputs the loaded file path to the log (only during test play). @default OFF */ /*:ja @plugindesc 並列プリロードプラグイン @author トリアコンタン @param 素材一覧データ @desc 「/data」以下に配置するJSONファイル名 @default MV_Project @param ロード間隔 @desc ファイルをロードする間隔(フレーム単位)です。0に指定すると全てロードしてからゲーム開始します。(ブラウザ時は除く) @default 0 @param ログ出力 @desc ロードしたファイルパスをログに出力します。(テストプレー時のみ) @default OFF @help 本プラグインは、最新のコアスクリプトで一部画像が正常に表示されないため 公開は停止しませんが、利用を非推奨とします。 一時期のコアスクリプトにはプリロード機能がなかったため本プラグインを 作成しましたが、OSS版の導入以後はコアスクリプト側で適切な 画像の読み込みと破棄の機能が実装されたため、当プラグインは 役割を終えたものと判断します。 ------------------------------------------------------------------------- ゲーム開始時に画像素材を並列ロードします。 可能な限り負荷を分散、軽減するように設計されています。 ロードする素材の一覧はfftfantt氏制作の「素材一覧用JSON作成プログラム」を 使用してください。(2016/04/28時点でMITライセンス) 同プログラムから必要な素材の一覧が作成されたJSONファイル 「MV_Project.json」を作成して「/data」以下に配置します。 作成する際は、「拡張子をつける」チェックを外してください。 ・使い方 https://github.com/fftfantt/RPGMakerMV/wiki/JSON_Maker_for_MV ・本体 https://raw.githubusercontent.com/fftfantt/RPGMakerMV/master/JSON_Maker_for_MV.zip ブラウザから実行する場合、画像のロードが完了してから次のロードを開始します。 そのため、大量の画像を指定するとロード完了までに時間が掛かり 効果が薄くなります。 chromeでプレーする場合、大量に画像をロードすると処理速度が著しく低下します。 (本プラグインなしでも一定時間プレーすると発生する本体側の問題です) その場合、下記を参考に対策プラグインの導入をお願いします。(本体ver1.2.0の場合) http://fanblogs.jp/tabirpglab/archive/422/0 プリロードできるのは、色相が0の画像データのみです。 どうしても色相を変えた画像をロードしたい場合は「MV_Project.json」を 該当箇所を以下の通り直接編集する必要があります。 例:色相が「100」の「Bat.png」をプリロードしたい場合 "Bat" -> "Bat:100" 注意! このプラグインを適用したゲームをモバイルネットワークでプレーすると、 通信量が膨大になる恐れがあります。必要に応じて注意喚起ください。 利用規約: 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) についても制限はありません。 このプラグインはもうあなたのものです。 */ var $dataMaterials = null; (function () { 'use strict'; var pluginName = 'ParallelPreload'; var getParamString = function (paramNames) { var value = getParamOther(paramNames); return value === null ? '' : value; }; var getParamNumber = function (paramNames, min, max) { var value = getParamOther(paramNames); if (arguments.length < 2) min = -Infinity; if (arguments.length < 3) max = Infinity; return (parseInt(value, 10) || 0).clamp(min, max); }; var getParamBoolean = function (paramNames) { var value = getParamOther(paramNames); return (value || '').toUpperCase() === 'ON'; }; var getParamOther = function (paramNames) { if (!Array.isArray(paramNames)) paramNames = [paramNames]; for (var i = 0; i < paramNames.length; i++) { var name = PluginManager.parameters(pluginName)[paramNames[i]]; if (name) return name; } return null; }; var iterate = function (that, handler) { Object.keys(that).forEach(function (key, index) { handler.call(that, key, that[key], index); }); }; //============================================================================= // パラメータの取得と整形 //============================================================================= var paramMaterialListData = getParamString(['MaterialListData', '素材一覧データ']) + '.json'; var paramLoadInterval = getParamNumber(['LoadInterval', 'ロード間隔']); var paramOutputLog = getParamBoolean(['OutputLog', 'ログ出力']); var localLoadComplete = false; var localIntervalCount = 0; //============================================================================= // DataManager // ロード対象素材スタックの作成を追加定義します。 //============================================================================= DataManager._databaseFiles.push( { name: '$dataMaterials', src: paramMaterialListData } ); DataManager.materialFilePaths = null; var _DataManager_loadDataFile = DataManager.loadDataFile; DataManager.loadDataFile = function (name, src) { if (name === '$dataMaterials' && (this.isBattleTest() || this.isEventTest())) { arguments[1] = paramMaterialListData; } _DataManager_loadDataFile.apply(this, arguments); }; var _DataManager_onLoad = DataManager.onLoad; DataManager.onLoad = function (object) { _DataManager_onLoad.apply(this, arguments); if (object === $dataMaterials) { this.initParallelPreload(); } }; DataManager.initParallelPreload = function () { this.materialFilePaths = []; iterate($dataMaterials, function (key, value) { for (var i = 0, n = value.length; i < n; i++) { this.materialFilePaths.push([key, value[i]]); } }.bind(this)); }; DataManager.loadMaterial = function () { var filePathInfo = this.materialFilePaths.shift(); if (filePathInfo) { if (Utils.isOptionValid('test') && paramOutputLog) { console.log('Load material : ' + filePathInfo[0] + '/' + filePathInfo[1]); } var loadImageHandler = ImageManager.loadHandlers[filePathInfo[0]]; if (loadImageHandler) this.loadImage(loadImageHandler, filePathInfo); var loadAudioHandler = AudioManager.loadHandlers[filePathInfo[0]]; if (loadAudioHandler) this.loadAudio(loadAudioHandler, filePathInfo); } else { localLoadComplete = true; } }; DataManager.loadImage = function (loadHandler, filePathInfo) { var key = filePathInfo[1].split(':'); var hue = key.length > 1 ? parseInt(key[1], 10) : 0; var bitmap = ImageManager[loadHandler](key[0], hue); if (bitmap.isReady()) return; bitmap._isNeedLagDraw = true; bitmap._lagDrawHue = hue; if (Utils.isNwjs()) { localIntervalCount = paramLoadInterval; } else { localIntervalCount = Infinity; bitmap.addLoadListener(function () { localIntervalCount = paramLoadInterval; }.bind(this)); } }; DataManager.loadAudio = function (loadHandler, filePathInfo) { if (AudioManager.shouldUseHtml5Audio()) return; var audio = AudioManager[loadHandler](filePathInfo[0], filePathInfo[1]); if (Utils.isNwjs()) { localIntervalCount = paramLoadInterval; } else { localIntervalCount = Infinity; audio.addLoadListener(function () { localIntervalCount = paramLoadInterval; }.bind(this)); } }; //============================================================================= // SceneManager // ロード処理を実行します。 //============================================================================= var _SceneManager_updateScene = SceneManager.updateScene; SceneManager.updateScene = function () { _SceneManager_updateScene.apply(this, arguments); if (!localLoadComplete && DataManager.materialFilePaths) this.updateParallelPreload(); }; SceneManager.updateParallelPreload = function () { while (localIntervalCount <= 0 && !localLoadComplete) { DataManager.loadMaterial(); } localIntervalCount--; }; //============================================================================= // ImageManager // ロード処理を実行します。 //============================================================================= ImageManager.loadHandlers = { animations: 'loadAnimation', battlebacks1: 'loadBattleback1', battlebacks2: 'loadBattleback2', enemies: 'loadEnemy', characters: 'loadCharacter', faces: 'loadFace', parallaxes: 'loadParallax', pictures: 'loadPicture', sv_actors: 'loadSvActor', sv_enemies: 'loadSvEnemy', system: 'loadSystem', tilesets: 'loadTileset', titles1: 'loadTitle1', titles2: 'loadTitle2' }; var _ImageManager_loadNormalBitmap = ImageManager.loadNormalBitmap; ImageManager.loadNormalBitmap = function (path, hue) { var bitmap = _ImageManager_loadNormalBitmap.apply(this, arguments); if (!bitmap.isReady()) bitmap._isNeedLagDraw = false; return bitmap; }; var _ImageManager_isReady = ImageManager.isReady; ImageManager.isReady = function () { var result = _ImageManager_isReady.apply(this, arguments); if (result) return true; for (var key in this.cache._inner) { if (!this.cache._inner.hasOwnProperty(key)) continue; var bitmap = this.cache._inner[key].item; if (!bitmap.isReady() && !bitmap._isNeedLagDraw) { return false; } } return true; }; var _ImageManager_isReady2 = ImageManager.isReady; ImageManager.isReady = function () { var result = false; try { result = _ImageManager_isReady2.apply(this, arguments); } catch (e) { for (var key in this.cache._inner) { if (!this.cache._inner.hasOwnProperty(key)) continue; var bitmap = this.cache._inner[key].item; if (bitmap.isError() && bitmap._isNeedLagDraw) { bitmap.eraseError(); delete this.cache._inner[key]; } } result = _ImageManager_isReady2.apply(this, arguments); } return result; }; //============================================================================= // AudioManager // ロード用のメソッド名を定義します。 //============================================================================= AudioManager.loadHandlers = { bgm: 'createBuffer', bgs: 'createBuffer', se: 'createBuffer', me: 'createBuffer' }; //============================================================================= // Bitmap // ロードと描画のタイミングを分離します。 //============================================================================= var _Bitmap__onLoad = Bitmap.prototype._onLoad; Bitmap.prototype._onLoad = function () { if (!this._isNeedLagDraw) { _Bitmap__onLoad.apply(this, arguments); } else { this._isLoading = false; this._loadingState = 'loaded'; // added by nekoma. this.resize(this._image.width, this._image.height); this._callLoadListeners(); } }; Bitmap.prototype.drawImage = function () { this._context.drawImage(this._image, 0, 0); if (this._lagDrawHue !== 0) { this.rotateHue(this._lagDrawHue); } this._setDirty(); this._isNeedLagDraw = false; }; Bitmap.prototype.drawImageIfNeed = function () { if (this._isNeedLagDraw) { if (this.isReady()) { this.drawImage(); } else { this._isNeedLagDraw = false; } } }; var _Bitmap_blt = Bitmap.prototype.blt; Bitmap.prototype.blt = function (source, sx, sy, sw, sh, dx, dy, dw, dh) { source.drawImageIfNeed(); _Bitmap_blt.apply(this, arguments); }; var _Bitmap_bltImage = Bitmap.prototype.bltImage; Bitmap.prototype.bltImage = function (source, sx, sy, sw, sh, dx, dy, dw, dh) { source.drawImageIfNeed(); _Bitmap_bltImage.apply(this, arguments); }; Bitmap.prototype.eraseError = function () { this._hasError = false; this._isLoading = false; this._loadingState = 'none'; // added by nekoma. }; //============================================================================= // Sprite // Bitmapのロード完了時に描画処理を実行します。 //============================================================================= var _Sprite__onBitmapLoad = Sprite.prototype._onBitmapLoad; Sprite.prototype._onBitmapLoad = function () { if (this._bitmap) this._bitmap.drawImageIfNeed(); _Sprite__onBitmapLoad.apply(this, arguments); }; //============================================================================= // TilingSprite // Bitmapのロード完了時に描画処理を実行します。 //============================================================================= var _TilingSprite__onBitmapLoad = TilingSprite.prototype._onBitmapLoad; TilingSprite.prototype._onBitmapLoad = function () { if (this._bitmap) this._bitmap.drawImageIfNeed(); _TilingSprite__onBitmapLoad.apply(this, arguments); }; //============================================================================= // Spriteset_Map // タイルセットはすぐに描画します。 //============================================================================= var _Spriteset_Map_loadTileset = Spriteset_Map.prototype.loadTileset; Spriteset_Map.prototype.loadTileset = function () { _Spriteset_Map_loadTileset.apply(this, arguments); if (this._tileset) { this._tilemap.bitmaps.forEach(function (bitmap) { bitmap.drawImageIfNeed(); }); } }; })();