RPGツクールMV
一人輪読会
ゲーム起動~Scene_Title呼び出しまでの流れ
@rinne_grid
目的
 ツクールMVの内部処理(rpg_objects.jsやrpg_core.js、rpg_scenes.js)で何を
やっているのか理解する
 個人的に気になるソースコードを探す
 今回
 ゲーム開始~Scene_Title呼び出しまでの流れについて調べて、アウトプット
Sceneに関係するメソッドの呼び出し順序
 1. initialize, 2.create, 3.start
 initializeは、SceneManager.goto内で、シーンオブジェクトが生成されたタイミング
で呼ばれる
 createは、SceneManager.changeSceneで、シーンが切り替わる時に呼ばれる
 startは、SceneManager.updateSceneで、シーンが開始されておらず、準備完了と
なった時点で呼ばれる
 SceneManager.updateはpixi.jsの関数(requestAnimationFrame)のコールバッ
クとして渡される。これを渡すことで、定期的にupdateを実行している
main.js
rpg_managers.js
rgs_scenes.js
・PluginManagerのセットアップ
・Scene_Bootの呼び出し
・SceneManager各種動作
・DataManager各種動作
・ConfigManager各種動作
・Scene_Boot
・Scene_Title
main.js
// 5行目
PluginManager.setup($plugins);
// 7行目
window.onload = function() {
SceneManager.run(Scene_Boot);
};
rpg_managers.js
// 1470行目
SceneManager.run = function(sceneClass) {
try {
this.initialize(); // ★A
this.goto(sceneClass); // ★B
this.requestUpdate(); // ★C
} catch (e) {
this.catchException(e);
}
};
rpg_managers.js
★A
// 1480行目
SceneManager.initialize = function() {
this.initGraphics();
this.checkFileAccess();
this.initAudio();
this.initInput();
this.initNwjs();
this.checkPluginErrors();
this.setupErrorHandlers();
};
this.initGraphics() : Graphicsの初期化
this.checkFileAccess() : index.htmlにおける、js/libs/pixi.jsから、js/main.jsまでを
getElementsByTagNameで取得し、XMLHttpRequestで取得確認をする
this.initAudio() : Web Audio APIがブラウザで使えるかどうか判断
this.initInput() : 入力関係の初期化(Input、TouchInput)
this.initNwjs() : Nw.jsの初期化
this.checkPluginErrors() : プラグインのエラーチェック。PluginManagerでエラーが発生した時点で、
_errorUrls配列に対象スクリプトのURLを格納している
this.setupErrorHandlers() : errorイベントが発生したら、SceneMangaer.onErrorが発火するように設定
keydownイベントが発生したら、SceneManager.onKeyDownが発火するように設定
rpg_managers.js
★B
// 1718行目
SceneManager.goto = function(sceneClass) {
if (sceneClass) {
this._nextScene = new sceneClass();
}
if (this._scene) {
this._scene.stop();
}
};
渡されたSceneクラス(Scene_Boot)のオブジェクトを生成
rpg_scenes.js
// 155行目
Scene_Boot.prototype.initialize = function() {
Scene_Base.prototype.initialize.call(this);
this._startDate = Date.now();
};
// Scene_Bootの初期化と開始日付の設定
rpg_manager.js
★C
// 1566行目
SceneManager.requestUpdate = function() {
if (!this._stopped) {
requestAnimationFrame(this.update.bind(this));
}
};
// SceneManager.updateをコールバックとして、requestAnimationFrameに渡す
// これで定期的にupdateが実行されるようになる
rpg_manager.js
// 1572行目
SceneManager.update = function() {
try {
this.tickStart();
this.updateInputData();
this.updateMain(); // ★D
this.tickEnd();
} catch (e) {
this.catchException(e);
}
};
this.updateMainの呼び出し
rpg_manager.js
★D
// 1639行目
SceneManager.updateMain = function() {
this.changeScene(); // ★E
this.updateScene(); // ★E’
this.renderScene();
this.requestUpdate();
};
rpg_manager.js
★E
SceneManager.changeScene = function() {
if (this.isSceneChanging() && !this.isCurrentSceneBusy()) {
if (this._scene) {
this._scene.terminate();
this._previousClass = this._scene.constructor;
}
this._scene = this._nextScene;
if (this._scene) {
this._scene.create();
…
// this._sceneには何も入っていない。Sceneも変更中ではないので、if文はスルー
// this._nextSceneにはScene_Baseのオブジェクトが入っている
// ここでようやく、Scene_Baseのcreateメソッドが呼ばれる
rpg_scenes.js
// 160行目
Scene_Boot.prototype.create = function() {
Scene_Base.prototype.create.call(this);
DataManager.loadDatabase(); // ★F
ConfigManager.load(); // ★G
this.loadSystemImages(); // ★H
};
rpg_managers.js
★F
// 65行目
DataManager.loadDatabase = function() {
var test = this.isBattleTest() || this.isEventTest();
var prefix = test ? 'Test_' : '';
for (var i = 0; i < this._databaseFiles.length; i++) {
var name = this._databaseFiles[i].name;
var src = this._databaseFiles[i].src;
this.loadDataFile(name, prefix + src);
}
…
rpg_managers.js
// 78行目
DataManager.loadDataFile = function(name, src) {
var xhr = new XMLHttpRequest();
var url = 'data/' + src;
xhr.open('GET', url);
xhr.overrideMimeType('application/json');
xhr.onload = function() {
if (xhr.status < 400) {
window[name] = JSON.parse(xhr.responseText);
DataManager.onLoad(window[name]);
}
};
xhr.onerror = function() {
DataManager._errorUrl = DataManager._errorUrl || url;
};
window[name] = null;
xhr.send();
};
// jsonファイルの読み込み、Gameオブジェクトを作成
// 例によって、エラーが発生したjsonは、_errorUrls配列に格納される
rpg_managers.js
★G
// 503行目
ConfigManager.load = function() {
var json;
var config = {};
try {
json = StorageManager.load(-1);
} catch (e) {
console.error(e);
}
…
// config.rpgsaveの存在確認
// ローカルファイルか、Webストレージかによってパラメーターが異なる
rpg_scenes.js
★H
// 167行目
Scene_Boot.prototype.loadSystemImages = function() {
ImageManager.loadSystem('Window');
ImageManager.loadSystem('IconSet');
ImageManager.loadSystem('Balloon');
ImageManager.loadSystem('Shadow1');
ImageManager.loadSystem('Shadow2');
ImageManager.loadSystem('Damage');
ImageManager.loadSystem('States');
ImageManager.loadSystem('Weapons1');
ImageManager.loadSystem('Weapons2');
ImageManager.loadSystem('Weapons3');
ImageManager.loadSystem('ButtonSet');
};
// 各アイコンファイルを取得
rpg_managers.js
★E’
// 1665行目
SceneManager.updateScene = function() {
if (this._scene) {
if (!this._sceneStarted && this._scene.isReady()) {
this._scene.start();
this._sceneStarted = true;
this.onSceneStart();
}
if (this.isCurrentSceneStarted()) {
this._scene.update();
}
}
};
// this._sceneがnullではなく、まだ開始されていないので、startする(Scene_Boot)
rpg_scenes.js
// 200行目
Scene_Boot.prototype.start = function() {
Scene_Base.prototype.start.call(this);
SoundManager.preloadImportantSounds();
if (DataManager.isBattleTest()) {
DataManager.setupBattleTest();
SceneManager.goto(Scene_Battle);
} else if (DataManager.isEventTest()) {
DataManager.setupEventTest();
SceneManager.goto(Scene_Map);
} else {
this.checkPlayerLocation();
DataManager.setupNewGame();
SceneManager.goto(Scene_Title);
Window_TitleCommand.initCommandPosition();
}
this.updateDocumentTitle();
};
// バトルテスト、イベントテストではないので、
// プレイヤーの初期位置を確認し、Scene_Titleを呼び出す

【ツクールMV】ゲーム開始~Scene_Title呼び出しまでの流れ(一人輪読会)