そもそも私がこの記事を書こうと思ったのは、公式フォーラムで見たとある質問が切っ掛けになっております。
◆スクリプト:$gameMessage.add('aaaa');
: :this.setWaitMode('message');
◆スクリプト:AudioManager.playSe({name:'Attack1', volume:90, pitch:100, pan:0})
↓
何故スクリプトを分けるとsetWaitModeが機能するのかさっぱり分かりませんが、とにかくありがとうございました。
ここら辺の仕組み、あまり解説している所ないよな…
しかも、これってツクールの根幹を理解するのに良い機会だよな…
と考え、この記事を建てました。
#そもツクールMVはどうやって「動いて」いるのか?
大元を辿れば、メインとなるループはSceneManager.update
です。
この中で更にSceneManager.updateMain
→ SceneManager.requestUpdate
を経て、pixiのrequestAnimationFrame
により次のフレームで再度SceneManager.update
が呼び出されます。
このSceneManager.updateMain
の中にはSceneManager.updateScene
があり、各Scene(Scene_Map/Scene_Battle等)のprototype.updateに繋がります。
#setWaitModeがしている事
前述の通り、Scene_Mapの場合、Scene_Map.prototype.update
が呼び出され、その中にはイベントコマンドをコントロールするGame_Interpreterのupdateも、Scene_Map.prototype.updateMainMultiply
→ Scene_Map.prototype.updateMain
→ Game_Map.prototype.update
→ Game_Map.prototype.updateInterpreter
を経由して呼び出されてます。
Game_Interpreter.prototype.update = function() {
while (this.isRunning()) {
if (this.updateChild() || this.updateWait()) {
break;
}
if (SceneManager.isSceneChanging()) {
break;
}
if (!this.executeCommand()) {
break;
}
if (this.checkFreeze()) {
break;
}
}
これを見ると分かる通り、Game_Interpreter.prototype.updateWait
がtrueを返した場合、breakが発生し次のコマンドを実行するだろうGame_Interpreter.prototype.executeCommand
は実行されません。
そして――
Game_Interpreter.prototype.updateWaitMode = function() {
var waiting = false;
switch (this._waitMode) {
case 'message':
waiting = $gameMessage.isBusy();
break;
case 'transfer':
waiting = $gamePlayer.isTransferring();
break;
case 'scroll':
waiting = $gameMap.isScrolling();
break;
case 'route':
waiting = this._character.isMoveRouteForcing();
break;
case 'animation':
waiting = this._character.isAnimationPlaying();
break;
case 'balloon':
waiting = this._character.isBalloonPlaying();
break;
case 'gather':
waiting = $gamePlayer.areFollowersGathering();
break;
case 'action':
waiting = BattleManager.isActionForced();
break;
case 'video':
waiting = Graphics.isVideoPlaying();
break;
case 'image':
waiting = !ImageManager.isReady();
break;
}
if (!waiting) {
this._waitMode = '';
}
return waiting;
};
こちらで分かる通り、_waitmodeに値がセットされていると、相応のパラメータをチェックし、まだ終わっていない場合は次のイベントコマンドに進まない仕組みになっております。
#結局何故スクリプトの中でsetWaitModeをセットしても次の行(スクリプト)が実行されてしまうのか
上記から分かる通り、waitmodeはあくまでも「一つのイベントコマンドから次のイベントコマンドに進むのを止める」効果を発揮してます。
同じスクリプトコマンドの中で改行しても、それは結局同じイベントコマンドの中身であり、それ故にwaitmodeは効果を発揮しません。
逆にスクリプトを別々のイベントコマンドに分けた場合、上記の通り、次のスクリプトイベントコマンドに進む事がupdateWaitmodeによって阻まれ、3行目相当のAudioManager.playSe({name:'Attack1', volume:90, pitch:100, pan:0})
は実行されない…と言う事ですね。